シミュレーションおよびコード実行時のパラメーター値セットの切り替え
同じブロック パラメーターの複数の独立した値のセットを保存するには、構造体の配列を使用します。パラメーターのセットを切り替えるには、配列のインデックスとして動作する変数を作成し、変数の値を変更します。シミュレーション時、および変数が調整可能な場合は生成されたコードの実行時に、変数の値を変更できます。
ブロック パラメーターにさまざまな値のセットを実装するためのより優れた方法は、バリアント パラメーター (Simulink.VariantVariable) を使用することです。このワークフローを使用する例については、Create a Simple Variant Parameter Modelを参照してください。バリアント パラメーター バンク (Simulink.VariantBank) を使用して、バリアント パラメーターを生成コードの構造体配列にグループ化します。バリアント パラメーター バンクは、コードでポインター切り替えを使用して、バリアント条件に基いてアクティブなパラメーター値のセットを切り替えます。
モデル例の確認
モデル例を開きます。
open_system('sldemo_fuelsys_dd_controller')

このモデルは、ガソリン エンジンの燃料供給システムを表しています。モデルの出力は、エンジンへの燃料流量の比率です。
入れ子にされたサブシステム switchable_compensation に移動します。
open_system(['sldemo_fuelsys_dd_controller/fuel_calc/',... 'switchable_compensation'])

このサブシステムは、燃料比信号のノイズを修正および除去します。サブシステムは燃料供給モードに基づいてさまざまなフィルター係数を使用します。燃料供給モードはエンジン内のセンサーの障害に基づいて制御ロジックにより変更されます。たとえば、制御アルゴリズムは、通常の動作中に low_mode サブシステムをアクティブにします。このアルゴリズムは、センサー障害に応答して rich_mode サブシステムをアクティブにします。
low_mode サブシステムを開きます。
open_system(['sldemo_fuelsys_dd_controller/fuel_calc/',... 'switchable_compensation/low_mode'])

