Main Content

生成コードのデータ インターフェイスの構成

生成コードに含めるために信号、状態、パラメーターを指定します。

生成コード内でデータの次の属性を制御する方法について学習します。

  • 名前

  • データ型

  • データ ストレージ クラス

モデル例の詳細については、C コード生成のためのコントロール アルゴリズム モデルの準備を参照してください。

モデル例を開く

モデル例 rtwdemo_PCG_Eval_P2 を開きます。

open_system('rtwdemo_PCG_Eval_P2')

データ宣言

ほとんどのプログラミング言語では、使用前にデータと関数を宣言する必要があります。宣言により、以下の事項を指定します。

  • スコープ: データにアクセスできるプログラムの領域

  • 持続時間: データがメモリ内に維持されている時間

  • データ型: データに割り当てられるメモリの量

  • 初期化: 値、メモリのポインターまたは NULL

スコープと持続時間を組み合わせたものがストレージ クラスです。開始値を指定しない場合、ほとんどのコンパイラはゼロ値または null ポインターを割り当てます。

以下のデータ型がサポートされています。

  • double:倍精度浮動小数点

  • single:単精度浮動小数点

  • int8:符号付き 8 ビット整数

  • uint8:符号なし 8 ビット整数

  • int16:符号付き 16 ビット整数

  • uint16:符号なし 16 ビット整数

  • int32:符号付き 32 ビット整数

  • uint32:符号なし 32 ビット整数

  • 固定小数点: 8 ビット、16 ビット、32 ビット語長

