I have an existing Simulink model from a customer that uses function-call semantics as event triggers on Stateflow charts, amongst other things. For our current purposes, I need to be able to generate a simple output pulse when a function-call trigger occurs, such that:
- At the function call trigger, we set the output to value 1
- After a fixed period of time (e.g. 1ms), the output value is set to 0. And this then repeats whenever the function call trigger next occurs. I tried setting up a stateflow chart as follows:
And although this does generate a pulse, the transition from High to Low state only occurs when the E event occurs, rather than 1ms after when the initial E event occurred. That is, it is obvious that the chart is going to sleep in between the E function-call events. The E events are around 200ms apart, and each pulse of 'y' is also the same width - when I want it to only be 1ms wide when y=1. Is there a way to change the chart settings so that it stays awake until the transition from High back to Low has occurred? Or could I acheive the same behaviour using a Function-call subsytem instead of a Stateflow chart? Either is fine for me.
(The overall model uses a Variable solver, as the block generating the function-call pulses requires it.)
CodePudding user response:
So after some experimentation, here's a solution that seems to be working for me.
The chart:
This lives inside the following subsystem:
The FunctionCall input comes from the customer block that generates occasional function calls. The 1ms function call has a sample time of 0.001. These are muxed to the input events of the chart as E and M1 respectively.
Within the chart, the function call E will transition from Low state to High state and set y=1; Then, after 2 instances of the M1 event, we transition back to low and set y=0.
It does seem odd that I need to wait for 2 instances of M1, rather than just having the transition as M1 - but given that E and M1 will both occur at the same time (generally, E is at a microsecond boundary), without the after(2, M1)
transition, I could see the state transitions happening by using debug breakpoints and stepping, but they were both occurring at the same time step thus the pulses were 0 time in width.
With the above chart, I can see (via a Scope of the value of y) that I'm getting y pulses with width 1ms, and they start at the same time as E.
If someone has any better solutions, please feel free to submit them too!
CodePudding user response:
It looks like you're using the event as an enabled trigger for your chart, which means the chart is only being evaluated when the trigger is enabled. This means the chart output is only updated once per trigger, giving your issue.
Instead, one approach would be to convert the event source into a Boolean signal which is the full rate of your model, i.e. kHz to capture a 1ms sample, then use a detected increase in this signal as a "normal" (not an enabled trigger) variable for your stateflow.
Here is a minimal model
In this case, I'm deliberately driving an enabled subsystem from the event, shown below, which creates the Boolean signal. Note that you need to set the "Output when disabled" property of the out port to "reset" so that it flips back to 0 between event triggers. Otherwise you have the same problem.
The "Detect Increase" block is in the standard Simulink library, and converts our Boolean (which lasts the frequency of the event) to a single sample on the rising edge. You may not need this depending on what your E
signal looks like, in my case it was required because E
comes from a signal-builder pulse.
Now the chart has a simple Boolean input which is true for one sample on the event trigger. We can implement a chart very similar to the one you had:
Obviously you can change the after
duration to suit your needs.