Discrete Filter ブロックは、燃料比信号をフィルター処理します。ブロックのダイアログ ボックスで、[分子係数] パラメーターにフィルターの分子係数を設定します。
兄弟サブシステム rich_mode には、異なる係数を使用する Discrete Filter ブロックも含まれます。
モデル ブロック線図を更新して信号データ型を表示します。ブロックの入出力信号では、単精度の浮動小数点データ型 single を使用します。
モデルの左下隅でモデル データ バッジをクリックしてから、[データ ディクショナリ] リンクをクリックします。このモデルのデータ ディクショナリ sldemo_fuelsys_dd_controller.sldd がモデル エクスプローラーで開きます。
モデル エクスプローラーの [モデルの階層構造] ペインで [データの設計] ノードを選択します。
[コンテンツ] ペインで、s16En15 などの Simulink.NumericType オブジェクトのプロパティを表示します。これらすべてのオブジェクトは現在単精度の浮動小数点データ型 single を表します。モデルはこれらのオブジェクトを使用して、Discrete Filter ブロックの入出力信号を含む信号のデータ型を設定します。
シミュレーション中および生成されたコードの実行中に、これらの各サブシステムで、ユーザーが制御する値をもつ変数に基づいてさまざまな分子係数を切り替えます。
構造体の配列へのパラメーター値の保存
既存の分子係数のセットを、値が構造体の Simulink.Parameter オブジェクトに保存します。構造体の各フィールドには、いずれかの Discrete Filter ブロックの係数が保存されます。
lowBlock = ['sldemo_fuelsys_dd_controller/fuel_calc/'... 'switchable_compensation/low_mode/Discrete Filter']; richBlock = ['sldemo_fuelsys_dd_controller/fuel_calc/'... 'switchable_compensation/rich_mode/Discrete Filter']; params.lowNumerator = eval(get_param(lowBlock,'Numerator')); params.richNumerator = eval(get_param(richBlock,'Numerator')); params = Simulink.Parameter(params);
params の値を一時変数にコピーします。この一時構造体のフィールドの値を変更し、変更した構造体を params の 2 番目の要素として代入します。
temp = params.Value;
temp.lowNumerator = params.Value.lowNumerator * 2;
temp.richNumerator = params.Value.richNumerator * 2;
params.Value(2) = temp;
clear temp
params の値は 2 つの構造体の配列です。各構造体はフィルター係数の 1 つのセットを格納しています。
パラメーター セットを切り替える変数を作成する
Ctrl という名前の Simulink.Parameter オブジェクトを作成します。
Ctrl = Simulink.Parameter(2);
Ctrl.DataType = 'uint8';
low_mode サブシステムの Discrete Filter ブロックのダイアログ ボックスで、[分子係数] パラメーターを式 params(Ctrl).lowNumerator に設定します。
set_param(lowBlock,'Numerator','params(Ctrl).lowNumerator');
rich_mode サブシステムの Discrete Filter ブロックで、[分子係数] パラメーターの値を params(Ctrl).richNumerator に設定します。
set_param(richBlock,'Numerator','params(Ctrl).richNumerator');
この式は変数 Ctrl を使用して params 内の構造体の 1 つを選択します。式ではその後構造体のフィールドの 1 つを逆参照します。フィールド値には分子係数の値が設定されています。
係数のセットを切り替えるには、Ctrl の値を構造体の配列の対応するインデックスに変更します。
バス オブジェクトを構造体配列のデータ型として使用する
必要に応じて Simulink.Bus オブジェクトを作成して構造体配列のデータ型として使用します。以下が可能です。
構造体の形状の制御。
フィールドごとにデータ型や物理単位などの特性を制御。
生成コード内の
struct型の名前の制御。
関数 Simulink.Bus.createObject を使用してオブジェクトを作成し、オブジェクトの名前を paramsType に変更します。
Simulink.Bus.createObject(params.Value)
paramsType = slBus1;
clear slBus1
データ ディクショナリの Simulink.NumericType オブジェクトを使用して、構造体のフィールドのデータ型を制御できます。バス オブジェクトでデータ型オブジェクトの名前を使用して、各要素の DataType プロパティを設定します。
paramsType.Elements(1).DataType = 's16En15'; paramsType.Elements(2).DataType = 's16En7';
バス オブジェクトを構造体配列のデータ型として使用します。
params.DataType = 'Bus: paramsType';
切り替え変数に列挙型を使用する
必要に応じて切り替え変数のデータ型として列挙型を使用します。それぞれのパラメーター セットに意味のある名前を関連付けると共に、切り替え変数が使用できる値を制限できます。
FilterCoeffs という名前の列挙型を作成します。params 内の各構造体について、列挙メンバーを作成します。各列挙メンバーの基となる整数値を、params の対応するインデックスに設定します。
Simulink.defineIntEnumType('FilterCoeffs',{'Weak','Aggressive'},[1 2])
この列挙型を切り替え変数のデータ型として使用します。この変数の値を Aggressive に設定します。これはインデックス 2 に対応します。
Ctrl.Value = FilterCoeffs.Aggressive;
データ ディクショナリに新しいオブジェクトを追加する
作成したオブジェクトをデータ ディクショナリ sldemo_fuelsys_dd_controller.sldd に追加します。
dictObj = Simulink.data.dictionary.open('sldemo_fuelsys_dd_controller.sldd'); sectObj = getSection(dictObj,'Design Data'); addEntry(sectObj,'Ctrl',Ctrl) addEntry(sectObj,'params',params) addEntry(sectObj,'paramsType',paramsType)
列挙型をデータ ディクショナリに保存することもできます。ただし、変更を sldemo_fuelsys_dd_controller.sldd に保存することはできないため、この場合は列挙型をインポートすることはできません。データ ディクショナリへの列挙型の保存の詳細については、データ ディクショナリの列挙値を参照してください。
シミュレーション中にパラメーター セットを切り替える
モデル例 sldemo_fuelsys_dd を開きます。このモデルはコントローラー モデル sldemo_fuelsys_dd_controller を参照しています。
open_system('sldemo_fuelsys_dd')