ストレージ クラスでは以下を実行できます。

  • カスタム名が付き、グローバル変数の宣言と定義を含むエクスポート ファイルを生成する。

  • グローバル変数宣言を含むカスタム ヘッダー ファイルをインポートする。

  • 宣言内で const または volatile 型修飾子を生成する。

  • パラメーターをマクロで表現する (#define またはコンパイラ オプション)。

  • 信号またはパラメーターをフラットな構造体またはビット フィールドにパッケージングする。

Simulink と Stateflow でのデータ制御

この例ではデータ オブジェクトを使用してデータのコード生成設定を指定します。また、ダイアログ ボックスを使用してモデル内に設定を保存することもできます。いずれの方法でもデータ型とストレージ クラスを完全に制御することができます。1 つのモデル内で両方の方法を使用できます。

この例では次のデータ オブジェクトのタイプに焦点を合わせます。

  • 信号

  • パラメーター

  • バス

コード ジェネレーターは MATLAB® ベース ワークスペースまたは Simulink® データ ディクショナリからのオブジェクトを使用します。コマンド プロンプトでコマンドを使用するか、モデル データ エディターまたはモデル エクスプローラーとコード マッピング エディターを使用してオブジェクトを作成し、検査することができます。

例として、以下ではモデルによってベース ワークスペースで作成された Simulink.Signal オブジェクト pos_cmd_one の定義を検証します。

  1. Embedded Coder アプリを開きます。

  2. [モデル化] タブで [モデル データ エディター] をクリックします。

  3. モデル データ エディターで、[信号] タブを検査します。

  4. [追加情報の表示/更新] ボタンをクリックします。

  5. [コンテンツのフィルター] ボックスの横にある [選択を使用してフィルター処理します] ボタンを切り換えます。

  6. モデルで pos_cmd_one 信号線を選択します。これで、データ テーブルには 2 つの行が含まれます。1 つはモデル内の信号線に対応する行で、もう 1 つはベース ワークスペース内の信号オブジェクトに対応する行です。信号線に対応する行の場合は、[Resolve] チェック ボックスがオンになります。これは、信号線で信号オブジェクトから設定を取得することを意味します。

  7. オプションで、信号オブジェクトの他のプロパティを検査するには、[ビューの変更] ドロップダウン リストの設定を調整します。

  8. モデルで pos_cmd_one 信号線を選択し、その信号線の上または下に表示される省略記号で一時停止して、操作バーを開きます。[信号の追加] ボタンをクリックします。

  9. [コード マッピング エディター] を開き、[信号] タブをクリックします。pos_cmd_one 信号ストレージ クラスを検査します。

モデル データ エディターに戻り、[選択を使用してフィルター処理します] ボタンを切り換えます。これで、データ テーブルには次の信号線と信号オブジェクトが示されます。

  • pos_cmd_one

  • pos_rqst

  • P_InErrMap

  • ThrotComm

ThrotCommSimulink.Bus オブジェクト ThrottleCommands のインスタンス化であるバス信号です。バス信号が非バーチャルの場合、信号は C コード内に構造体として表示されます。バス オブジェクトはモデル データ エディターに表示されません。ただし、モデル エクスプローラー ([ツール表示]、[モデル エクスプローラー]) でオブジェクトを検査できます。

C コードの場合と同様に、バス定義 (ThrottleCommands) を使用して構造体の複数のインスタンスを作成できます。モデル ブロック線図では、バス信号は中心に点線のある幅広線で表示されます。

データ オブジェクトには、シミュレーションやコード生成のために設定できる次のようなプロパティがあります。

  • DataType (生成されたコード内のストレージの数値データ型)

  • StorageClass (コード生成用のストレージ クラス)

  • Value (パラメーター値)

  • InitialValue (信号の初期値)

  • Alias (コード ジェネレーターが使用するデータの別の名前)

  • Dimensions (パラメーターまたは信号値のサイズと次元数)

  • Complexity (数値の実数/複素数)

  • Unit (cm などの物理単位)

  • Min (最小値)

  • Max (最大値)

プロパティ Description を使用してデータ オブジェクトのカスタム ドキュメンテーションを指定します。

新しいデータ オブジェクトの追加

名前付きの信号、ステート、パラメーター用にデータ オブジェクトを作成することができます。データ オブジェクトを構造と関連付けるには、構造に名前が付いていなければなりません。

データ オブジェクト ウィザード ツールはデータ オブジェクトを作成し、目的とするオブジェクトを作成するための構造を検索します。モデル例にはデータ オブジェクトと関連付けされていない 2 つの信号、fbk_1pos_cmd_two が含まれています。

信号を検索し、信号用のデータ オブジェクトを作成するには

1. データ オブジェクト ウィザードを開きます。

dataobjectwizard('rtwdemo_PCG_Eval_P2')

2. [検索] をクリックして構造の候補を検索します。

3. [すべて選択] をクリックしてすべての候補を選択します。

4. [作成] をクリックしてデータ オブジェクトを作成します。

データ オブジェクト ウィザードは次のコマンドと同等の動作を実施します。

fbk_1 = Simulink.Signal;
fbk_1.Dimensions = 1;
fbk_1.DataType = 'double';
outport = get_param('rtwdemo_PCG_Eval_P2/fbk_1','PortHandles');
outport = outport.Outport;
set_param(outport,'MustResolveToSignalObject','on')

pos_cmd_two = Simulink.Signal;
pos_cmd_two.Dimensions = 1;
pos_cmd_two.DataType = 'double';
outport = get_param('rtwdemo_PCG_Eval_P2/PI_ctrl_2','PortHandles');
outport = outport.Outport;
set_param(outport,'MustResolveToSignalObject','on')

データ オブジェクトの設定

各データ オブジェクトのデータ型とストレージ クラスを設定します。データ オブジェクトのプロパティを設定するには、モデル データ エディターの該当するタブを検査します。[ビューの変更] ドロップダウン リストを使用して設計プロパティ (データ型など) とコード生成設定 (ストレージ クラスなど) を示します。

モデル データ エディターで、[信号] タブを検査し、[追加情報の表示/更新] ボタンをクリックして、データ オブジェクト ウィザードで作成した信号オブジェクトの情報を表示します。次に、オブジェクトの次のプロパティを設定します。

  • fbk_1:データ型は double、ストレージ クラスは ImportedExtern

  • pos_cmd_two:データ型は double、ストレージ クラスは ExportedGlobal

または、次のコマンドをコマンド プロンプトで使用して、オブジェクトを設定できます。

fbk_1.DataType = 'double';
fbk_1.StorageClass = 'ImportedExtern';

pos_cmd_two.DataType = 'double';
pos_cmd_two.StorageClass = 'ExportedGlobal';

パラメーター データのファイル配置の制御

Embedded Coder® を使用して、パラメーターと定数が定義されているファイルの配置を制御できます。モデル例では、パラメーター定義をファイル eval_data.c に書き込みます。

パラメーターと定数の定義の配置を変更するには、モデル コンフィギュレーションでデータ配置オプションを設定します。[コンフィギュレーション パラメーター] ダイアログ ボックスの [コード生成]、[コード配置] ペインでオプションを設定します。

モデル例で、[コンフィギュレーション パラメーター] ダイアログ ボックスの [コード配置] ペインを検証します。このモデルは、データ定義をファイル eval_data.c に、宣言をファイル eval_data.h に配置します。

ブロック パラメーターを調整可能またはインラインとして宣言する

モデル コンフィギュレーション パラメーター [既定のパラメーター動作] を設定することで、生成コード内のブロック パラメーターの既定の調整可能性を制御できます。

モデル例では、既定のパラメーター動作は Inlined に設定されています。既定では、ブロック パラメーターはコード内で数値リテラル値として表現され、メモリ内に保存される変数として表現されません。Simulink.Parameter オブジェクトを使用してインライン化をオーバーライドし、個々のパラメーターの調整可能性を保持できます。

生成コードでの信号データ オブジェクトの有効化

信号データ オブジェクト (Simulink.Signal) は生成されたコード内に表示されます。モデル内の個々の信号線について、[信号名を Simulink の信号オブジェクトに関連付ける] オプションを選択して、信号名がワークスペースまたはデータ ディクショナリの Simulink.Signal オブジェクトに明示的に関連付けられるようにします。モデル データ エディターで、[ビューの変更] を [コード] に設定し、[Resolve] 列のチェック ボックスをオンにします。

または、モデル内のすべての信号に対してオプションを選択することもできます。コマンド プロンプトで関数 disableimplicitsignalresolution を使用します。

生成コードのデータ オブジェクトの表示

モデル例からコードを生成します。

slbuild('rtwdemo_PCG_Eval_P2');
### Starting build procedure for: rtwdemo_PCG_Eval_P2
### Successful completion of code generation for: rtwdemo_PCG_Eval_P2

Build Summary

Top model targets built:

Model                Action           Rebuild Reason                                    
========================================================================================
rtwdemo_PCG_Eval_P2  Code generated.  Code generation information file does not exist.  

1 of 1 models built (0 models already up to date)
Build duration: 0h 0m 36.354s

生成されたファイルをより簡単に参照するために、コード生成レポートを作成します。Simulink エディターで、モデル コンフィギュレーション パラメーター [モデル レポートを開く] を選択します。

次の生成されたファイルにアクセスできます。

  • rtwdemo_PCG_Eval_P2.c:ステップ関数と初期化関数を定義します。定義されたデータ オブジェクトを使用します。

  • eval_data.c:定義されたパラメーターに初期値を代入します。モデル コンフィギュレーションは具体的にファイル名を設定します。

  • eval_data.h:パラメーター データの extern 宣言を提供します。モデル コンフィギュレーションは具体的にファイル名を設定します。

  • ert_main.c:スケジューリング機能を定義します。

  • rtwdemo_PCG_Eval_P2.h:信号、状態、パラメーター データを保存する既定の構造体の型定義が含まれます。データ オブジェクト設定により、一部のデータは代わりに eval_data.c に表示されます。

  • PCG_Eval_p2_private.h:生成した関数用にプライベート (ローカル) データを定義します。

  • rtwdemo_PCG_Eval_P2_types.h:リアルタイム モデル データ構造体を宣言します。

  • rtwtypes.h:Simulink® Coder™ で定義されるデータ型へのマッピングを提供します (typedef)。外部システムとの統合に使用されます。

たとえば、ファイル eval_data.c を表示すると、ベース ワークスペースの Simulink.Parameter オブジェクトに対応するグローバル変数に対して、const メモリが割り当てられています。

cfile = fullfile('rtwdemo_PCG_Eval_P2_ert_rtw','eval_data.c');
rtwdemodbtype(cfile,'/* Exported data definition */','* [EOF]',1,1)
/* Exported data definition */

/* Const memory section */
/* Definition for custom storage class: Const */
const real_T I_Gain = -0.03;
const real_T I_InErrMap[9] = { -1.0, -0.5, -0.25, -0.05, 0.0, 0.05, 0.25, 0.5,
  1.0 } ;

const real_T I_OutMap[9] = { 1.0, 0.75, 0.6, 0.0, 0.0, 0.0, 0.6, 0.75, 1.0 } ;

const real_T P_Gain = 0.74;
const real_T P_InErrMap[7] = { -1.0, -0.25, -0.01, 0.0, 0.01, 0.25, 1.0 } ;

const real_T P_OutMap[7] = { 1.0, 0.25, 0.0, 0.0, 0.0, 0.25, 1.0 } ;

/*
 * File trailer for generated code.
 *
 * [EOF]

ファイル rtwdemo_PCG_Eval_P2.c では、モデルの関数 step のコード アルゴリズムを表示します。このアルゴリズムではデータ オブジェクトの名前が直接使用されています。

cfile = fullfile('rtwdemo_PCG_Eval_P2_ert_rtw','rtwdemo_PCG_Eval_P2.c');
rtwdemodbtype(cfile,'/* Model step function */',...
    '/* Sum: ''<S2>/Sum3'' incorporates:',1,0);
