Seth on Simulink
August 20th, 2009
A Better If-Else Construct
In a previous post, I answered a question about how
to model an If-Else behavior. Here I will restate the algorithm I want to create:
if(sel==0)
out = 2*in1;
elseif (sel==1)
out = 3*in2;
The first answer I gave relied upon a Switch block and the Conditional
Input Branch Execution optimization to get an efficient If-Else construct
in the model. While this works, I don’t like reliance on an optimization to
provide good behavior. Sometimes, small changes to the model prevent Simulink
from applying an optimization. I think it is best to implement requirements explicitly.
In this post, I want to show you a way to model explicitly an If-Else conditional
execution behavior.
Conditionally Executed Subsystems and Merge
The If-Else construct requires decision logic to control the
execution of algorithm contained within the expression. One way to do this is
using the If block (from the Ports & Subsystems library), combined with the
If Action Subsystem. The If Action Subsystem executes based on the conditional
expression in the If block. If you have used Function Call subsystems, this is
very similar.

The If block provides control over If and ElseIf conditions,
and there is even an option to provide an Else signal.

This model will give you the conditional execution of the
two subsystem, however, the subsystems write their outputs to separate signals.
How do you get two subsystem to write to the same signal?
Merge the Signals
The Merge block provides a way for both subsystems to write
to the same signal.

In many ways, the Merge block doesn’t behave like a block
with the traditional input/output relationship. I think of it more like a
jumper across multiple wires. The merge block specifies that all signals
connected to it have the same value and actually share the same memory. This
is the programming practice of specifying multiple writers to the same
variable.
Generated Code with Merge
The code generated from the above model looks a lot like our
original algorithm.
34 /* If: '<Root>/If' incorporates: 35 * ActionPort: '<S1>/Action Port' 36 * ActionPort: '<S2>/Action Port' 37 * Inport: '<Root>/In3' 38 * SubSystem: '<Root>/If Action Subsystem' 39 * SubSystem: '<Root>/If Action Subsystem1' 40 */ 41 if (sel == 0.0) { 42 /* Gain: '<S1>/Gain' incorporates: 43 * Inport: '<Root>/In1' 44 */ 45 out = 2.0 * u1; 46 } else { 47 if (sel == 1.0) { 48 /* Gain: '<S2>/Gain' incorporates: 49 * Inport: '<Root>/In2' 50 */ 51 out = 3.0 * u2; 52 } 53 }
Correct use of Merge
Because Merge blocks are a memory specification rather than
an algorithmic construct, there are some guidelines
for using merge blocks. The documentation shows some correct and incorrect
usage patterns. If you use merge block in your model, I suggest you run the Model
Advisor Check for proper Merge block usage.
Now it’s your turn
Do you use the Merge block in your models? Leave a comment here and
share your experience.
01:55 UTC |
Posted in Code Generation, Modeling, Real-Time Workshop, Simulink Tips |
Permalink |
You can follow any responses to this entry through the RSS 2.0 feed.
You can skip to the end and leave a response. Pinging is currently not allowed.
Leave a Reply
|
A topic that has caused great trouble over the years. As you mention, Simulink doesn’t always apply the conditional execution optimization (code that has states is a common reason here) and so it is generally required that developers use the If/Action or the Switch/Action (a great alternative to an If block with u1==0, u1==1, u1==2,…).
These always draw complaints about how many lines one needs to connect properly, how easy it is to make a mistake, and how hard it is to visually inspect. Most of the Action subsystems are more complex, with multiple inputs and outputs feeding multiple merge blocks and lines crossing everywhere.
To deal with this, I’ve seen:
- Put all the merge blocks in a merge subsystem to prevent lines crossing. Inside the merge subsystem, ports 1 & 3 feed the first merge block, ports 2 & 4 feed the second, or similar.
- Change the foreground color on the Action subsystem so the lines are colored and easier to trace.
- Use a virtual bus to bring all the signals together and then break apart without lines crossing.
- Use local From/Goto blocks to avoid crossing signals.
Some people also use the From/Goto to avoid having the dashed action lines crossing other lines on their way to that top port.
And because this is so messy, just the mechanics of implementing If/Then/Else logic gets dedicated to its own subsystem so it can be inspected independently. If the logic is complex, sometimes the If block gets its own subsystem (or Stateflow chart with Boolean outputs) too.
We encourage people to do something, but don’t have a standard. What do others do to create maintainable models as the Action subsystem I/O grows?
Hello Seth!
Read all your good articles.
But can you please consider my question for your next article of just give me your kind shortly explanation.
Cant build simulink model for that ODE:
L1*x1′ + R1*x1 + M12*x2′ + 1/C1*int(x) = 0
L2*x2′ + R2*x2 + M21*x1′ = 0
where int(x1) = Uc
build model like this:
http://picspix.com/img87/5728/16333.jpg
but it was failed..
It’s classic quotation of LC circuit+mutal inductance bind
Thanks a lot, and
sorry for out of topic post.
Regards,
Valentino.
@Bob - You got me thinking about this. I see what you mean about the number of wires and the challenge of making sure they get connected correctly every time. I hope I’ll be able to propose some kind of solution in a future post.
@valio - Start by rewriting the ODEs in terms of first order derivatives. This was discussed in a previous blog post about How to draw ODEs in Simulink.
please tell me how can i get the sampling time used in simulation