Now that we've discussed a bit about change detections here using a block diagram approach, I would like to show you have this can be achieved using Stateflow. The principle remains the same, but what I'm actually interested in showing you is how to obtain the previous value of a given variable in a chart, without using any unit delay, memory hold or latch (in order to compare it with our current value). Here we go.
1) Objective:
Create a rising edge, falling edge or change detector.
2) Model configuration:
Solver -> discrete, fixed simulation step. Step-size -> 0.01s. We will use MATLAB as the action language of our chart.
3) Principle of operation
Rising edge -> (x(t-1) == 0) && (x(t) > 0)
Falling edge -> (x(t-1) > 0) && (x(t) == 0)
Detect change -> (x(t-1) ~= (x(t)) (for floating point, abs(x(t)-x(t-1))>tolerance)
Most importantly, we need to learn how to get x(t-1) directly within our chart. It's very simple actually: we will create a local variable. The last instruction performed in the chart at every iteration will be assigning the value of our input to this local. Thus, at the next iteration, our local will hold the previous value of our input.
4) Solutions
Let's suppose our input is an 8 bit unsigned integer. Thus, we will no longer take into account any rounding errors and so on (discussed in the previous example).
a) Create a chart. Using the model explorer, create a variable called SF_input (scope -> input, type -> uint8).
b) Create another variable called SF_input_old (scope -> local, type -> uint8).
c) Create a variable called Sgn_rising (scope -> output, type -> boolean).
By now, you should have something like this:
d) Create a state, name it. Initialize SF_input_old. Without it, we will have a simulation error, as our chart will try to access its value without it being assigned at t=0s. Furthermore, I do not suggest initializing it to 0 (if our SF_input has a constant non-null value, we will detect a rise after 1 simulation step, even though our input hasn't changed). Use SF_input as the initialization value.
e) Start coding the logic. We will use a few junctions. Our condition will be [(SF_input_old == 0) && (SF_input_old > 0)]. Be sure to place this condition on the transition marked with 1, or else the condition will never be evaluated. If the condition is met, we will set Sgn_rising to true, else Sgn_rising will be set to false. After both assignments, remember the most important instruction: {SF_input_old = SF_input;}. This will ensure that our previous value gets updated every simulation step. Here's how your chart should look like.
In case you wonder why I added the second junction instead of placing the instruction under the condition, there are two reasons: first is good practice (conditions should be placed horizontally, whereas assignments should be placed vertically). The second one would be to improve legibility. It's not mandatory to use my approach, though.
Here's the result of the simulation (note that I've added a Data Type Conversion to the step input, as it is a double by default):
Here's the logic for the falling edge (using a new output called Sgn_falling):
And the change detector (using Sgn_change):
That should be it. The main aspect I wanted to focus on was how to create a local that can store the previous value of a variable inside a chart. It's a very useful functionality in a variety of situations (such as the ones above).