/* Model step function */
void rtwdemo_PCG_Eval_P2_step(void)
{
  real_T Discrete_Time_Integrator1;
  real_T Discrete_Time_Integrator1_i;
  real_T rtb_IntegralGainShape;

  /* Sum: '<S2>/Sum2' incorporates:
   *  Inport: '<Root>/fbk_1'
   *  Inport: '<Root>/pos_rqst'
   */
  rtb_IntegralGainShape = *pos_rqst - fbk_1;

  /* DiscreteIntegrator: '<S2>/Discrete_Time_Integrator1' */
  if (rtwdemo_PCG_Eval_P2_DWork.Discrete_Time_Integrator1_SYSTE != 0) {
    /* DiscreteIntegrator: '<S2>/Discrete_Time_Integrator1' */
    Discrete_Time_Integrator1 =
      rtwdemo_PCG_Eval_P2_DWork.Discrete_Time_Integrator1_DSTAT;
  } else {
    /* DiscreteIntegrator: '<S2>/Discrete_Time_Integrator1' incorporates:
     *  Gain: '<S2>/Int Gain1'
     *  Lookup_n-D: '<S2>/Integral  Gain Shape'
     *  Lookup_n-D: '<S3>/Integral  Gain Shape'
     *  Product: '<S2>/Product3'
     */
    Discrete_Time_Integrator1 = I_Gain * look1_binlx(rtb_IntegralGainShape,
      &I_InErrMap[0], &I_OutMap[0], 8U) * rtb_IntegralGainShape * 0.001 +
      rtwdemo_PCG_Eval_P2_DWork.Discrete_Time_Integrator1_DSTAT;
  }

  /* End of DiscreteIntegrator: '<S2>/Discrete_Time_Integrator1' */

データ オブジェクトで指定するストレージ クラスや他のコード生成設定を使用しない場合、生成されたコードは次のようになります。

  • モデル コンフィギュレーション パラメーターでこれらの最適化を選択すると、不変信号およびブロック パラメーターがインライン化されます

  • モデルの入力信号と出力信号、ブロックの状態および調整可能パラメーターは、グローバル データ構造体に配置されます

  • MATLAB 変数に対応するグローバル変数は作成されません

対照的に、このコード例では大半の既定のデータ構造体がユーザー定義のデータ オブジェクトに置き換えられたことがわかります。たとえば、次の信号とパラメーターがグローバル変数としてコード内に現れます。

  • pos_rqst

  • fbk_1

  • I_Gain

  • I_OutMap

  • I_InErrMap

しかし、ローカル変数 rtb_IntegralGainShape と状態変数 rtwdemo_PCG_Eval_P2_DWork.Discrete_Time_Integrator1_DSTAT はコード ジェネレーター データ構造体を使用しています。これらのエンティティに対してデータ オブジェクトは存在しません。

モデル データをデータ ディクショナリに保存

MATLAB セッションを終了すると、ベース ワークスペースで作成した変数は保持されません。データ オブジェクトやバス オブジェクトを永続的に保存するために、モデルをデータ ディクショナリにリンクすることを検討します。

  1. モデル例の [モデル化] タブの [設計] で、[データ ディクショナリへのリンク] をクリックします。

  2. [モデル プロパティ] ダイアログ ボックスで、[新規作成] をクリックします。

  3. [新しいデータ ディクショナリを作成します] ダイアログ ボックスで、[ファイル名]rtwdemo_PCG_Eval_dict に設定して [保存] をクリックします。

  4. [モデル プロパティ] ダイアログ ボックスで、[適用] をクリックします。

  5. [データの移行] をクリックします。

  6. 参照される変数のコピーに関するメッセージに対して、[移行] をクリックします。

  7. [OK] をクリックします。

または、手動でオブジェクトをデータ ディクショナリに移行するために、プログラムのコマンドを使用することもできます。

% Create a list of the variables and objects that the target
% model uses.
usedVars = {Simulink.findVars('rtwdemo_PCG_Eval_P2').Name};
% Create a new data dictionary in your current folder. Link the model to
% this new dictionary.
dictObj = Simulink.data.dictionary.create('rtwdemo_PCG_Eval_dict.sldd');
set_param('rtwdemo_PCG_Eval_P2','DataDictionary','rtwdemo_PCG_Eval_dict.sldd')
% Import only the target variables from the base workspace to the data
% dictionary.
importFromBaseWorkspace(dictObj,'clearWorkspaceVars',true,'varList',usedVars);
saveChanges(dictObj);

モデルが使用するオブジェクトはデータ ディクショナリに永続的に保存されます。ディクショナリの内容を表示するには、モデルの左下隅にあるモデル データ バッジをクリックしてから [データ ディクショナリ] リンクをクリックします。モデル エクスプローラーの [モデルの階層構造] ペインで [データの設計] ノードを選択します。

モデルからデータを分離しておくと、次のメリットが得られます。

1 つのモデル、複数のデータセット

  • 異なるデータ型を使用してターゲット ハードウェアを変更する (たとえば、浮動小数点と固定小数点ターゲット)

  • 異なるパラメーター値を使用して制御アルゴリズムの動作を変更する (たとえば、キャリブレーション値の異なる再利用可能なコンポーネント)

複数のモデル、1 つのデータセット

  • システム内の Simulink® モデル間でデータを共有する

  • プロジェクト間でデータを共有する (たとえば、トランスミッション制御、エンジン制御、ホイール制御ですべて同じメッセージ データセットを使用する可能性がある)

関連するトピック