Products & Services Solutions Academia Support User Community Company

Learn more about Simulink   

Sample Times

About Sample Times

You can specify the sample-time behavior of your S-functions in mdlInitializeSampleTimes. Your S-function can inherit its rates from the blocks that drive it or define its own rates.

You can specify your S-function's rates (i.e., sample times) as

With block-based sample times, the S-function specifies a set of operating rates for the block as a whole during the initialization phase of the simulation. With port-based sample times, the S-function specifies a sample time for each input and output port individually during initialization. During the simulation phase, with block-based sample times, the S-function processes all inputs and outputs each time a sample hit occurs for the block. By contrast, with port-based sample times, the block processes a particular port only when a sample hit occurs for that port.

For example, consider two sample rates, 0.5 and 0.25 seconds, respectively:

You should use port-based sample times if your application requires unequal sample rates for input and output execution or if you do not want the overhead associated with running input and output ports at the highest sample rate of your block.

In some applications, an S-Function block might need to operate internally at one or more sample rates while inputting or outputting signals at other rates. The hybrid block- and port-based method of specifying sample rates allows you to create such blocks.

In typical applications, you specify only one block-based sample time. Advanced S-functions might require the specification of port-based or multiple block sample times.

Block-Based Sample Times

Level-2 M-file S-functions specify block-based sample times in their setup method. Use the line

block.SampleTimes = [sampleTime offsetTime];

to specify the sample time. Use a value of [-1 0] to indicate an inherited sample time. See How to Specify the Sample Time in Using Simulink for a complete list of valid sample times.

C MEX S-functions specify block-based sample time information in

The next two sections discuss how to specify block-based sample times for C MEX S-functions. A third section presents a simple example that shows how to specify sample times in mdlInitializeSampleTimes. For a detailed example, see mixedm.c.

Specifying the Number of Sample Times in mdlInitializeSizes

To configure your S-function for block-based sample times, use

ssSetNumSampleTimes(S,numSampleTimes);

where numSampleTimes > 0. This tells the Simulink engine that your S-function has block-based sample times. the engine calls mdlInitializeSampleTimes, which in turn sets the sample times.

Setting Sample Times and Specifying Function Calls in mdlInitializeSampleTimes

mdlInitializeSampleTimes specifies two pieces of execution information:

You specify the sample times as pairs [sample_time, offset_time], using these macros

ssSetSampleTime(S, sampleTimePairIndex, sample_time)
ssSetOffsetTime(S, offsetTimePairIndex, offset_time)

where sampleTimePairIndex and offsetTimePairIndex starts at 0.

The valid sample time pairs are (uppercase values are macros defined in simstruc.h):

[CONTINUOUS_SAMPLE_TIME,  0.0                       ]
[CONTINUOUS_SAMPLE_TIME,  FIXED_IN_MINOR_STEP_OFFSET]
[discrete_sample_period,  offset                    ]
[VARIABLE_SAMPLE_TIME  ,  0.0                       ]

Alternatively, you can specify that the sample time is inherited from the driving block, in which case the S-function can have only one sample time pair,

[INHERITED_SAMPLE_TIME,  0.0                       ]

or

[INHERITED_SAMPLE_TIME,  FIXED_IN_MINOR_STEP_OFFSET]

The following guidelines might help in specifying sample times:

If your function has no intrinsic sample time, you must indicate that it is inherited according to the following guidelines:

To check for a sample hit during execution (in mdlOutputs or mdlUpdate), use the ssIsSampleHit or ssIsContinuousTask macro. For example, use the following code fragment to check for a continuous sample hit:

if (ssIsContinuousTask(S,tid)) {
}

To determine whether the third (discrete) task has a hit, use the following code fragment:

