信号、状態、パラメーター データへの実行時のアクセス
モデルの反復的な開発においては、モデル実行で生成される出力信号や状態のデータを取得します。実行時にはパラメーターの値の調整も行い、出力での結果を確認します。そうすることで、設計を決定する際の判断をこのような出力の解析に基づいたものにできます。ラピッド プロトタイピング環境では、この信号、状態、パラメーターのデータにアクセスするために、データをアドレス可能なメモリに格納するように生成コードを設定できます。
既定では、生成コードの効率を高めるために、最適化設定によって、不要な信号ストレージを削除したり、ブロック パラメーターの数値をインライン化したりするように設定されています。その代わりに、このデータ用にアドレス可能なメモリを割り当てるコードを生成するには、最適化を無効にするか、個々のデータ項目に対してコード生成設定を指定します。
モデル例の確認
この例のためにモデル ConfigurationRapidPrototypingInterface を準備するスクリプトを実行します。
prepare_configurationRapidPrototypingInterface
以下のデータはコード生成のために構成されます。
パラメーター
UPPER、LOWER、K1、Table1、およびTable2信号
In1、In2、In3、In4、およびOut1状態
X(遅延) およびmode(データ ストア メモリ書き込み)
モデル例 ConfigurationRapidPrototypingInterface を開きます。
ConfigurationRapidPrototypingInterface

