Guy on Simulink

Simulink & Model-Based Design

Stateflow Active State Output

This week, Corey Lagunowich is here to talk about a very useful Stateflow feature, the Active State Output.

Active State Output

Did you know that with Stateflow, it is possible to monitor which state is currently active, and use that information in the rest of the Simulink model? This feature is named Active State Output. The screenshot below shows how to do this for one of the charts in the example Temporal Logic Using the AT Function.

Enabling Active State Output

The checkbox creates a new output port on your chart block, whose value (in simulation) is of an enumerated type with values that match the names of the child states.

When doing this for a chart with parallel decomposition, Active State Output needs to be enabled for each parallel state individually, and each parallel state has a separate corresponding output port. (The sf_car demonstration uses this to output the current gear selected by the shift logic to its transmission model).

We can also take advantage of this feature in order to accomplish something special in the code generated from Stateflow charts.

Stateflow States in Generated Code  (Default Behavior)

When using Embedded Coder to generate code from Stateflow charts, by default the states of the chart are created as macros using the #define directive. For example, here is a snippet from the generated code from the chart shown above.

/* Named constants for Chart: '<Root>/Temporal Logic' */ #define sf_tlat_IN_NO_ACTIVE_CHILD ((uint8_T)0U) #define sf_tlat_IN_State ((uint8_T)1U) /* Named constants for Chart: '<Root>/Without Temporal Logic' */ #define sf_tlat_IN_A ((uint8_T)1U) #define sf_tlat_IN_B ((uint8_T)2U) #define sf_tlat_IN_C ((uint8_T)3U)

The macros are grouped together by chart under an identifying comment line, but there is no intrinsic distinction as to which chart they belong to.

Stateflow States as Enums

So what if you would like to have a more organized grouping? Specifically, what if you would like to have your states be members of an enumeration?

As you might have guessed, we need to enable Active State Output. But we need to do two more things in order to get this enumeration in a nice, clean, standalone form. First, open the signal properties for the signal coming from the Active State Output port and give the signal a name. Second, set the signal’s storage class (under the Code Generation tab) to ExportedGlobal.

Configuring Generated Code for Active State Output

Now, in the *_types.h generated code file, there will be an enumeration definition, like so:

typedef enum { listofStates_None = 0, /* Default value */ listofStates_A, listofStates_B, listofStates_C } listofStates;

And in the generated c code for the model, macros for the chart  are no longer defined; rather, a global (with the name of the signal) is declared of type listOfStates:

/* Exported block signals */ listofStates currentState; /* '<Root>/Without Temporal Logic' */

Further down in that c code file, you will find a switch-case statement that implements the logic of the Without Temporal Logic chart, like so:

switch (currentState) { case listofStates_A: ... break; case listofStates_B: ... break; default: ... break;

One Last Note

When you enable Active State Output, you can also check the “Define enumerated type manually” box and click on the helpful hyperlink to automatically create a template m-file that defines the enumerated type.

At the top of this file you will find an enumeration declaration with a list of all the state names. Tempting as it may be, you cannot change these names here unless you also change them in the chart itself. However, you can use this file to change some other behaviors using the methods that follow (but that’s a blog post for another day).

Now it's your turn

Are you already using the active state output? Give this a try and let us know what you think by leaving a comment here.

|
  • print
  • send email

Comments

To leave a comment, please click here to sign in to your MathWorks Account or create a new one.