if (ssIsSampleHit(S,2,tid) {
}

The Simulink engine always assigns an index of 0 to the continuous sample rate, if it exists, however you get incorrect results if you use ssIsSampleHit(S,0,tid).

Example: mdlInitializeSampleTimes

This example specifies that there are two discrete sample times with periods of 0.01 and 0.5 seconds.

static void mdlInitializeSampleTimes(SimStruct *S)
{
  ssSetSampleTime(S, 0, 0.01);
  ssSetOffsetTime(S, 0, 0.0);
  ssSetSampleTime(S, 1, 0.5);
  ssSetOffsetTime(S, 1, 0.0);
} /* End of mdlInitializeSampleTimes. */

Specifying Port-Based Sample Times

Port-based sample times cannot be used with S-functions that have neither input ports nor output ports. If an S-function uses port-based sample times and has no ports, the S-function produces errors when the Simulink model is updated or run. If the number of input or output ports on an S-function is variable, extra protection should be added into the S-function to ensure the total number of ports does not go to zero.

To use port-based sample times in a Level-2 M-file S-function:

To use port-based sample times in your C MEX S-function, you must specify the number of sample times as port-based in the S-function's mdlInitializeSizes method:

ssSetNumSampleTimes(S, PORT_BASED_SAMPLE_TIMES)

You must also specify the sample time of each input and output port in the S-function's mdlInitializeSizes method, using the following macros

ssSetInputPortSampleTime(S, idx, period)
ssSetInputPortOffsetTime(S, idx, offset)
ssSetOutputPortSampleTime(S, idx, period)
ssSetOutputPortOffsetTime(S, idx, offset)

The call to ssSetNumSampleTimes can be placed before or after the port-based sample times are actually specified in mdlInitializeSizes. However, if ssSetNumSampleTimes does not configure the S-function to use port-based sample times, any sample times set on the ports will be ignored.

For any given port, you can specify

Specifying Inherited Sample Time for a Port

In a Level-2 M-file S-function, use a value of [-1 0] for the SampleTime property of each port to specify that the port inherits its sample time.

To specify that a port's sample time is inherited in a C MEX S-function, the mdlInitializeSizes method should set its period to -1 and its offset to 0. For example, the following code specifies inherited sample time for a C MEX S-function's first input port:

ssSetInputPortSampleTime(S, 0, -1);
ssSetInputPortOffsetTime(S, 0, 0);

When you specify port-based sample times, the Simulink engine calls mdlSetInputPortSampleTime and mdlSetOutputPortSampleTime to determine the rates of inherited signals.

Once all rates have been determined, the engine calls mdlInitializeSampleTimes. Even though there is no need to initialize port-based sample times at this point, the engine invokes this method to give your S-function an opportunity to configure function-call connections. Your S-function must thus provide an implementation for this method regardless of whether it uses port-based sample times or function-call connections. Although you can provide an empty implementation, you might want to use it to check the appropriateness of the sample times that the block inherited during sample time propagation. Use ssGetInputPortSampleTime and ssGetOutputPortSampleTime in mdlInitializeSampleTimes to obtain the values of the inherited sample times. For example, the following code in mdlInitializeSampleTimes checks if the S-function's first input inherited a continuous sample time.

if (!ssGetInputPortSampleTime(S,0) {
    ssSetErrorStatus(S,"Cannot inherit a continuous sample time.");
}

Specifying Constant Sample Time for a Port

If your S-function uses port-based sample times, it can specify that any of its ports has a constant sample time. This means that the signal entering or leaving the port never changes from its initial value at the start of the simulation.

In a Level-2 M-file S-function, use the following line of code to specify a constant port-based sample time:

block.OutputPort(1).SampleTime = [inf 0];

The Simulink engine determines if a constant sample time is valid during sample-time propagation.

For C MEX S-functions, before specifying a constant sample time for an output port whose output depends on the S-function's parameters, the S-function should use ssGetInlineParameters to check whether the Inline parameters option on the Optimization pane of the Configuration parameters dialog box is on. If this option is not selected, you can change the values the S-function's parameters and hence its outputs during the simulation. In this case, the S-function can not specify a constant sample time for any ports whose outputs depend on the S-function's parameters.

To specify constant sample time for a port, the S-function must perform the following tasks

See sfun_port_constant.c, the source file for the sfcndemo_port_constant demo, for an example of how to create ports with a constant sample time.

Configuring Port-Based Sample Times for Use in Triggered Subsystems

Level-2 M-file S-functions with port-based sample times cannot be placed in a triggered subsystem. You must modify your S-function to use block-based sample times if you need to include it in a triggered subsystem.

To use a C MEX S-function in a triggered subsystem, your port-based sample time S-function must perform the following tasks.

See sfun_port_triggered.c, the source file for the sfcndemo_port_triggered.mdl demo model, for an example of how to create an S-function that can be used in a triggered subsystem.

Hybrid Block-Based and Port-Based Sample Times

The hybrid method of assigning sample times combines the block-based and port-based methods. You first specify, in mdlInitializeSizes, the total number of rates at which your block operates, including both block and input and output rates, using ssSetNumSampleTimes.

You then set the SS_OPTION_PORT_SAMPLE_TIMES_ASSIGNED option, using ssSetOptions, to tell the simulation engine that you are going to use the port-based method to specify the rates of the input and output ports individually. Next, as in the block-based method, you specify the periods and offsets of all of the block's rates, both internal and external, using

ssSetSampleTime
ssSetOffsetTime

Finally, as in the port-based method, you specify the rates for each port, using

ssSetInputPortSampleTime(S, idx, period)
ssSetInputPortOffsetTime(S, idx, offset)
ssSetOutputPortSampleTime(S, idx, period)
ssSetOutputPortOffsetTime(S, idx, offset)

Note that each of the assigned port rates must be the same as one of the previously declared block rates. For an example S-function, see mixedm.c.

Level-2 M-file S-functions do not support hybrid block-based and port-based sample times.

Multirate S-Function Blocks

In a multirate S-Function block, you can encapsulate the code that defines each behavior in the mdlOutputs and mdlUpdate functions with a statement that determines whether a sample hit has occurred. In a C MEX S-function, the ssIsSampleHit macro determines whether the current time is a sample hit for a specified sample time. The macro has this syntax:

ssIsSampleHit(S, st_index, tid)

where S is the SimStruct, st_index identifies a specific sample time index, and tid is the task ID (tid is an argument to the mdlOutputs and mdlUpdate functions).

For example, these statements in a C MEX S-function specify three sample times: one for continuous behavior and two for discrete behavior.

ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
ssSetSampleTime(S, 1, 0.75);
ssSetSampleTime(S, 2, 1.0);

In the mdlUpdate function, the following statement encapsulates the code that defines the behavior for the sample time of 0.75 second.

if (ssIsSampleHit(S, 1, tid)) {
}

The second argument, 1, corresponds to the second sample time, 0.75 second.

Use the following lines to encapsulate the code that defines the behavior for the continuous sample hit:

if (ssIsContinuousTask(S,tid)) {
}

In a Level-2 M-file S-function, use the IsSampleHit method to determine whether the current simulation time is one at which a task handled by this block is active.

Example of Defining a Sample Time for a Continuous Block

This example defines a sample time for a block that is continuous.

/* Initialize the sample time and offset. */
static void mdlInitializeSampleTimes(SimStruct *S)
{
  ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
  ssSetOffsetTime(S, 0, 0.0);
}

You must add this statement to the mdlInitializeSizes function.

ssSetNumSampleTimes(S, 1);

Example of Defining a Sample Time for a Hybrid Block

This example defines sample times for a hybrid S-Function block.

/* Initialize the sample time and offset. */
static void mdlInitializeSampleTimes(SimStruct *S)
{
  /* Continuous state sample time and offset. */
  ssSetSampleTime(S, 0, CONTINUOUS_SAMPLE_TIME);
  ssSetOffsetTime(S, 0, 0.0);

  /* Discrete state sample time and offset. */
  ssSetSampleTime(S, 1, 0.1);
  ssSetOffsetTime(S, 1, 0.025);
}

In the second sample time, the offset causes the Simulink engine to call the mdlUpdate function at these times: 0.025 second, 0.125 second, 0.225 second, and so on, in increments of 0.1 second.

The following statement, which indicates how many sample times are defined, also appears in the mdlInitializeSizes function.

ssSetNumSampleTimes(S, 2);

Multirate S-Functions and Sample Time Hit Calculations

For fixed-step solvers, Simulink uses integer arithmetic, rather than floating-point arithmetic, to calculate the sample time hits. Consequently, task times are integer multiples of their corresponding sample time periods.

This calculation method becomes important if you consider performing Boolean logic based upon task times in multirate S-functions. For example, consider an S-function that has two sample times. The fact that (ssIsSampleHit(S, idx1) == true && ssIsSampleHit(S,idx2) == true, does not guarantee that ssGetTaskTime(S, idx1) == ssGetTaskTime(S, idx2).

Synchronizing Multirate S-Function Blocks

If tasks running at different rates need to share data, you must ensure that data generated by one task is valid when accessed by another task running at a different rate. You can use the ssIsSpecialSampleHit macro in the mdlUpdate or mdlOutputs routine of a multirate S-function to ensure that the shared data is valid. This macro returns true if a sample hit has occurred at one rate and a sample hit has also occurred at another rate in the same time step. It thus permits a higher rate task to provide data needed by a slower rate task at a rate the slower task can accommodate.

Suppose, for example, that your model has an input port operating at one rate (with a sample time index of 0) and an output port operating at a slower rate (with a sample time index of 1). Further, suppose that you want the output port to output the value currently on the input. The following example illustrates usage of this macro.

if (ssIsSampleHit(S, 0, tid) {
  if (ssIsSpecialSampleHit(S, 0, 1, tid) {
     /* Transfer input to output memory. */
     ...
  }
}

if (ssIsSampleHit(S, 1, tid) {
   /* Emit output. */
   ...
}

In this example, the first block runs when a sample hit occurs at the input rate. If the hit also occurs at the output rate, the block transfers the input to the output memory. The second block runs when a sample hit occurs at the output rate. It transfers the output in its memory area to the block's output.

Note that higher-rate tasks always run before slower-rate tasks. Thus, the input task in the preceding example always runs before the output task, ensuring that valid data is always present at the output port.

In a Level-2 M-file S-function, use the IsSpecialSampleHit method to determine whether the current simulation time is one at which multiple tasks implemented by this block are active.

Specifying Model Reference Sample Time Inheritance

If your C MEX S-function inherits its sample times from the blocks that drive it, it should specify whether submodels containing your S-function can inherit sample times from their parent model. If the S-function's output does not depend on its inherited sample time, use the ssSetModelReferenceSampleTimeInheritanceRule macro to set the S-function's sample time inheritance rule to USE_DEFAULT_FOR_DISCRETE_INHERITANCE. Otherwise, set the rule to DISALLOW_SAMPLE_TIME_INHERITANCE to disallow sample-time inheritance for submodels that include S-functions whose outputs depend on their inherited sample time and thereby avoid inadvertent simulation errors.

If you are uncertain whether an existing S-function's output depends on its inherited sample time, check whether it invokes any of the following C macros:

or TLC functions:

If your S-function does not invoke any of these macros or functions, its output does not depend on its inherited sample time and hence it is safe to use in submodels that inherit their sample time.

Sample-Time Inheritance Rule Example

As an example of an S-function that precludes a submodel from inheriting its sample time, consider an S-function that has the following mdlOutputs method:

static void mdlOutputs(SimStruct *S, int_T tid) {
    const real_T *u = (const real_T*) 
    ssGetInputPortSignal(S,0);
    real_T       *y = ssGetOutputPortSignal(S,0);
    y[0] = ssGetSampleTime(S,tid) * u[0];
}

The output of this S-function is its inherited sample time, hence its output depends on its inherited sample time, and hence it is unsafe to use in a submodel. For this reason, this S-function should specify its model reference inheritance rule as follows:

ssSetModelReferenceSampleTimeInheritanceRule
(S, DISALLOW_SAMPLE_TIME_INHERITANCE);
  


Related Products & Applications

Learn more about Simulink through this collection of videos, articles, technical literature and the Getting Started with Simulink Guide.

 © 1984-2009- The MathWorks, Inc.    -   Site Help   -   Patents   -   Trademarks   -   Privacy Policy   -   Preventing Piracy   -   RSS