シミュレーション中にモデルを操作できるように、シミュレーション終了時間を Inf に設定します。
シミュレーションの実行を開始し、Scope ブロックのダイアログ ボックスを開きます。エンジンの通常動作時の燃料流量 (fuel 信号) の振動と大幅な振幅がスコープに表示されます。
モデル エクスプローラーでデータ ディクショナリ sldemo_fuelsys_dd_controller.sldd の内容を表示します。Ctrl の値を FilterCoeffs.Weak に設定します。
モデル ブロック線図 sldemo_fuelsys_dd を更新します。アグレッシブの度合いが低いフィルター係数のために、燃料比の振動の振幅が減少することがスコープによって示されます。
シミュレーションを停止します。
コードの生成と検査
Simulink Coder ソフトウェアをお持ちの場合、コードの実行中にパラメーター セットを切り替えることができるコードを生成できます。
モデル エクスプローラーでデータ ディクショナリ sldemo_fuelsys_dd_controller.sldd の内容を表示します。[コンテンツ] ペインで、[列ビュー] を Storage Class に設定します。
構造体配列が生成コード内で調整可能なグローバル変数として現れるように、[StorageClass] 列を使用してストレージ クラス ExportedGlobal を params に適用します。コードの実行中に切り替え変数の値を変更できるように、同じストレージ クラスを Ctrl に適用します。
または、オブジェクトを構成するために、次のコマンドを使用します。
tempEntryObj = getEntry(sectObj,'params'); params = getValue(tempEntryObj); params.StorageClass = 'ExportedGlobal'; setValue(tempEntryObj,params); tempEntryObj = getEntry(sectObj,'Ctrl'); Ctrl = getValue(tempEntryObj); Ctrl.StorageClass = 'ExportedGlobal'; setValue(tempEntryObj,Ctrl);
コントローラー モデルからコードを生成します。
slbuild('sldemo_fuelsys_dd_controller')
### Searching for referenced models in model 'sldemo_fuelsys_dd_controller'. ### Total of 1 models to build. ### Starting build procedure for: sldemo_fuelsys_dd_controller ### Successful completion of code generation for: sldemo_fuelsys_dd_controller Build Summary Top model targets: Model Build Reason Status Build Duration ================================================================================================================== sldemo_fuelsys_dd_controller Information cache folder or artifacts were missing. Code generated. 0h 0m 44.026s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 47.459s
コード生成レポートで、ヘッダー ファイル sldemo_fuelsys_dd_controller_types.h を表示します。このコードは列挙データ型 FilterCoeffs を定義します。
file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',... 'sldemo_fuelsys_dd_controller_types.h'); coder.example.extractLines(file,'#ifndef DEFINED_TYPEDEF_FOR_FilterCoeffs_',... '/* Forward declaration for rtModel */',1,0)
#ifndef DEFINED_TYPEDEF_FOR_FilterCoeffs_
#define DEFINED_TYPEDEF_FOR_FilterCoeffs_
typedef enum {
Weak = 1, /* Default value */
Aggressive
} FilterCoeffs;
#endif
また、このコードは Simulink.Bus オブジェクトに対応付けられている構造体型 paramsType も定義します。このフィールドは、モデルの単精度浮動小数点データ型を使用します。
coder.example.extractLines(file,'#ifndef DEFINED_TYPEDEF_FOR_paramsType_',... '#ifndef DEFINED_TYPEDEF_FOR_FilterCoeffs_',1,0)
#ifndef DEFINED_TYPEDEF_FOR_paramsType_
#define DEFINED_TYPEDEF_FOR_paramsType_
typedef struct {
real32_T lowNumerator[2];
real32_T richNumerator[2];
} paramsType;
#endif
ソース ファイル sldemo_fuelsys_dd_controller.c を表示します。このコードは、列挙型を使用して切り替え変数 Ctrl を定義します。
file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',... 'sldemo_fuelsys_dd_controller.c'); coder.example.extractLines(file,'FilterCoeffs Ctrl = Aggressive;',... '/* Block signals (default storage) */',1,0)
FilterCoeffs Ctrl = Aggressive; /* Variable: Ctrl
* Referenced by:
* '<S12>/Discrete Filter'
* '<S13>/Discrete Filter'
*/
このコードは、構造体配列 params も定義します。
coder.example.extractLines(file,'/* Exported block parameters */',... '/* Variable: params',1,1)
/* Exported block parameters */
paramsType params[2] = { {
{ 8.7696F, -8.5104F },
{ 0.0F, 0.2592F }
}, { { 17.5392F, -17.0208F },
{ 0.0F, 0.5184F }
} } ; /* Variable: params
モデルの関数 step のコード アルゴリズムは、構造体配列のインデックスを指定するために切り替え変数を使用します。
構造体配列に格納されているパラメーター セットを切り替えるには、コードの実行中に Ctrl の値を変更します。
データ ディクショナリへの接続を閉じます。この例では未保存の変更は破棄されます。変更を保存するには、'-save' オプションを使用します。
Simulink.data.dictionary.closeAll('sldemo_fuelsys_dd_controller.sldd','-discard')