You can detect changes in Stateflow^{®} data from one time step to the next time step. All charts can detect changes on chart input data. C charts can also detect changes in chart output data, local chart variables, machine-parented variables, and data store memory data.
For each of these types of data, you can use operators that detect the following changes.
Type of Change | Operator |
---|---|
Data changes value from the beginning of the last time step to the beginning of the current time step. |
See hasChanged Operator. |
Data changes from a specified value at the beginning of the last time step to a different value at the beginning of the current time step. | |
Data changes to a specified value at the beginning of the current time step from a different value at the beginning of the last time step. |
Change detection operators return 1 if the data value changes or 0 if there is no change. See Change Detection Operators.
Stateflow software ships with a model sf_tetris2
that shows how you
can detect asynchronous changes in inputs — in this case, user keystrokes — to
manipulate a Tetris shape as it moves through the playing field. The chart TetrisLogic
implements this logic:
TetrisLogic contains a subchart called Moving that calls the operator
hasChanged
to determine when users press any of the Tetris control
keys, and then moves the shape accordingly. Here is a look inside the subchart:
To run the model, follow these steps:
Open the model by typing sf_tetris2
at the MATLAB^{®} prompt.
Start simulation.
A chart detects changes in chart data by evaluating values at time step boundaries. That is, the chart compares the value at the beginning of the previous execution step with the value at the beginning of the current execution step. To detect changes, the chart automatically double-buffers these values in local variables, as follows:
Local Buffer: | Stores: |
---|---|
var_name |
Value of data at the beginning of the last time step |
var_name |
Value of data at the beginning of the current time step |
Double-buffering occurs once per time step except if multiple input events occur in the same time step. Then, double-buffering occurs once per input event (see Handle Changes When Multiple Input Events Occur).
When you invoke change detection operations in an action, Stateflow software performs the following operations:
Double-buffers data values after a Simulink^{®} event triggers the chart, but before the chart begins execution.
Compares values in _prev
and _start
buffers.
If the values match, the change detection operator returns 0 (no change); otherwise,
it returns 1 (change).
The following diagram places these tasks in the context of the chart life cycle:
The fact that buffering occurs before chart execution has implications for change detection in the following scenarios:
Stateflow software attempts to filter out transient changes in local chart variables by evaluating their values only at time boundaries (see How Change Detection Works). This behavior means that the software evaluates the specified local variable only once at the end of the execution step and, therefore, returns a consistent result. That is, the return value remains constant even if the value of the local variable fluctuates within a given time step.
For example, suppose that in the current time step a local variable
temp
changes from its value at the previous time step, but then
reverts to the original value. In this case, the operator
hasChanged(temp)
returns 0 for the next time step, indicating that no
change occurred. For more information, see Change Detection Operators.
When multiple input events occur in the same time step, Stateflow software updates the _prev
and _start
buffers once per event. In this way, a chart detects changes between input events, even if
the changes occur more than once in a given time step.
All charts can use change detection operators to check for changes in chart inputs. C charts can also use change detection operators on outputs, local variables, and in Stateflow data that is bound to Simulink data store memory.
You can invoke change detection operators wherever you call built-in functions in a chart — in state actions, transition actions, condition actions, and conditions. There are three change detection operators:
The hasChanged
operator detects any change in Stateflow data since the last time step, using the following heuristic:
$$\text{hasChanged}(x)=\{\begin{array}{ll}1\hfill & \text{if}{x}_{\text{prev}}\ne {x}_{\text{start}}\hfill \\ 0\hfill & \text{otherwise,}\hfill \end{array}$$
where x_{start}
represents the value at the
beginning of the current time step and x_{prev}
represents the value at the beginning of the previous time step.
Syntax
hasChanged ( u )
C charts can also use:
hasChanged ( m [ expr ] ) hasChanged ( s [ expr ] )
where u
is a scalar or matrix variable, m
is a
matrix, and s
is a structure.
The arguments u
,
m
, and s
must be one of the following data types:
Input in a MATLAB chart
Input, output, or local variable in a C chart
If you enable the chart option Initialize Outputs Every Time Chart
Wakes Up, do not use an output as the argument of the
hasChanged
operator. With this option enabled, the
hasChanged
operator always returns 0
(or
false
), so there is no reason to use change detection.
Stateflow data in a C chart that is bound to Simulink data store memory
The arguments cannot be expressions or custom code variables.
Description. hasChanged (
returns
u
)1
if u
changes value since
the last time step. If u
is a matrix,
hasChanged
returns 1
if
any element of u
changes
value since the last time step.
hasChanged (
returns m
[ expr
]
)1
if the value at location
expr
of matrix
m
changes value since the last time step.
expr
can be an arbitrary expression that
evaluates to a scalar value.
hasChanged (
returns s
[ expr
]
)1
if the value at location
expr
of structure
s
has changed since the last time step.
s
must be a fully qualified name, such as
u.foo.bar
, which resolves to a structure.
expr
can be an arbitrary expression that
evaluates to a scalar value.
All forms of hasChanged
return zero if a chart writes to the
data, but does not change its value.
The hasChangedFrom
operator detects when Stateflow data changes from a specified value since the last time
step, using the following heuristic:
$$\text{hasChangedFrom}(x,{x}_{0})=\{\begin{array}{ll}1\hfill & \text{if}{x}_{\text{prev}}\ne {x}_{\text{start}}\text{and}{x}_{\text{prev}}={x}_{0}\hfill \\ 0\hfill & \text{otherwise,}\hfill \end{array}$$
where x_{start}
represents the value at the
beginning of the current time step and x_{prev}
represents the value at the beginning of the previous time step.
Syntax
hasChangedFrom ( u , v )
C charts can also use:
hasChangedFrom ( m [ expr ], v ) hasChangedFrom ( s [ expr ], v )
where u
is a scalar or matrix variable,
m
is a matrix, and
s
is a structure.
The arguments u
,
m
, and s
must be one of the following data types:
Input in a MATLAB chart
Input, output, or local variable in a C chart
If you enable the chart option Initialize Outputs Every Time Chart
Wakes Up, do not use an output as the argument of the
hasChanged
operator. With this option enabled, the
hasChanged
operator always returns 0
(or
false
), so there is no reason to use change detection.
Stateflow data in a C chart that is bound to Simulink data store memory
The first arguments u
,
m
, and
s
cannot be expressions or custom code
variables. The second argument v
can be an
expression. However, if the first argument is a matrix variable, then
v
must resolve to a scalar value or a matrix
value with the same dimensions as the first argument.
Description. hasChangedFrom (
returns 1 if u
, v
)u
changes from the value specified by
v
since the last time step. If
u
is a matrix variable whose elements all
equal the value specified by v
,
hasChangedFrom
returns 1 if one or more elements of the matrix
changes to a different value in the current time step.
hasChangedFrom (
returns m
[ expr
], v
)1
if the value at location
expr
of matrix
m
changes from the value specified by
v
since the last time step.
expr
can be an arbitrary expression that
evaluates to a scalar value.
hasChangedFrom (
returns s
[ expr
], v
)1
if the value at location
expr
of structure
s
changes from the value specified by
v
since the last time step.
s
must be a fully qualified name, such as
u.foo.bar
, which resolves to a structure.
expr
can be an arbitrary expression that
evaluates to a scalar value.
The hasChangedTo
operator detects when Stateflow data changes to a specified value since the last time step, using the
following heuristic:
$$\text{hasChangedTo}(x,{x}_{0})=\{\begin{array}{ll}1\hfill & \text{if}{x}_{\text{prev}}\ne {x}_{\text{start}}\text{and}{x}_{\text{start}}={x}_{0}\hfill \\ 0\hfill & \text{otherwise,}\hfill \end{array}$$
where x_{start}
represents the value at the
beginning of the current time step and x_{prev}
represents the value at the beginning of the previous time step.
Syntax
hasChangedTo ( u , v )
C charts can also use:
hasChangedTo ( m [ expr ], v ) hasChangedTo ( s [ expr ], v )
where u
is a scalar or matrix variable,
m
is a matrix, and
s
is a structure.
Charts that use MATLAB as the action language can only use scalar variables.
The arguments u
,
m
, and s
must be one of the following data types:
Input in a MATLAB chart
Input, output, or local variable in a C chart
If you enable the chart option Initialize Outputs Every Time Chart
Wakes Up, do not use an output as the argument of the
hasChanged
operator. With this option enabled, the
hasChanged
operator always returns 0
(or
false
), so there is no reason to use change detection.
Stateflow data in a C chart that is bound to Simulink data store memory
The first arguments u
,
m
, and
s
cannot be expressions or custom code
variables. The second argument v
can be an
expression. However, if the first argument is a matrix variable, then
v
must resolve to either a scalar value or a
matrix value with the same dimensions as the first argument.
Description. hasChangedTo (
returns 1 if u
, v
)u
changes to the value specified by
v
in the current time step. If
u
is a matrix variable,
hasChangedTo
returns 1 if any its of its elements changes value so
that all elements of the matrix equal the value specified by
v
in the current time step.
hasChangedTo (
returns m
[ expr
], v
)1
if the value at location
expr
of matrix
m
changes to the value specified by
v
in the current time step.
expr
can be an arbitrary expression that
evaluates to a scalar value.
hasChangedTo (
returns s
[ expr
], v
)1
if the value at location
expr
of structure
s
changes to the value specified by
v
in the current time step.
s must be a fully qualified name, such as
u.foo.bar
, which resolves to a structure.
expr
can be an arbitrary expression that
evaluates to a scalar value.
The following model shows how to use the hasChanged
,
hasChangedFrom
, and hasChangedTo
operators to detect
specific changes in an input signal. In this example, a Ramp block sends a discrete,
increasing time signal to a chart:
The model uses a fixed-step solver with a step size of 1. The signal increments by 1 at each time step. The chart analyzes the input signal for the following changes at each time step:
Any change from the previous time step
Change to the value 3
Change from the value 3
To check the signal, the chart calls three change detection operators in a transition
action, and outputs the return values as y1
, y2
, and
y3
, as follows:
During simulation, the outputs y1
, y2
, and
y3
are shown in this scope.
The ramp input signal u
is represented in green, and the
y1
, y2
, and y3
values are
represented as yellow, blue, and red respectively. y1
transitions at T1,
and stays at a value of 1 because u
continues to increase each time step.
y3
transitions at T3 when the value of u
has reached
3, but then transitions back to 0 at T4 when u
increases from 3 to 4.
y2
transitions to 1 at T4 when u
changes from 3 to
4, and then transitions back to 0 at T5 when u
increases from 4 to
5.