S-function: In which initialization callback function is the input data available to use?

3 ビュー (過去 30 日間)
Bengt-Arne
Bengt-Arne 2011 年 9 月 6 日
コメント済み: Egambaravel 2013 年 11 月 18 日
I need to initialize my C S-function by calling an external DLL function. Before I call my initialization function, I need to get the input port values. In which callback function, can I get the input values and use them to initialize my model?
I have created a test S-function that prints the input data from the different callback functions (See the code below). Try to connect constant blocks to the input ports with the data type conversion block in between. Then you see that the real input port data is set already in mdlStart but the integer and boolean is not. The input port data is always available from mdlOutput.
But mdlOutput is not a good initialization functions? Then I need to add a flag that keep track if it was the first time it was called + all input ports must have direct feedthrough, which is not my case.
Does anyone have any suggestion for how I could solve this problem?
#define S_FUNCTION_NAME testinput
#define S_FUNCTION_LEVEL 2
#include "simstruc.h"
static void printInputs(SimStruct *S, char* cbfunname)
{
InputInt32PtrsType int_ptr;
InputRealPtrsType real_ptr;
InputBooleanPtrsType bool_ptr;
if (ssGetT(S)<0.1) {
printf("%s time=%16.16lf\n",cbfunname,ssGetT(S));
real_ptr=(InputRealPtrsType)ssGetInputPortSignalPtrs(S,0);
int_ptr=(InputInt32PtrsType)ssGetInputPortSignalPtrs(S,1);
bool_ptr=(InputBooleanPtrsType)ssGetInputPortSignalPtrs(S,2);
//ssGetInputPortConnected(S,0)?"TRUE":"FALSE"
printf("%s REAL = %lf\n",cbfunname,*real_ptr[0]);
printf("%s INTEGER = %d\n",cbfunname,*int_ptr[0]);
printf("%s BOOLEAN = %s\n",cbfunname,*bool_ptr[0]?"TRUE":"FALSE");
}
}
static void mdlInitializeSizes(SimStruct *S)
{
ssSetNumInputPorts(S, 3);
ssSetInputPortWidth( S, 0, 1 ); /* Real */
ssSetInputPortWidth( S, 1, 1 ); /* Integer */
ssSetInputPortWidth( S, 2, 1 ); /* Boolean */
ssSetInputPortDataType( S, 0, SS_DOUBLE );
ssSetInputPortDataType( S, 1, SS_INT32 );
ssSetInputPortDataType( S, 2, SS_BOOLEAN );
ssSetInputPortDirectFeedThrough( S, 0, 1 );
ssSetInputPortDirectFeedThrough( S, 1, 1 );
ssSetInputPortDirectFeedThrough( S, 2, 1 );
ssSetNumNonsampledZCs(S,1);
} /* end mdlInitializeSizes */
static void mdlInitializeSampleTimes(SimStruct *S)
{
ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetOffsetTime(S, 0, 0.0);
//printInputs(S,"mdlInitializeSampleTimes");
} /* end mdlInitializeSampleTimes */
#define MDL_INITIALIZE_CONDITIONS /* Change to #undef to remove function */
static void mdlInitializeConditions(SimStruct *S)
{
printInputs(S,"mdlInitializeConditions");
}
#define MDL_START /* Change to #undef to remove function */
static void mdlStart(SimStruct *S)
{
printInputs(S,"mdlStart");
}
static void mdlOutputs(SimStruct *S, int_T tid)
{
printInputs(S,"mdlOutputs");
} /* end mdlOutputs */
#define MDL_ZERO_CROSSINGS /* Change to #undef to remove function */
static void mdlZeroCrossings(SimStruct *S)
{
printInputs(S,"mdlZeroCrossings");
}
#define MDL_UPDATE /* Change to #undef to remove function */
static void mdlUpdate(SimStruct *S, int_T tid)
{
printInputs(S,"mdlUpdate");
}
#define MDL_DERIVATIVES /* Change to #undef to remove function */
static void mdlDerivatives(SimStruct *S)
{
printInputs(S,"mdlDerivatives");
}
static void mdlTerminate(SimStruct *S)
{
printf("mdlTerminate\n");
} /* end mdlTerminate */
#ifdef MATLAB_MEX_FILE /* Is this file being compiled as a MEX-file? */
# include "simulink.c" /* MEX-file interface mechanism */
#else
# include "cg_sfun.h" /* Code generation registration function */
#endif

回答 (2 件)

Kaustubha Govind
Kaustubha Govind 2011 年 9 月 6 日
The inputs to an S-function are only reliably available in the mdlOutputs method. The inputs to any block are the outputs of other blocks which first need to be executed before their outputs are available. This is not guaranteed to be done until the mdlOutputs method of each block starts executing.
If you need to do some library initialization based on the values of the inputs at t=0, I recommend creating a boolean DWork state to represent an "isInitialized" flag - set this to true after the first time mdlOutputs is called and your library is initialized. For subsequent calls to mdlOutputs, this flag would be true, so the library initialization should be conditional on this value.

Bengt-Arne
Bengt-Arne 2011 年 9 月 6 日
Thanks alot, but how should I then handle non direct feedthrough input ports? They are, as you know I guess=), not available from mdlOutput. Setting them to direct feedthrough is not the best solution in my case, since it may cause unneccesary algebraic loops. Maybe mdlUpdate would be a better place to initialize then. And in that case, I have to create some "dummy" outputs at time 0 in mdlOutputs.
  3 件のコメント
Bengt-Arne
Bengt-Arne 2011 年 11 月 3 日
According to this site, http://www.mathworks.se/help/toolbox/simulink/sfg/f8-37326.html, the mdlUpdate is called after mdlOutputs. I therefore have to produce some "dummy" output values in mdlOutputs the first time it is called.
Egambaravel
Egambaravel 2013 年 11 月 18 日
I have similar problem executing my S-function. I need to get the S-function output based on the input values at time = 0 (without initialization, the S-function should work). When I declare all inputs as Feedthrough the S-function runs for a while (time 0 to 200 s say) and throws error after that.
mdlupdate code always starts with some initialization and hence not useful for me.
Therefore the same question how to handle Feedthrough = 0 in mdloutput.
One more question: i am not able to pass the integer signals in loop (Feedthrough as 1). any idea.

サインインしてコメントする。

製品

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by