シミュレーションおよびコード実行時のパラメーター値セットの切り替え
同じブロック パラメーターの複数の独立した値のセットを保存するには、構造体の配列を使用します。パラメーターのセットを切り替えるには、配列のインデックスとして動作する変数を作成し、変数の値を変更します。シミュレーション時、および変数が調整可能な場合は生成されたコードの実行時に、変数の値を変更できます。
モデル例の確認
モデル例を開きます。
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')
### Starting build procedure for: sldemo_fuelsys_dd_controller ### Successful completion of code generation for: sldemo_fuelsys_dd_controller Build Summary Top model targets built: Model Action Rebuild Reason ================================================================================================= sldemo_fuelsys_dd_controller Code generated. Code generation information file does not exist. 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 33.598s
コード生成レポートで、ヘッダー ファイル sldemo_fuelsys_dd_controller_types.h
を表示します。このコードは列挙データ型 FilterCoeffs
を定義します。
file = fullfile('sldemo_fuelsys_dd_controller_ert_rtw',... 'sldemo_fuelsys_dd_controller_types.h'); rtwdemodbtype(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
も定義します。このフィールドは、モデルの単精度浮動小数点データ型を使用します。
rtwdemodbtype(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'); rtwdemodbtype(file,'FilterCoeffs Ctrl = Aggressive;',... '/* Block signals (default storage) */',1,0)
FilterCoeffs Ctrl = Aggressive; /* Variable: Ctrl * Referenced by: * '<S12>/Discrete Filter' * '<S13>/Discrete Filter' */
このコードは、構造体配列 params
も定義します。
rtwdemodbtype(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')