このモデルでは MATLAB® の数値変数をモデル ワークスペースに読み込みます。ワークスペース変数は、モデルにいくつかのブロック パラメーターを設定します。しかし、モデル内の Gain ブロックは、リテラル値 2 を使用します。
最適化の無効化
1. モデルで、モデル コンフィギュレーション パラメーターの [信号ストレージの再利用] をクリアします。この最適化のほか、[余分なローカル変数の削除 (式の畳み込み)] などの最適化をクリアすると、生成コードで信号線にメモリが割り当てられます。[信号ストレージの再利用] をクリアすると、他のほとんどの最適化が無効になります。
set_param('ConfigurationRapidPrototypingInterface','OptimizeBlockIOStorage','off')
2. モデル コンフィギュレーション パラメーター [既定のパラメーター動作] を [Tunable] に設定します。このコンフィギュレーション パラメーターを [Tunable] に設定すると、生成コードでブロック パラメーターおよびワークスペース変数にメモリが割り当てられます。
set_param('ConfigurationRapidPrototypingInterface','DefaultParameterBehavior','Tunable')
3. コードを生成します。
slbuild('ConfigurationRapidPrototypingInterface')
### Searching for referenced models in model 'ConfigurationRapidPrototypingInterface'. ### Total of 1 models to build. ### Starting build procedure for: ConfigurationRapidPrototypingInterface ### Successful completion of build procedure for: ConfigurationRapidPrototypingInterface Build Summary Top model targets: Model Build Reason Status Build Duration ========================================================================================================================================= ConfigurationRapidPrototypingInterface Information cache folder or artifacts were missing. Code generated and compiled. 0h 0m 28.304s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 30.53s
4. コード生成レポートで、ファイル ConfigurationRapidPrototypingInterface.h を表示します。このヘッダー ファイルは、信号のデータを格納する構造体型を定義しています。構造体にはモデル内の各信号線を表すフィールドが格納されます。たとえば、Gain という名前の Gain ブロックの出力信号はフィールド Gain として表されています。
file = fullfile('ConfigurationRapidPrototypingInterface_grt_rtw','ConfigurationRapidPrototypingInterface.h'); coder.example.extractLines(file,'/* Block signals (default storage) */',... 'B_ConfigurationRapidPrototypingInterface_T;',1,1)
/* Block signals (default storage) */
typedef struct {
real_T Delay; /* '<Root>/Delay' */
real_T Table2; /* '<Root>/Table2' */
real_T Table1; /* '<Root>/Table1' */
real_T Gain; /* '<Root>/Gain' */
boolean_T RelOp1; /* '<Root>/RelOp1' */
boolean_T RelOp2; /* '<Root>/RelOp2' */
boolean_T LogOp; /* '<Root>/LogOp' */
boolean_T DataStoreRead; /* '<Root>/Data Store Read' */
} B_ConfigurationRapidPrototypi_T;
/* Block states (default storage) for system '<Root>' */
typedef struct {
real_T X; /* '<Root>/Delay' */
} DW_ConfigurationRapidPrototyp_T;
/* External inputs (root inport signals with default storage) */
typedef struct {
real_T In1; /* '<Root>/In1' */
real_T input2; /* '<Root>/In2' */
real_T In3; /* '<Root>/In3' */
real_T In4; /* '<Root>/In4' */
} ExtU_ConfigurationRapidProtot_T;
/* Parameters (default storage) */
struct P_ConfigurationRapidPrototypi_T_ {
Table1_Type Table1; /* Variable: Table1
* Referenced by: '<Root>/Table1'
*/
Table2_Type Table2; /* Variable: Table2
* Referenced by: '<Root>/Table2'
*/
real_T LOWER; /* Variable: LOWER
* Referenced by: '<Root>/Constant2'
*/
real_T UPPER; /* Variable: UPPER
* Referenced by: '<Root>/Constant1'
*/
real_T Gain_Gain; /* Expression: 2
* Referenced by: '<Root>/Gain'
*/
real_T Delay_InitialCondition; /* Expression: 0
* Referenced by: '<Root>/Delay'
*/
uint32_T Table2_maxIndex[2]; /* Computed Parameter: Table2_maxIndex
* Referenced by: '<Root>/Table2'
*/
boolean_T DataStoreMemory_InitialValue;
/* Computed Parameter: DataStoreMemory_InitialValue
* Referenced by: '<Root>/Data Store Memory'
*/
};
/* Real-time Model Data Structure */
struct tag_RTM_ConfigurationRapidPro_T {
const char_T *errorStatus;
};
/* Block parameters (default storage) */
extern P_ConfigurationRapidPrototypi_T ConfigurationRapidPrototyping_P;
/* Block signals (default storage) */
extern B_ConfigurationRapidPrototypi_T ConfigurationRapidPrototyping_B;
/* Block states (default storage) */
extern DW_ConfigurationRapidPrototyp_T ConfigurationRapidPrototypin_DW;
/* External inputs (root inport signals with default storage) */
extern ExtU_ConfigurationRapidProtot_T ConfigurationRapidPrototyping_U;
/*
* Exported States
*
* Note: Exported states are block states with an exported global
* storage class designation. Code generation will declare the memory for these
* states and exports their symbols.
*
*/
extern boolean_T mode; /* '<Root>/Data Store Memory' */
/* Model entry point functions */
extern void ConfigurationRapidPrototypingInterface_initialize(void);
extern void ConfigurationRapidPrototypingInterface_step(void);
extern void ConfigurationRapidPrototypingInterface_terminate(void);
/* Exported data declaration */
/* Data with Exported storage */
extern real_T output; /* '<Root>/Out1' */
/* Real-time Model object */
extern RT_MODEL_ConfigurationRapidPr_T *const ConfigurationRapidPrototypin_M;
/*-
* The generated code includes comments that allow you to trace directly
* back to the appropriate location in the model. The basic format
* is <system>/block_name, where system is the system number (uniquely
* assigned by Simulink) and block_name is the name of the block.
*
* Use the MATLAB hilite_system command to trace the generated code back
* to the model. For example,
*
* hilite_system('<S3>') - opens system 3
* hilite_system('<S3>/Kp') - opens and selects block Kp which resides in S3
*
* Here is the system hierarchy for this model
*
* '<Root>' : 'ConfigurationRapidPrototypingInterface'
*/
#endif /* ConfigurationRapidPrototypingInterface_h_ */
このファイルは、ブロック パラメーターのデータを格納する構造体型を定義しています。たとえば、Gain ブロックの [ゲイン] パラメーターはフィールド Gain_Gain として表されています。構造体のその他のフィールドは、信号および状態の初期条件など、モデルの他のブロック パラメーターやワークスペース変数を表します。
coder.example.extractLines(file,'/* Parameters (default storage) */',... '/* Real-time Model Data Structure */',1,0)
/* Parameters (default storage) */
struct P_ConfigurationRapidPrototypi_T_ {
Table1_Type Table1; /* Variable: Table1
* Referenced by: '<Root>/Table1'
*/
Table2_Type Table2; /* Variable: Table2
* Referenced by: '<Root>/Table2'
*/
real_T LOWER; /* Variable: LOWER
* Referenced by: '<Root>/Constant2'
*/
real_T UPPER; /* Variable: UPPER
* Referenced by: '<Root>/Constant1'
*/
real_T Gain_Gain; /* Expression: 2
* Referenced by: '<Root>/Gain'
*/
real_T Delay_InitialCondition; /* Expression: 0
* Referenced by: '<Root>/Delay'
*/
uint32_T Table2_maxIndex[2]; /* Computed Parameter: Table2_maxIndex
* Referenced by: '<Root>/Table2'
*/
boolean_T DataStoreMemory_InitialValue;
/* Computed Parameter: DataStoreMemory_InitialValue
* Referenced by: '<Root>/Data Store Memory'
*/
};
5. ファイル ConfigurationRapidPrototypingInterface_data.c を表示します。このソース ファイルは、パラメーター構造体にグローバル メモリを割り当て、モデルのパラメーターの値に基づいてフィールドの値を初期化します。
6. ソース ファイル ConfigurationRapidPrototypingInterface.c を表示します。このコードは、信号のデータを格納する構造体変数にグローバル メモリを割り当てます。
file = fullfile('ConfigurationRapidPrototypingInterface_grt_rtw','ConfigurationRapidPrototypingInterface.c'); coder.example.extractLines(file,'/* Block signals (default storage) */',... 'B_ConfigurationRapidPrototypingInterface_T ConfigurationRapidPrototypingInterface_B;',1,1)
/* Block signals (default storage) */
B_ConfigurationRapidPrototypi_T ConfigurationRapidPrototyping_B;
/* Block states (default storage) */
DW_ConfigurationRapidPrototyp_T ConfigurationRapidPrototypin_DW;
/* External inputs (root inport signals with default storage) */
ExtU_ConfigurationRapidProtot_T ConfigurationRapidPrototyping_U;
/* Real-time model */
static RT_MODEL_ConfigurationRapidPr_T ConfigurationRapidPrototypin_M_;
RT_MODEL_ConfigurationRapidPr_T *const ConfigurationRapidPrototypin_M =
&ConfigurationRapidPrototypin_M_;
/* Model step function */
void ConfigurationRapidPrototypingInterface_step(void)
{
/* RelationalOperator: '<Root>/RelOp1' incorporates:
* Constant: '<Root>/Constant1'
* Inport: '<Root>/In1'
*/
ConfigurationRapidPrototyping_B.RelOp1 = (ConfigurationRapidPrototyping_U.In1 >
ConfigurationRapidPrototyping_P.UPPER);
/* RelationalOperator: '<Root>/RelOp2' incorporates:
* Constant: '<Root>/Constant2'
* Inport: '<Root>/In1'
*/
ConfigurationRapidPrototyping_B.RelOp2 = (ConfigurationRapidPrototyping_U.In1 <
ConfigurationRapidPrototyping_P.LOWER);
/* Logic: '<Root>/LogOp' */
ConfigurationRapidPrototyping_B.LogOp =
(ConfigurationRapidPrototyping_B.RelOp1 ||
ConfigurationRapidPrototyping_B.RelOp2);
/* DataStoreWrite: '<Root>/Data Store Write' */
mode = ConfigurationRapidPrototyping_B.LogOp;
/* DataStoreRead: '<Root>/Data Store Read' */
ConfigurationRapidPrototyping_B.DataStoreRead = mode;
/* UnitDelay: '<Root>/Delay' */
ConfigurationRapidPrototyping_B.Delay = ConfigurationRapidPrototypin_DW.X;
/* Switch: '<Root>/Switch' */
if (ConfigurationRapidPrototyping_B.DataStoreRead) {
/* Lookup_n-D: '<Root>/Table1' incorporates:
* Inport: '<Root>/In2'
*/
ConfigurationRapidPrototyping_B.Table1 = look1_binlc
(ConfigurationRapidPrototyping_U.input2,
ConfigurationRapidPrototyping_P.Table1.BP,
ConfigurationRapidPrototyping_P.Table1.Table, 10U);
/* Gain: '<Root>/Gain' */
ConfigurationRapidPrototyping_B.Gain =
ConfigurationRapidPrototyping_P.Gain_Gain *
ConfigurationRapidPrototyping_B.Table1;
/* Outport: '<Root>/Out1' */
output = ConfigurationRapidPrototyping_B.Gain;
} else {
/* Outport: '<Root>/Out1' */
output = ConfigurationRapidPrototyping_B.Delay;
}
/* End of Switch: '<Root>/Switch' */
/* Lookup_n-D: '<Root>/Table2' incorporates:
* Inport: '<Root>/In3'
* Inport: '<Root>/In4'
*/
ConfigurationRapidPrototyping_B.Table2 = look2_binlc
(ConfigurationRapidPrototyping_U.In3, ConfigurationRapidPrototyping_U.In4,
ConfigurationRapidPrototyping_P.Table2.BP1,
ConfigurationRapidPrototyping_P.Table2.BP2,
ConfigurationRapidPrototyping_P.Table2.Table,
ConfigurationRapidPrototyping_P.Table2_maxIndex, 3U);
/* Update for UnitDelay: '<Root>/Delay' */
ConfigurationRapidPrototypin_DW.X = ConfigurationRapidPrototyping_B.Table2;
}
/* Model initialize function */
void ConfigurationRapidPrototypingInterface_initialize(void)
{
/* Registration code */
/* initialize error status */
rtmSetErrorStatus(ConfigurationRapidPrototypin_M, (NULL));
/* block I/O */
(void) memset(((void *) &ConfigurationRapidPrototyping_B), 0,
sizeof(B_ConfigurationRapidPrototypi_T));
/* Storage classes */
output = 0.0;
/* states (dwork) */
(void) memset((void *)&ConfigurationRapidPrototypin_DW, 0,
sizeof(DW_ConfigurationRapidPrototyp_T));
/* exported global states */
mode = false;
/* external inputs */
(void)memset(&ConfigurationRapidPrototyping_U, 0, sizeof
(ExtU_ConfigurationRapidProtot_T));
/* Start for DataStoreMemory: '<Root>/Data Store Memory' */
mode = ConfigurationRapidPrototyping_P.DataStoreMemory_InitialValue;
/* InitializeConditions for UnitDelay: '<Root>/Delay' */
ConfigurationRapidPrototypin_DW.X =
ConfigurationRapidPrototyping_P.Delay_InitialCondition;
}
/* Model terminate function */
void ConfigurationRapidPrototypingInterface_terminate(void)
{
/* (no terminate code required) */
}
信号の値は、モデルの関数 step のコード アルゴリズムで計算されます。その後、それらの値が信号構造体のフィールドに代入されます。アルゴリズムによる計算には、パラメーター構造体のフィールドのパラメーター値が使用されます。
最適化からのデータ項目の除外
[信号ストレージの再利用] などのコード生成の最適化を選択する際、個々のデータ項目について、最適化しないで保持することができます。それらの項目に対しては、生成コードでアドレス可能メモリが割り当てられます。
前にクリアした最適化を選択します。
set_param('ConfigurationRapidPrototypingInterface','OptimizeBlockIOStorage','on') set_param('ConfigurationRapidPrototypingInterface','LocalBlockOutputs','on') set_param('ConfigurationRapidPrototypingInterface','DefaultParameterBehavior','Inlined')
1. [C コード] タブで、[コード インターフェイス]、[個々の要素コードのマッピング] を選択します。
2. コード マッピング エディターで [信号/状態] タブを検査します。
3. モデルで、Gain ブロックの出力信号を選択します。
4. 信号線の上または下に表示される省略記号上で一時停止してアクション バーを開きます。[信号の追加] ボタンをクリックします。コード マッピング エディターで [信号] ノードが展開され、追加した信号がリストされます。
cm = coder.mapping.api.get('ConfigurationRapidPrototypingInterface'); gain_ports = get_param('ConfigurationRapidPrototypingInterface/Gain','PortHandles'); gain_outPort = gain_ports.Outport; addSignal(cm,gain_outPort);
5. [ストレージ クラス] を Model default に設定して、Outport の既定のストレージ クラスを信号に適用します。
setSignal(cm,gain_outPort,'StorageClass','Model default','Identifier','Gain');
6. モデルで Gain ブロックを選択します。
7. プロパティ インスペクターで、ゲイン値をモデル ワークスペース パラメーター オブジェクト K1 に設定します。
8. コード マッピング エディターの [パラメーター] タブで [Model parameters] を展開します。
9. パラメーター K1 を選択します。[ストレージ クラス] を設定して、Auto 以外のストレージ クラスを適用します。たとえば、ストレージ クラス Model default を使用します。Model default を使用して、K1 はモデル パラメーター Default に対して指定された既定のストレージ クラスを取得し、グローバルなパラメーター構造体のフィールドとして表示されます。
set_param('ConfigurationRapidPrototypingInterface/Gain','Gain','K1'); setModelParameter(cm,'K1','StorageClass','Model default');
10. コードを生成します。
slbuild('ConfigurationRapidPrototypingInterface')
### Searching for referenced models in model 'ConfigurationRapidPrototypingInterface'. ### Total of 1 models to build. ### Starting build procedure for: ConfigurationRapidPrototypingInterface ### Successful completion of build procedure for: ConfigurationRapidPrototypingInterface Build Summary Top model targets: Model Build Reason Status Build Duration ===================================================================================================================== ConfigurationRapidPrototypingInterface Generated code was out of date. Code generated and compiled. 0h 0m 7.9358s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 9.1162s
11. コード生成レポートで、ファイル ConfigurationRapidPrototypingInterface.h を表示します。信号のデータを格納する構造体は、Gain ブロックのテスト ポイント出力を表すフィールド Gain のみを 1 つ定義しています。
file = fullfile('ConfigurationRapidPrototypingInterface_grt_rtw','ConfigurationRapidPrototypingInterface.h'); coder.example.extractLines(file,'/* Block signals (default storage) */',... 'B_ConfigurationRapidPrototypingInterface_T;',1,1)
/* Block signals (default storage) */
typedef struct {
real_T Gain; /* '<Root>/Gain' */
} B_ConfigurationRapidPrototypi_T;
/* Block states (default storage) for system '<Root>' */
typedef struct {
real_T X; /* '<Root>/Delay' */
} DW_ConfigurationRapidPrototyp_T;
/* External inputs (root inport signals with default storage) */
typedef struct {
real_T In1; /* '<Root>/In1' */
real_T input2; /* '<Root>/In2' */
real_T In3; /* '<Root>/In3' */
real_T In4; /* '<Root>/In4' */
} ExtU_ConfigurationRapidProtot_T;
/* Parameters (default storage) */
struct P_ConfigurationRapidPrototypi_T_ {
int8_T K1; /* Variable: K1
* Referenced by: '<Root>/Gain'
*/
};
/* Real-time Model Data Structure */
struct tag_RTM_ConfigurationRapidPro_T {
const char_T *errorStatus;
};
/* Block parameters (default storage) */
extern P_ConfigurationRapidPrototypi_T ConfigurationRapidPrototyping_P;
/* Block signals (default storage) */
extern B_ConfigurationRapidPrototypi_T ConfigurationRapidPrototyping_B;
/* Block states (default storage) */
extern DW_ConfigurationRapidPrototyp_T ConfigurationRapidPrototypin_DW;
/* External inputs (root inport signals with default storage) */
extern ExtU_ConfigurationRapidProtot_T ConfigurationRapidPrototyping_U;
/*
* Exported States
*
* Note: Exported states are block states with an exported global
* storage class designation. Code generation will declare the memory for these
* states and exports their symbols.
*
*/
extern boolean_T mode; /* '<Root>/Data Store Memory' */
/* Model entry point functions */
extern void ConfigurationRapidPrototypingInterface_initialize(void);
extern void ConfigurationRapidPrototypingInterface_step(void);
extern void ConfigurationRapidPrototypingInterface_terminate(void);
/* Exported data declaration */
/* Data with Exported storage */
extern real_T output; /* '<Root>/Out1' */
/* Real-time Model object */
extern RT_MODEL_ConfigurationRapidPr_T *const ConfigurationRapidPrototypin_M;
/*-
* The generated code includes comments that allow you to trace directly
* back to the appropriate location in the model. The basic format
* is <system>/block_name, where system is the system number (uniquely
* assigned by Simulink) and block_name is the name of the block.
*
* Use the MATLAB hilite_system command to trace the generated code back
* to the model. For example,
*
* hilite_system('<S3>') - opens system 3
* hilite_system('<S3>/Kp') - opens and selects block Kp which resides in S3
*
* Here is the system hierarchy for this model
*
* '<Root>' : 'ConfigurationRapidPrototypingInterface'
*/
#endif /* ConfigurationRapidPrototypingInterface_h_ */
ブロック パラメーターのデータを格納する構造体は、パラメーター オブジェクト K1 を表すフィールド K1 を 1 つ定義しています。
coder.example.extractLines(file,'/* Parameters (default storage) */',... '/* Real-time Model Data Structure */',1,0)
/* Parameters (default storage) */
struct P_ConfigurationRapidPrototypi_T_ {
int8_T K1; /* Variable: K1
* Referenced by: '<Root>/Gain'
*/
};
生成されたインターフェイスによるデータへのアクセス
標準化されたインターフェイスを介してモデル データにアクセスするために、生成コードに追加のコードやファイルを含めるように設定できます。たとえば、信号のデータをログに記録したり実行時にパラメーターを調整したりするには C API を使用します。
次のカスタム ソース コードを現在のフォルダーの ex_myHandCode.c という名前のファイルにコピーします。
#include "ex_myHandHdr.h"
#define paramIdx 0 /* Index of the target parameter,
determined by inspecting the array of structures generated by the C API. */
#define sigIdx 0 /* Index of the target signal,
determined by inspecting the array of structures generated by the C API. */
void tuneFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr)
{
/* Take action with the parameter value only at
the beginning of simulation and at the 5-second mark. */
if (*tPtr == 0 || *tPtr == 5) {
/* Local variables to store information extracted from
the model mapping information (mmi). */
void** dataAddrMap;
const rtwCAPI_DataTypeMap *dataTypeMap;
const rtwCAPI_ModelParameters *params;
int_T addrIdx;
uint16_T dTypeIdx;
uint8_T slDataType;
/* Use built-in C API macros to extract information. */
dataAddrMap = rtwCAPI_GetDataAddressMap(mmi);
dataTypeMap = rtwCAPI_GetDataTypeMap(mmi);
params = rtwCAPI_GetModelParameters(mmi);
addrIdx = rtwCAPI_GetModelParameterAddrIdx(params,paramIdx);
dTypeIdx = rtwCAPI_GetModelParameterDataTypeIdx(params,paramIdx);
slDataType = rtwCAPI_GetDataTypeSLId(dataTypeMap, dTypeIdx);
/* Handle data types 'double' and 'int8'. */
switch (slDataType) {
case SS_DOUBLE: {
real_T* dataAddress;
dataAddress = dataAddrMap[addrIdx];
/* At the 5-second mark, increment the parameter value by 1. */
if (*tPtr == 5) {
(*dataAddress)++;
}
printf("Parameter value is %f\n", *dataAddress);
break;
}
case SS_INT8: {
int8_T* dataAddress;
dataAddress = dataAddrMap[addrIdx];
if (*tPtr == 5) {
(*dataAddress)++;
}
printf("Parameter value is %i\n", *dataAddress);
break;
}
}
}
}
void logFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr)
{
/* Take action with the signal value only when
the simulation time is an integer value. */
if (*tPtr-(int_T)*tPtr == 0) {
/* Local variables to store information extracted from
the model mapping information (mmi). */
void** dataAddrMap;
const rtwCAPI_DataTypeMap *dataTypeMap;
const rtwCAPI_Signals *sigs;
int_T addrIdx;
uint16_T dTypeIdx;
uint8_T slDataType;
/* Use built-in C API macros to extract information. */
dataAddrMap = rtwCAPI_GetDataAddressMap(mmi);
dataTypeMap = rtwCAPI_GetDataTypeMap(mmi);
sigs = rtwCAPI_GetSignals(mmi);
addrIdx = rtwCAPI_GetSignalAddrIdx(sigs,sigIdx);
dTypeIdx = rtwCAPI_GetSignalDataTypeIdx(sigs,sigIdx);
slDataType = rtwCAPI_GetDataTypeSLId(dataTypeMap, dTypeIdx);
/* Handle data types 'double' and 'single'. */
switch (slDataType) {
case SS_DOUBLE: {
real_T* dataAddress;
dataAddress = dataAddrMap[addrIdx];
printf("Signal value is %f\n", *dataAddress);
break;
}
case SS_SINGLE: {
real32_T* dataAddress;
dataAddress = dataAddrMap[addrIdx];
printf("Signal value is %f\n", *dataAddress);
break;
}
}
}
}
2. 次のカスタム ヘッダー コードを現在のフォルダーの ex_myHandHdr.h という名前のファイルにコピーします。
#include <stdio.h> #include <string.h> #include <math.h> /* Include rtw_modelmap.h for definitions of C API macros. */ #include "rtw_modelmap.h" #include "builtin_typeid_types.h" #include "rtwtypes.h" void tuneFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr); void logFcn(rtwCAPI_ModelMappingInfo *mmi, time_T *tPtr);
これらのファイルでは、モデル例から生成したコードの信号やパラメーター データにアクセスするために C API を使用します。
3. モデル コンフィギュレーション パラメーター [インクルード ヘッダー] を [#include "ex_myHandHdr.h"] に、[ソース ファイル] を [ex_myHandCode.c] に設定します。
set_param('ConfigurationRapidPrototypingInterface','CustomHeaderCode','#include "ex_myHandHdr.h"') set_param('ConfigurationRapidPrototypingInterface','CustomSource','ex_myHandCode.c')
4. モデル コンフィギュレーション パラメーター [MAT ファイルのログ] を選択します。生成された実行可能ファイルは、シミュレーションの停止時間 (モデル コンフィギュレーション パラメーターで設定) までしか実行されません。
set_param('ConfigurationRapidPrototypingInterface','MatFileLogging','on')
5. C API モデル コンフィギュレーション パラメーター [パラメーター]、[信号]、[状態]、[ルートレベル I/O] を選択します。
set_param('ConfigurationRapidPrototypingInterface','RTWCAPIParams','on') set_param('ConfigurationRapidPrototypingInterface','RTWCAPISignals','on') set_param('ConfigurationRapidPrototypingInterface','RTWCAPIStates','on') set_param('ConfigurationRapidPrototypingInterface','RTWCAPIRootIO','on')
6. Custom Code ブロック ライブラリを読み込みます。
custcode

7. モデルに System Outputs ブロックを追加します。
add_block('custcode/System Outputs','ConfigurationRapidPrototypingInterface/System Outputs')
8. System Outputs ブロックのダイアログ ボックスで、[System Outputs Function 実行コード] を次のコードに設定します。
{
ConfigurationRapidPrototypingInterface_U.input2++;
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(ConfigurationRapidPrototypingInterface_M).mmi);
tuneFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M));
}9. ブロックのダイアログ ボックスで、[System Outputs Function 終了コード] を次のコードに設定します。
{
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo(ConfigurationRapidPrototypingInterface_M).mmi);
logFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M));
}または、System Outputs ブロックの設定のために、コマンド プロンプトで以下のコマンドを使用します。
temp.TLCFile = 'custcode'; temp.Location = 'System Outputs Function'; temp.Middle = sprintf(['{\nConfigurationRapidPrototyping_U.input2++;'... '\nrtwCAPI_ModelMappingInfo *MMI = '... '&(rtmGetDataMapInfo(ConfigurationRapidPrototypingInterface_M).mmi);'... '\ntuneFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M));\n}']); temp.Bottom = sprintf(['{\nrtwCAPI_ModelMappingInfo *MMI = '... '&(rtmGetDataMapInfo(ConfigurationRapidPrototypingInterface_M).mmi);'... '\nlogFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M));\n}']); set_param('ConfigurationRapidPrototypingInterface/System Outputs','RTWdata',temp)
10. コードを生成します。
slbuild('ConfigurationRapidPrototypingInterface')
### Searching for referenced models in model 'ConfigurationRapidPrototypingInterface'. ### Total of 1 models to build. ### Starting build procedure for: ConfigurationRapidPrototypingInterface ### Successful completion of build procedure for: ConfigurationRapidPrototypingInterface Build Summary Top model targets: Model Build Reason Status Build Duration ===================================================================================================================== ConfigurationRapidPrototypingInterface Generated code was out of date. Code generated and compiled. 0h 0m 11.235s 1 of 1 models built (0 models already up to date) Build duration: 0h 0m 11.763s
11. コード生成レポートで、インターフェイス ファイル ConfigurationRapidPrototypingInterface_capi.c を表示します。このファイルは、C API を介したデータ項目の処理に使用できる構造体の配列を初期化します。たとえば、構造体 rtBlockSignals の配列では、最初の構造体 (インデックス 0) は、モデルの Gain ブロックのテスト ポイント出力信号を表します。
file = fullfile('ConfigurationRapidPrototypingInterface_grt_rtw','ConfigurationRapidPrototypingInterface_capi.c'); coder.example.extractLines(file,'/* Block output signal information */',... '/* Individual block tuning',1,0)
/* Block output signal information */
static const rtwCAPI_Signals rtBlockSignals[] = {
/* addrMapIndex, sysNum, blockPath,
* signalName, portNumber, dataTypeIndex, dimIndex, fxpIndex, sTimeIndex
*/
{ 0, 0, TARGET_STRING("ConfigurationRapidPrototypingInterface/Gain"),
TARGET_STRING(""), 0, 0, 0, 0, 0 },
{
0, 0, (NULL), (NULL), 0, 0, 0, 0, 0
}
};
addrMapIndex などの構造体のフィールドは、信号の特性を表す rtDataAddrMap など他の構造体の配列のインデックスを示します。これらの特性には、信号データのアドレス (データへのポインター)、数値データ型および信号の次元が含まれます。
12. ファイル ConfigurationRapidPrototypingInterface.c で、モデルの関数 step のコード アルゴリズムを表示します。アルゴリズムでは、最初に System Outputs ブロックで指定したコードが実行されます。
file = fullfile('ConfigurationRapidPrototypingInterface_grt_rtw','ConfigurationRapidPrototypingInterface.c'); coder.example.extractLines(file,'/* user code (Output function Body) */',... '/* Logic: ''<Root>/LogOp'' incorporates:',1,0)
/* user code (Output function Body) */
/* System '<Root>' */
{
ConfigurationRapidPrototyping_U.input2++;
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo
(ConfigurationRapidPrototypingInterface_M).mmi);
tuneFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M));
}
/* DataStoreWrite: '<Root>/Data Store Write' incorporates:
* Constant: '<Root>/Constant1'
* Constant: '<Root>/Constant2'
* Inport: '<Root>/In1'
* Logic: '<Root>/LogOp'
* RelationalOperator: '<Root>/RelOp1'
* RelationalOperator: '<Root>/RelOp2'
*/
mode = ((ConfigurationRapidPrototyping_U.In1 > 10.0) ||
(ConfigurationRapidPrototyping_U.In1 < -10.0));
/* Gain: '<Root>/Gain' incorporates:
* Inport: '<Root>/In2'
* Lookup_n-D: '<Root>/Table1'
*/
ConfigurationRapidPrototyping_B.Gain = (real_T)
ConfigurationRapidPrototyping_P.K1 * look1_binlc
(ConfigurationRapidPrototyping_U.input2, rtCP_Table1_bp01Data,
rtCP_Table1_tableData, 10U);
/* Switch: '<Root>/Switch' incorporates:
* DataStoreRead: '<Root>/Data Store Read'
*/
if (mode) {
/* Outport: '<Root>/Out1' */
output = ConfigurationRapidPrototyping_B.Gain;
} else {
/* Outport: '<Root>/Out1' incorporates:
* UnitDelay: '<Root>/Delay'
*/
output = ConfigurationRapidPrototypin_DW.X;
}
/* End of Switch: '<Root>/Switch' */
/* Lookup_n-D: '<Root>/Table2' incorporates:
* Inport: '<Root>/In3'
* Inport: '<Root>/In4'
*/
rtb_Table2 = look2_binlc(ConfigurationRapidPrototyping_U.In3,
ConfigurationRapidPrototyping_U.In4, rtCP_Table2_bp01Data,
rtCP_Table2_bp02Data, rtCP_Table2_tableData, rtCP_Table2_maxIndex, 3U);
/* user code (Output function Trailer) */
/* System '<Root>' */
{
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo
(ConfigurationRapidPrototypingInterface_M).mmi);
logFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M));
}
/* Update for UnitDelay: '<Root>/Delay' */
ConfigurationRapidPrototypin_DW.X = rtb_Table2;
/* Matfile logging */
rt_UpdateTXYLogVars(ConfigurationRapidPrototypin_M->rtwLogInfo,
(&ConfigurationRapidPrototypin_M->Timing.taskTime0));
/* signal main to stop simulation */
{ /* Sample time: [1.0s, 0.0s] */
if ((rtmGetTFinal(ConfigurationRapidPrototypin_M)!=-1) &&
!((rtmGetTFinal(ConfigurationRapidPrototypin_M)-
ConfigurationRapidPrototypin_M->Timing.taskTime0) >
ConfigurationRapidPrototypin_M->Timing.taskTime0 * (DBL_EPSILON))) {
rtmSetErrorStatus(ConfigurationRapidPrototypin_M, "Simulation finished");
}
}
/* Update absolute time for base rate */
/* The "clockTick0" counts the number of times the code of this task has
* been executed. The absolute time is the multiplication of "clockTick0"
* and "Timing.stepSize0". Size of "clockTick0" ensures timer will not
* overflow during the application lifespan selected.
* Timer of this task consists of two 32 bit unsigned integers.
* The two integers represent the low bits Timing.clockTick0 and the high bits
* Timing.clockTickH0. When the low bit overflows to 0, the high bits increment.
*/
if (!(++ConfigurationRapidPrototypin_M->Timing.clockTick0)) {
++ConfigurationRapidPrototypin_M->Timing.clockTickH0;
}
ConfigurationRapidPrototypin_M->Timing.taskTime0 =
ConfigurationRapidPrototypin_M->Timing.clockTick0 *
ConfigurationRapidPrototypin_M->Timing.stepSize0 +
ConfigurationRapidPrototypin_M->Timing.clockTickH0 *
ConfigurationRapidPrototypin_M->Timing.stepSize0 * 4294967296.0;
}
/* Model initialize function */
void ConfigurationRapidPrototypingInterface_initialize(void)
{
/* Registration code */
/* initialize non-finites */
rt_InitInfAndNaN(sizeof(real_T));
/* initialize real-time model */
(void) memset((void *)ConfigurationRapidPrototypin_M, 0,
sizeof(RT_MODEL_ConfigurationRapidPr_T));
rtmSetTFinal(ConfigurationRapidPrototypin_M, 10.0);
ConfigurationRapidPrototypin_M->Timing.stepSize0 = 1.0;
/* Setup for data logging */
{
static RTWLogInfo rt_DataLoggingInfo;
rt_DataLoggingInfo.loggingInterval = (NULL);
ConfigurationRapidPrototypin_M->rtwLogInfo = &rt_DataLoggingInfo;
}
/* Setup for data logging */
{
rtliSetLogXSignalInfo(ConfigurationRapidPrototypin_M->rtwLogInfo, (NULL));
rtliSetLogXSignalPtrs(ConfigurationRapidPrototypin_M->rtwLogInfo, (NULL));
rtliSetLogT(ConfigurationRapidPrototypin_M->rtwLogInfo, "");
rtliSetLogX(ConfigurationRapidPrototypin_M->rtwLogInfo, "");
rtliSetLogXFinal(ConfigurationRapidPrototypin_M->rtwLogInfo, "");
rtliSetLogVarNameModifier(ConfigurationRapidPrototypin_M->rtwLogInfo, "rt_");
rtliSetLogFormat(ConfigurationRapidPrototypin_M->rtwLogInfo, 0);
rtliSetLogMaxRows(ConfigurationRapidPrototypin_M->rtwLogInfo, 1000);
rtliSetLogDecimation(ConfigurationRapidPrototypin_M->rtwLogInfo, 1);
rtliSetLogY(ConfigurationRapidPrototypin_M->rtwLogInfo, "");
rtliSetLogYSignalInfo(ConfigurationRapidPrototypin_M->rtwLogInfo, (NULL));
rtliSetLogYSignalPtrs(ConfigurationRapidPrototypin_M->rtwLogInfo, (NULL));
}
/* block I/O */
(void) memset(((void *) &ConfigurationRapidPrototyping_B), 0,
sizeof(B_ConfigurationRapidPrototypi_T));
/* Storage classes */
output = 0.0;
/* states (dwork) */
(void) memset((void *)&ConfigurationRapidPrototypin_DW, 0,
sizeof(DW_ConfigurationRapidPrototyp_T));
/* exported global states */
mode = false;
/* external inputs */
(void)memset(&ConfigurationRapidPrototyping_U, 0, sizeof
(ExtU_ConfigurationRapidProtot_T));
/* Initialize DataMapInfo substructure containing ModelMap for C API */
ConfigurationRapidPrototypingInterface_InitializeDataMapInfo();
/* Matfile logging */
rt_StartDataLoggingWithStartTime(ConfigurationRapidPrototypin_M->rtwLogInfo,
0.0, rtmGetTFinal(ConfigurationRapidPrototypin_M),
ConfigurationRapidPrototypin_M->Timing.stepSize0, (&rtmGetErrorStatus
(ConfigurationRapidPrototypin_M)));
/* Start for DataStoreMemory: '<Root>/Data Store Memory' */
mode = false;
/* InitializeConditions for UnitDelay: '<Root>/Delay' */
ConfigurationRapidPrototypin_DW.X = 0.0;
}
/* Model terminate function */
void ConfigurationRapidPrototypingInterface_terminate(void)
{
/* (no terminate code required) */
}
このコードでは最初に、関数 step が実行されるたびに信号の値をインクリメントして入力信号 input2 に摂動を与えます。その後、コードは組み込みのマクロ rtmGetDataMapInfo を使用して、モデル データ構造体 ConfigurationRapidPrototypingInterface_M からモデル マッピング情報を抽出します。ポインター MMI は抽出されたマッピング情報をポイントします。これにより、関数 tuneFcn および関数 logFcn は、C API ファイル ConfigurationRapidPrototypingInterface_capi.c で定義されている構造体の配列に含まれる情報にアクセスできます。
13. ファイル ex_myHandCode.c の関数 tuneFcn を表示します。この関数は、C API (モデル マッピング情報 mmi を介して) およびシミュレーション時間へのポインターを使用して、コード実行中の特定の時間にパラメーター K1 の値を出力します。シミュレーション時間が 5 秒に達すると、関数はメモリ内のパラメーター値を変更します。switch case ブロックを使用することで、関数はデータ型が int8 または double のどちらでも、パラメーター データにアクセスできます。
14. モデルの関数 step のコード アルゴリズムをもう一度表示します。関数の終わりに近づくと、アルゴリズムは System Outputs ブロックで指定したコードを実行します。このコードは関数 logFcn を呼び出します。
coder.example.extractLines(file,'/* user code (Output function Trailer) */',... '/* Matfile logging */',1,0)
/* user code (Output function Trailer) */
/* System '<Root>' */
{
rtwCAPI_ModelMappingInfo *MMI = &(rtmGetDataMapInfo
(ConfigurationRapidPrototypingInterface_M).mmi);
logFcn(MMI, rtmGetTPtr(ConfigurationRapidPrototypingInterface_M));
}
/* Update for UnitDelay: '<Root>/Delay' */
ConfigurationRapidPrototypin_DW.X = rtb_Table2;
15. ファイル ex_myHandCode.c の関数 logFcn を表示します。この関数は C API を使用してテスト ポイントされた信号の値を出力します。関数は、データ型が single または double のどちらでも信号データにアクセスできます。
16. コマンド プロンプトで、生成された実行可能ファイル ConfigurationRapidPrototypingInterface.exe を実行します。
system('ConfigurationRapidPrototypingInterface')
パラメーターと信号値がコマンド ウィンドウの出力に表示されます。
C API などのデータ インターフェイスの詳細については、生成されたコードのインターフェイスを参照してください。
参考
Simulink.Parameter | Simulink.Signal | Simulink.Signal | System Outputs