Skip to Main Content Skip to Search
File Exchange
MATLAB Newsgroup
Link Exchange
  Blogs  
 Contest 
MathWorks.com

Seth on Simulink

May 7th, 2008

Bus Signals in the Generated Code

Blog reader Paul J. shared with us his mental model of the bus as a structure. While this isn’t true of virtual buses, it is precisely true of nonvirtual buses. In fact, when you generate the code for a nonvirtual bus using Real-Time Workshop, the result is a structure.

Focus on the boundaries

In a previous post about nonvirtual bus signals I talked about memory allocated for the bus. The places we have to think about memory allocation are the boundaries of systems. Here is the simplebusdemo_nv.mdl

Simple bus demo diagram with a nonvirtual bus

This model has the root level boundaries defined by the inport and outport blocks. It also has a boundary at the edge of the ReusableFcn subsystem. The main_bus crosses this boundary and the generated code is different if the bus is virtual versus nonvirtual.

The ReusableFcn subsystem contains a Bus Selector and two gain blocks.

ReusableFcn subsystem with nonvirtual bus input

I configured the subsystem to generate a reusable function. Here are the settings for the subsystem:

ReusableFcn subsystem parameters

Basically, I have specified how Real-Time Workshop should wrap up the algorithm implemented inside this system. By specifying “Treat as atomic unit”, the blocks inside the system execute together. Real-Time Workshop will generate reusable function code with my specified name (ReusableFcn) into a file of the same name (ReusableFcn.c). The reusable function code will pass input and output signals as arguments to the function.

I can now picture what this will look like:

ReusableFcn(inputs..., outputs...)

Virtual buses pass every element separately

ReusableFcn subsystem with virtual bus input

When the bus signal is virtual at the inport to the ReusableFcn, only the elements of the bus that are used in the system need to be passed through the boundary. Here is the actual code for the function call:

30   /* Outputs for atomic SubSystem: '<Root>/ReusableFcn' */
31   ReusableFcn(simplebusdemo_vir_U.Pulse, simplebusdemo_vir_U.Chirp,
32               &simplebusdemo_vir_B.ReusableFcn_m);
33 

Notice, there is no evidence in the code that a bus signal exists. At compile-time, direct connections between sources and destinations replace the virtual bus.

19 /* Output and update for atomic system: '<Root>/ReusableFcn' */
20 void ReusableFcn(real32_T rtu_0, real_T rtu_1, rtB_ReusableFcn *localB)
21 {
22   /* Gain: '<S1>/Gain' */
23   localB->Gain = 2.0F * rtu_0;
24 
25   /* Gain: '<S1>/Gain1' */
26   localB->Gain1 = 3.0 * rtu_1;
27 }

Nonvirtual buses are structures

ReusableFcn subsystem with nonvirtual bus input

The nonvirtual bus is a contiguous block of memory. This is assembled and passed into the ReusableFcn.

30   /* local block i/o variables */
31   main_bus rtb_main_bus;
32 
33   /* BusCreator: '<Root>/Bus Creator' incorporates:
34    *  BusCreator: '<Root>/BusConversion_InsertedFor_Bus Creator_at_inport_0'
35    *  BusCreator: '<Root>/BusConversion_InsertedFor_Bus Creator_at_inport_1'
36    *  Inport: '<Root>/In1'
37    *  Inport: '<Root>/In2'
38    *  Inport: '<Root>/In3'
39    *  Inport: '<Root>/In4'
40    *  Inport: '<Root>/In5'
41    */
42   rtb_main_bus.bus1.Chirp = simplebusdemo_nv_U.Chirp;
43   rtb_main_bus.bus1.Constant[0] = simplebusdemo_nv_U.Constant[0];
44   rtb_main_bus.bus1.Constant[1] = simplebusdemo_nv_U.Constant[1];
45   rtb_main_bus.bus1.Constant[2] = simplebusdemo_nv_U.Constant[2];
46   rtb_main_bus.bus2.Clock = simplebusdemo_nv_U.Clock;
47   rtb_main_bus.bus2.Pulse = simplebusdemo_nv_U.Pulse;
48   rtb_main_bus.bus2.Sine[0] = simplebusdemo_nv_U.Sine[0];
49   rtb_main_bus.bus2.Sine[1] = simplebusdemo_nv_U.Sine[1];
50 
51   /* Outputs for atomic SubSystem: '<Root>/ReusableFcn' */
52   ReusableFcn(&rtb_main_bus, &simplebusdemo_nv_B.ReusableFcn_a);

Each of the input signals is being copied into the rtb_main_bus variable, which is an instance of the main_bus type. This structure matches the bus object definition specified by main_bus, bus1, and bus2.

I notice that the ReusableFcn has a shorter interface. Now the only input signal is a pointer to the rtb_main_bus, which is allocated locally.

ReusableFcn subsystem with nonvirtual bus input

19 /* Output and update for atomic system: '<Root>/ReusableFcn' */
20 void ReusableFcn(const main_bus *rtu_In1, rtB_ReusableFcn *localB)
21 {
22   /* Gain: '<S1>/Gain' */
23   localB->Gain = 2.0F * (*rtu_In1).bus2.Pulse;
24 
25   /* Gain: '<S1>/Gain1' */
26   localB->Gain1 = 3.0 * (*rtu_In1).bus1.Chirp;
27 }

In the case of nonvirtual bus signals, the concept of interface specification using the bus object carries all the way down to the generated code.

Now it’s your turn

We have now covered most of the important topics on bus signals. What questions remain about bus signals and their use in your models? Post a comment here.

April 29th, 2008

Nonvirtual Bus Signals

Most Simulink users have a good idea of what a bus signal is but I have found people are not as clear about what distinguishes virtual and nonvirtual buses. We have discussed bus signals in recent posts, and we are now ready to answer blog reader Han Geerligs request for “more explanation on virtal/nonvirtual buses.”

What is a nonvirtual bus?

Here are the two types of bus signals, virtual and nonvirtual.

Virtual and nonvirtual bus signals

To make a bus nonvirtual, provide a bus object and check the “Output as nonvirtual bus” check box in the Bus Creator dialog. You can review how to make a bus object with the example provided in this previous post.

Nonvirtual bus creator dialog

The big difference between virtual and nonvirtual buses is how Simulink treats memory allocation. A virtual bus does not allocate specific memory for the bus, whereas nonvirtual bus signals represent memory.

In a previous post, we saw that when you update your diagram (Ctrl-D), the virtual buses disappear and what remains are connections between the actual source and the destination block. The memory allocated for those signals is not contiguous. Using a nonvirtual bus specifies the creation of a structure, which resides in contiguous memory.

At first, this concept was foreign to me because I generally had not thought about memory allocation in Simulink. To better illustrate this concept I will compare two models, simplebusdemo_vir.mdl and simplebusdemo_nv.mdl. (Bus objects are in simplebusdemo_nv_busobjects.mat.)

Simple bus demo with virtual buses

Simple bus demo with nonvirtual buses

Both use bus objects to specify the interface to the ReusableFcn subsystem, but simplebusdemo_nv has a nonvirtual bus crossing the boundary. Here is my mental picture of memory being allocated for the virtual bus example.

Memory layout with virtual buses

The first and fifth inport have type double inputs, with one and two elements respectively represented in red. The second inport has three elements of int16, represented in green. The third inport is one element of type uint32 represented by orange, and the fourth inport is one element of type single represented by blue. The bus creators and bus signals are all virtual blocks, so there is no memory associated with those blocks or their ports.

The inports for the nonvirtual bus example have the same pattern of memory allocation, but now we have to add in the memory for the nonvirtual bus. Here is the way I picture it.

Memory layout with nonvirtual buses

The output of the bus creator is a scalar element of main_bus type as defined by the bus object. The bus object is the definition, and the nonvirtual bus is an instance of a structure with that definition. I often see confusion between bus objects and instances defined by bus objects. They are not the same thing. The bus object is a definition of an interface. Your model may contain many instances that share that same interface definition.

Nonvirtual bus signals and efficiency

As you can see from the above picture, the nonvirtual bus has added memory to the model. In this case, that memory consists of copies of the memory defined at the inports. I have often heard the rumor that bus signals result in many unnecessary copies. This is not completely accurate. Nonvirtual bus signals can result in additional copies, but from the Simulink engine perspective, this is the specification. Another way to build this model would be to remove the five inports and replace them with a single inport, which outputs a main_bus type. Then it would look like this.

Memory layout for a single inport with a nonvirtual bus

Notice, when you specify a bus object on an inport, the icon changes to show that a bus object defines that interface.

When do you need a nonvirtual bus?

The only places you need nonvirtual buses are at the boundaries in your model when you want to define the interface as a structure. Some examples of these boundaries are Stateflow charts and model reference blocks. At the interface between systems, virtual buses are as a collection of individual elements, with each passing separately to the system. The nonvirtual bus forces the memory to be a contiguous structure passed into the system.

Nonvirtual buses show up in other places in models where they are not required by semantics. Most often the reason it is done is to control the signal memory allocation in the generate code.

Virtual versus nonvirtual buses

To summarize,

  • Virtual buses don’t really exist in memory (the memory they represent is at the actual source)
  • Virtual bus elements are not contiguous in memory
  • Nonvirtual buses resides in contiguous memory
  • Nonvirtual buses may incur copies which could reduce the efficiency of the system
  • Virtual buses will often require less memory

I think these concepts still require further illustration by looking at the generated code. You can get a sneak peak if you want to download the models and build the code yourself, or, tune in next week when I post about bus signals in the generated code.

Now it’s your turn

Do you ever picture the memory allocated in your Simulink model? Did I describe the reason you use nonvirtual bus signals? Are there other reasons I didn’t consider? Post a comment and share your thoughts.

April 18th, 2008

Bus Objects and Interface Specifications

A few recent comments on this blog have asked about bus objects. Blog reader KMR remarked that "bus objects are one of the most important parts of the whole bus concept: allowing you to lock down an interface." This week I introduce bus objects and how they can help avoid modeling errors.

Bus objects provide a specification

In an earlier post, we saw that virtual bus signals do not have to include any information about the size and datatype of their signals. This information propagates from the other blocks (like sources and Inports) in the diagram. The simplebusdemo.mdl doesn’t need a specification for the bus signal because it is virtual. Our mental model of the bus signal is a bundle of rainbow colored wires that link the sources to their destinations. We often refer to a bus as a tie-wrap of signals.

simplebusdemo_diag.png

If you did want to lock down the description of this bus, you must use a bus object. If the bus is the rainbow colored bundle of wires, in my mental model the bus object is the definition for the cable connector at the end of that bundle. It defines all the pins and their exact configuration and asserts that only those types of signals may be connected.

Check “Specify properties via bus object” and include the bus object name on the Bus Creator blocks to add the specification to your model. I’ll get to creating bus objects in the next section.

Bus Creator dialog with a bus object

Bus Creators use bus objects for error checking. If the input signals do not have the same types and dimensions as the elements in the bus object Simulink will error. There is also a connectivity diagnostic to check for element name mismatch in the bus object. Turn the diagnostic up to warning or error to ensure your signals are consistent with the block specification.

Making a bus object

The easiest way to make a bus object is directly from your diagram. Simulink.Bus.createObject is a function that generates a bus object for the block you specify based on your diagram. Specify the bus creator or port that has the highest level in the hierarchy of the bus. Simulink.Bus.createObject recursively creates bus objects for buses that feed into the given block. For our example, the main_bus is specified by the simplebusdemo/Bus Creator (not Bus Creator1 or Bus Creator2).

>> Simulink.Bus.createObject('simplebusdemo', 'simplebusdemo/Bus Creator');
>> whos
Name Size Bytes Class Attributes
 
ans 1x1 272 struct
bus1 1x1 Simulink.Bus
bus2 1x1 Simulink.Bus
main_bus 1x1 Simulink.Bus

To look at bus objects, use the buseditor. (click to enlarge)

Bus editor for the main_bus

As of R2008a Simulink has a new bus editor, so unless you are using this release, your version will look different. The left pane shows all bus objects in the workspace. The selected node in the tree displays its children in the center pane, and on the right, you have the details for each selected element. The information about dimensions, datatype and signal name are all a part of the bus object. For hierarchical bus signals, the element datatype is the name of another bus. Looking at the main_bus, it has two signals, bus1 of type bus1, and bus2 of type bus2. The name and type do not have to match, but they do in this case.

If you are happy with your bus objects, I recommend saving them to a MAT-file so you do not have to regenerate them every time. Some people prefer to generate an M-file and call that as part of their initialization routines, instead of loading the MAT-file. I have automatically generated this M-file during the call to Simulink.Bus.createObject. Given an output file name, Simulink.bus.createObject also outputs the code you need to make that bus object.

>> Simulink.Bus.createObject('simplebusdemo',...
'simplebusdemo/Bus Creator','simplebusdemo_busScript');

Bus specification in action

If I change my constant input signal to be type int8 instead of double Simulink will throw an error during update diagram (Ctrl-D).

The input bus to block 'simplebusdemo_bo_error/Bus Creator1' does not match the bus specified by the bus object 'bus1' on the block dialog. The following errors were detected :
Bus element 'Constant' of bus object 'bus1' is specified to be of datatype 'double', but the incoming signal has a datatype of 'int8'.

Bus creator with error

As you can see, the bus object has locked down the specification for the signals fed into the bus creator. When something does not match Simulink reports an error.

Bus objects can be specified on ports

In addition to the bus creators, Inports and Outports can also be fully specified with a bus object. When a bus object is used on a port you are asserting that only that special type of connector can be used with that port. This port could be a root level Inport or Outport, or a port on a subsystem. If the subsystem is in a library, you have defined its interface, and all instances of the library block must match the specification.

Outport dialog with a bus object

Getting back to the comment that “[bus objects] are one of the most important parts of the whole bus concept: allowing you to lock down an interface.” The concept of locking down an interface is important to developing reusable components as well as working with others on large modeling projects. This is a very powerful concept I have seen used in conjunction with an interface control document (ICD) to define the interface to a system. The document specifies the characteristics of the bus signals, and the bus object enforces that those characteristics are true.

I have also seen a Simulink model specify the interface, with a script used to generate the ICD from the model. This makes the Simulink model the single source of truth. Your model will always be in sync with the specification if this is your workflow.

Now it’s your turn

What do you think about bus objects? Do you use them? I still have not had anyone volunteer to show off their use of bus signals with a screen capture from their model. Leave a comment and then send me an e-mail with the image. I will post it for you and we can all marvel at your work.

April 11th, 2008

How do you think about virtual buses?

Today I present for your reading pleasure a continuation of our discussion on mux and bus signals. Last week we looked at the advanced uses of Mux Blocks. This week I want to discuss the mental model of virtual bus signals.

We start with a simple bus model

A simple bus demo model

I have slightly modified the busdemo.mdl example that ships with Simulink to make my simplebusdemo.mdl. Buses are used to route signals around complex diagrams, and this model is not complex, so bear with me. In addition, bus signals usually pass through levels of hierarchy, but for convenience, I am keeping everything at a single level.

The mental model of the bus

In a previous post, I talked about the mental model of the bus as a tie-wrap of wires. I imagine the rainbow bundle of wires gathered together at the bus creator, and just the wires I am interested in emerging from the bus selector. Virtual bus signals are simply a graphical convenience and do not change the behavior of the model.

What do you mean by a virtual bus?

When you look at the bus creator block, you will notice that there is a box to check labeled "Output as nonvirtual bus". Unless this is checked, a virtual bus signal is output.

Bus creator dialog, note, nonvirtual bus is unchecked

The Bus Creator and Bus Selector dialog show the contents of the bus by signal name. These signals (the individual colored wires) are arranged hierarchically by their connections to the Bus Creator blocks. The Bus Creator blocks do not actually change the signals, and so we can call these virtual buses. The diagram represents the bus as we draw it, and this keeps everything nice and organized for us.

What does Simulink do with the bus?

Simulink needs to know the actual sources that feed into the bus, and the destination blocks that are connected to the outputs of the Bus Selector. Simulink gets this information in the first part of the simulation process during Update Diagram. Before the model runs, Simulink compiles the diagram into an internal representation. This compile process is part of Update Diagram. You can force Simulink to compile the diagram through the menu Edit->Update Diagram, or use the hot-key Ctrl-D.

Update diagram analyzes the model to make sure that it conforms to the semantics of Simulink. I have not always thought of Simulink as a programming language, but when I draw the diagram, I am actually programming! The compiled internal representation removes any unnecessary stuff in the model. In our model, there are five inputs and two outputs. To calculate the outputs we only need the Pulse and Chirp signals. So what happens to the other signals?

When you update the diagram, it is equivalent to a wiring of the actual sources directly to the blocks consuming those signals. Simulink does not include the virtual bus in its internal representation. We can imagine the internal Simulink representation for our simple bus model, after update diagram:

Simple bus demo without the bus

Virtual buses are efficient

Virtual bus signals are efficient because Simulink optimizes the unused signals out of the model. For many of the large models I work with, virtual buses keep the diagram organized and do not add overhead in the model. If you go back to our mental model of the rainbow bundle of wires, the unused signals are essentially like wires that only connect at one end. They might be a part of the bundle, but there is nothing connected at the destination. Simulink only needs to keep track of the wires that run from a source to a destination.

When I want to see another view on the internal representation in Simulink, I use the Real-Time Workshop to generated C-code. The integration of Simulink and Real-Time Workshop allow you to convert the model in to C-code that is appropriate for running on a real-time embedded system.

If you did not believe me that Simulink gets rid of the virtual bus, look at the C-code. There is no evidence of bus signals here:

   27     /* Outport: '<Root>/Out1' incorporates:
   28      *  Gain: '<Root>/Gain'
   29      *  Inport: '<Root>/In4'
   30      */
   31     simplebusdemo_Y.Out1 = 2.0 * simplebusdemo_U.Pulse;
   32   
   33     /* Outport: '<Root>/Out2' incorporates:
   34      *  Gain: '<Root>/Gain1'
   35      *  Inport: '<Root>/In1'
   36      */
   37     simplebusdemo_Y.Out2 = 3.0 * simplebusdemo_U.Chirp;

All that remains are the connections from the Pulse and Chirp inputs (part of the input signals structures model_U) to the gain blocks (which have been in-lined in the code) to the outputs.

Back to basics

I am eager to get into nonvirtual bus signals; however, I think it is important to review the basics before we jump into the advanced. Did you already know this? Does this fit with your mental model of virtual bus signals? Leave a comment and tell me about it.

April 3rd, 2008

Advanced Maneuvers using Mux and Demux

Last week I started a discussion of mux and bus signals. Our mental model of the mux signal is a vector. The Mux and Demux Blocks can do more than just combine and break apart the elements of a vector. This week I want to go a level deeper and talk about the advanced maneuvers using Mux/Demux Blocks.

Mux Blocks as specifications

The first thing I want to show you is how to use the Mux Block to specify additional information about the signal dimensions at its ports. Instead of just putting the number of ports, you can specify the width of each signal line connected to the Mux Block.

Mux vector dialog Mux diagram

This helps if you want to add a little more information to your model and include specifications at the Mux Block ports. When a signal is connected to the Mux Block and it has the wrong width, an error is thrown when the model is compiled.

Error in port widths or dimensions. Invalid dimension has been specified for input port 3 of 'model/System/Mux'.

Mux diagram error

Source blocks and ports can also supply this type of dimension information. I recommend that you specify dimensions on those source and port elements also, rather than just relying on the Mux Block. Information like dimensions should be included in interface and source blocks. For example, here is where you would add dimension information in the Inport dialog:

Inport dialog with port dimensions

Demux Specifications

The mux is nice to have, but the Demux Block puts this concept to good use for selecting out subsets of your signal. When specifying the number of outputs as a vector of widths, you can pull out blocks of elements from your vector into subvectors.

Demux block dialog with a vector of widths

Here is an example of the Demux Block breaking a vector of 8 elements into new signals of widths 1, 5 and 2.

Demux block outputting vectors of different widths

Going back to our mental model of the mux signal as a vector, I only use this technique if it is logical to represent my signal this way. In this model, peeling off each chunk of signals makes the diagram flow very nicely. This replaces the need to demux all elements of the signal and then mux the subset of the signal into a vector.

Mux and Demux Blocks also work with special signal types

Another use of Mux and Demux Blocks involves the special function call signal type. Before I talk about what mux and demux do, let us review the basics of function calls.

A short introduction to function calls

A function call system is similar to a triggered system except that instead of executing based on the value of a signal they execute immediately when called by the function call initiator. I have seen function call systems used to simulate asynchronous behavior or to schedule the execution of a component independent of other components. Function calls are critical when designing your own scheduler for an embedded system.

Function Call Generators (1 below), Stateflow(2), and S-functions are the most common function call initiators. Model Reference Blocks(3) and Function call subsystems (4) are two examples of functions that can be called.

Function call signals

Function calls and Mux Blocks

When you have a single function call initiator, and a single system to be called, the connection is simply from initiator to the system being called. When you have multiple function call initiators, the Mux block is used to join the function calls together. (Blocks can only have one function call port.)

Function calls with a mux block join

Function calls and Demux Blocks

When a single initiator needs to call multiple systems, the Demux Block allows you to split the signal. This is a very important semantic role for the Demux Block because function call signals are not allowed to branch like normal signals. Function call signals determine the execution order of the blocks they are connected to. If a function call was to branch, which destination system would be executed first? The Demux Block specifies the order of execution based on the port number that the signal is connected to. Port numbers are always counted from top to bottom, or left to right. Here is an example:

Function call demux

In this example, the function call initiator Task1 will execute Sys1, Sys2 and Sys3 in that order. I don’t know about you, but when I look at that picture I feel an aesthetic desire to uncross the lines going to Sys1 and Sys2. My urge is to reconnect the first and second outport from the Demux in order to uncross the signals, like this:

Function call demux with uncrossed lines.

This would fundamentally change the behavior of the system. The order of execution would then be Sys2, Sys1, and then Sys3. The Demux Block is an important part of function call semantics, and semantics trump aesthetics.

What do you think?

You may have started reading this post with the expectation to learn all about Mux and Demux, but you also got my elevator speech about function calls. Did you know about this use for Mux and Demux? What is new or different in your mental model for these blocks? Leave a comment and tell me about it.

March 27th, 2008

What is a Composite Signal?

The answer is short and sweet. A composite signal is a mux or a bus signal. These can be thought of as a collection of other component signals. The subtleties of using bus signals and mux signals are a common source of modeling questions, and in 2006 The MathWorks published a new section of Simulink documentation to specifically discuss Composite Signals. In this post I will start to share my mental model of the mux and bus.

It started with mux

The basic concept for the Mux Block is the idea of bundling signals together. This bundle of signals can be routed through the model, and then operated upon as a collective unit. (Mux actually stands for multiplex.) Along with the Mux Block is the Demux Block, which breaks signals apart into their components to be operated on individually. Take a look at this example.

Simple Mux Example

The Mux is putting the three signals, (x,y,z) into a single line of width 3. The Demux Block is used to break apart the signals into their basic elements. The Mux and Demux do not change the signals, and are considered virtual. When the model is run, it is as if the blocks don’t exist, and only the connections from source to destination remain, like this:

Simple mux model virtual blocks, just connections

An important mental model to use for the mux is the idea of creating a vector. This means you can do things to the output signal that you would do with a vector. For example, multiply the vector by 2.

Mux model with gain

These types of vector operations impose an important requirement that all signals passed into a Mux Block are the same data type. In my mental model of the mux, it only makes sense to lump signals together if they make sense as a vector. Usually the elements have the same units or they are useful as a group. The only specification you need for a Mux Block is the number of inputs.

Mux block dialog

Another benefit of using the mental model of a vector is that you can index with the selector block to pick off signals or rewire your connections.

Mux model with selector

Later on came the bus

When I need to bundle together signals of different types or I can’t naturally express my diagram with a vector, I use a bus. Bus signals can really clean up your diagram. Bus Creators and Bus Selectors provide a graphically convenient way to manage signals and organize your model. In my mental model of the bus, I imagine a rainbow of wires bundled together with a tie-wrap. Without that tie-wrap holding it together I would quickly loose my ability to keep the signals organized. To demonstrate this, I want to look at an example model of the DeHaviland Beaver from the Aerospace Blockset:

DeHaviland Beaver Model Top Level

At the top level of the model, everything is nice and orderly because all the information calculated by each subsystem is bundled up into a bus. Each system packages all the relevant signals into a bus using a Bus Creator, and then passes the bus along to the systems that consume those signals.

Aerospace 6DOF block and bus creator

Can you imagine if the signals were not bused together? This is a relatively modest model, but it would be a mess!

DeHaviland Beaver Model with no bus signals

Most of the component systems in this model use bus signals to provide simplified interface. I have noticed that some people will place signals in the bus, just in case they might be needed in another system. Here is an example of a system whose interface is defined with bus signals.

Calculate flight params system

With a quick glance at this diagram you can determine that the flight parameters (FltParams) can be calculated from environmental signals (EnvirBus) and aircraft signals (ACBus). Inside the system you can see Bus Selectors used to pull specific elements from the bundle of signals. The computed flight parameters are combined with a Bus Creator to define the FltParams Bus.

Calculate parameters system with bus creator

Bus signals can represent hierarchy

Let’s look at the hierarchy found in the Environment Bus. This is a simple example of a bus being fed into another bus. The environmental signals for gravity (g), pressure (rho), and wind bus (Vwind) are passed into the Bus Creator. The wind bus is defined by the body velocities (uvw_wind) and body rates (pqr_wind).

Environment system bus creator with annotations

This leads to an organized collection of signals in the bus, as shown by the Bus Creator dialog.

Bus creator dialog

At its most basic level, you only need specify the number of inputs to your bus creator. The names of elements are derived from the signal names. Like the Mux Blocks, these bus creators have not changed the signals at all, so we can call them virtual.

It doesn’t end here

We are just starting to get into this topic. Next week we will talk about more advanced maneuvers with Mux and Demux Blocks, specifying interfaces with Bus Objects, and nonvirtual buses.

Now it’s your turn

How do you use bus and mux signals? What kinds of modeling questions about composite signals do you have? Care to share? Post a comment below. If you want to show off the complicated bus hierarchy from your model, e-mail me a picture of your bus and I’ll post it for you (image tags are stripped from comments).

March 18th, 2008

A Historical Tour of the Library Browser

When I started using Simulink, the libraries were organized a little differently than they are today. There were fewer blocks and no such thing as a Library Browser. Take a look at Simulink 1.3c from 1996.

The Simulink 1.3c Library

This version was a little before my time. However, users of that era may remember it. When I joined The MathWorks in 1998, the Simulink 2 library looked like this.

The Simulink 2 Library

The main challenge with Simulink 2 was screen real estate. In order to build a model, you had to open each of the sub-libraries in a new window. First, you would need a Signal Generator, so you open Sources. Next you need a Unit Delay, so you open the Discrete library. Then you need a Scope, so you open Sinks, yet another window. In a short time your desktop would look like this.

Simulink 2 Libraries on the desktop

In the latter part of 1998 Simulink 3 was introduced. Along with it came the Library Browser on the PC. It was revolutionary because you didn't have to clutter your entire desktop with windows to get access to the blocks you needed. This made a real difference if all you had was an 800x600 pixel monitor.

Simulink 3 Library Browser

Unfortunately users on non-Windows platforms were stuck with the old interface. Even Simulink developers who preferred Linux we relegated to the "old school" libraries. Luckily, screen sizes have continued to increase since the 90s.

R2008a

With the release of R2008a all platforms can now use the same Library Browser. Our Linux-loving Simulink developers can now use the same great Library Browser we have on the PC. The Library Browser has a new grid view in addition to the traditional list view.

Simulink R2008a all-platform Library Browser

Notice the search tab, item 1 in the diagram below. This is an improvement over the old version. When searching, you will now see all the results in one place rather than having to walk through the tree to view each match. The results are grouped by library and can be collapsed to simplify browsing (2). The search options (3) also allow for regular expressions.

Simulink R2008a Library Browser Search Feature

The R2008a Library Browser has improved graphics and better performance compared with previous releases. The old version would redraw all blocks each time you viewed them, and in order to see the blocks in a library it had to be loaded into memory. The new browser uses caching to improve performance. The cache also enables faster searches without fully loading all libraries into memory. By the way, building the cache incurs a one time cost which you may notice the first time you start the Library Browser.

After seeing the new Library Browser, most people ask the same question:

But Seth, how do I add my library to the browser?

It has always been possible to add a library to Simulink, and you can read about it in the documentation. In order to add a library to the browser, create an slblocks.m file. You should store it in the directory with your library. I’m going to use the example library from a previous post. The most basic slblocks.m file looks like this:

function blkStruct = slblocks  
%SLBLOCKS Defines a block library.  
 
% Library's name. The name appears in the Library Browser's  
% contents pane.  
 
blkStruct.Name = ['A PID' sprintf('\n') 'Library'];  
 
% The function that will be called when the user double-clicks on
% the library's name. 
 
blkStruct.OpenFcn = 'pidLibrary';  
 
% The argument to be set as the Mask Display for the subsystem. You
% may comment this line out if no specific mask is desired.  
% Example: blkStruct.MaskDisplay = 'plot([0:2*pi],sin([0:2*pi]));';
 
blkStruct.MaskDisplay = '';
% End of blocks

After creating the library, you will need to select Refresh Tree View from the Library Browser View menu.

Simulink R2008a Custom Library

It is also possible to specify multiple libraries within the same slblocks.m. I recommend looking at the other slblocks.m files on your path for examples.

>> which -all slblocks

A well-documented example is in $matlab/toolbox/simulink/blocks/slblocks.m. You can start by making a copy of that one and then edit it to reference your library.

Try it yourself

If you have never added a library, try making a library of your most commonly used components. Select File -> New -> Library from the Library Browser. Drag in your favorite blocks and add this to the Library Browser to increase your productivity.

Do you have custom libraries? Are they displayed in the Library Browser? Let me know in the comments.

March 11th, 2008

Springtime and R2008a

I am eager for winter to release its icy grip on New England. Fortunately, change is in the air and spring is around the corner. At work, the big change is the new release of MATLAB. After installation I immediately notice the slight differences in the UI.

The new release of MATLAB and Simulink products went live for download at the beginning of this month. You can read about some of the changes to R2008a in the release notes. Here are some of my favorites:

Over the next few months, as the spring flowers bloom (for those of us in the northern latitudes), I will highlight many of these new features.

These are some of my favorite enhancements to Simulink products. Have you activated your new copy of R2008a? What do you see in the release notes that you want to try out?

March 4th, 2008

Searching in Simulink

Here we have an example library consisting of masked subsystems.

sys = 'pidLibrary';
open_system(sys)

When you double click on a block, you get the mask dialog, and the Help button displays the MaskHelp if you click on it.

Some of these blocks are properly documented, but others have no MaskHelp. You could click through all the blocks in this library and click on the help button, but that would be a painful manual process. How can you audit this library and ensure that the components are properly documented?

find_system

find_system is a very powerful tool for scripting in Simulink which allows you to automate tasks that might otherwise be time-consuming to perform. The find_system syntax is very specific:

find_system(sys, 'c1', cv1, 'c2', cv2,...'p1', v1, 'p2', v2,...)

find_system takes a set of constraints ('c1', cv1, 'c2', cv2) and searches for blocks in the system (sys) that have the specified parameter values ('p1', v1, 'p2', v2). Notice that all constraint/value pairs are passed to find_system before the parameter/value pairs. This confused me once when I got the order wrong, so watch out for that.

Here is a quick find_system command that returns the right answer.

blksNoHelp = find_system(sys,'MaskHelp','')
hilite_system(blksNoHelp,'find')
blksNoHelp = 
    'pidLibrary/Continuous PI 
Controller'
    'pidLibrary/Discrete PI 
Controller'

It is important to be aware of the search constraint defaults.

  • SearchDepth is set to all levels, but this can be changed to 0 for only open systems, 1 to search only the specified system, 2 for that system and its children, etc.
  • LookUnderMasks defaults to graphical only, which means find_system doesn’t look under functional masks (those with a dialog and workspace).
  • FollowLinks defaults to off, which means linked blocks are not searched. This is very important when the block might reside in a library linked from your system.
  • FindAll defaults to off, which means you will only get blocks back from the search. The other option is to specify on and find_system will also return lines and annotations from the model.
  • CaseSensitive is on by default, so make sure your caps lock isn’t turned on. This constraint affects the value inputs only; parameters are not treated as being case sensitive.

In our example, if we were also concerned with the contents of those masked blocks, we would need to expand our search to LookUnderMasks. This search would then return Simulink base blocks because they do not use MaskHelp. To reduce the results to only those blocks that are masked, we can do a search where the Mask property is set to on.

blksNoHelp2 = find_system(sys,'LookUnderMasks','all',...
                             'Mask','on','MaskHelp','')
hilite_system(setdiff(blksNoHelp2,blksNoHelp),'find')
blksNoHelp2 = 
    'pidLibrary/Continuous PI 
Controller'
    'pidLibrary/Discrete PI 
Controller'
    'pidLibrary/Discrete PID 
Controller/Discrete Derivative'

Another reason constraints are so important is that the amount of work done by find_system is proportional to the number of blocks included in the search. If you are looking under all masks, following all links and searching the full depth of the model hierarchy, the speed of the search will be proportional to the size of your model. find_system is not a Simulink Google search that skips across indexed model information. When find_system is called it has to resolve all block parameters as it works. This means that you will evaluate all the dialog code and parameters required by the search. To speed up find_system, include the appropriate constraints to reduce the number of blocks being evaluated.

Tip: Where ever possible include a SearchDepth to cast a small net.

Challenge

This got me thinking about how you might perform the inverse of this search. How would you find blocks that have MaskHelp without specifying the value it is set to? The first person to provide a correct answer in the comments gains fame and notoriety as a find_system expert.

Did you already know how to use find_system? This is my second post and I’m looking for feedback on how much experience you have with Simulink. Post a comment and tell me what you think.


Get the MATLAB code

Published with MATLAB® 7.6

February 26th, 2008

Welcome!

Welcome to the MATLAB Central Simulink blog! The purpose of this blog is twofold: First, I want to share Simulink tips and tricks that I've learned over the years. At the same time, I hope to learn from you about your experiences with Simulink. Where is it good? How can we improve it?

I've been using Simulink for 9 years, first as a member of our technical support team, and then as a trainer. I still remember when I first learned about the power of Simulink as a newly hired support engineer back in 1998. During a training class I saw differential equations drawn on a whiteboard and then simulated with a few clicks of the mouse. I got excited by how clearly it all worked. Simulink provided me with a framework for thinking about systems and the relationships between their basic components.

Of course, Simulink is much more than a simple tool for solving differential equations. It has a richness and depth that will give me plenty of material to draw on. What kind of topics can you expect to read about here? We'll talk about applications of Simulink in controls, signal processing and communications system design. With your help, we'll talk about how Simulink is used in areas I don't even know about yet. We'll talk about Model-Based Design in general, and we'll get a peek at some of the internal machinery of Simulink. I look forward to posts about all of these:

  • solvers
  • sample times
  • modeling
  • hacks
  • blocks
  • model reference
  • libraries
  • masking
  • custom code

An example: batch simulation

Let me start off with a specific example about running simulations. Simulink models are built using block diagrams, and once they've been created most everyone runs them by clicking the run button on the toolbar.

If you have to run a sweep of parameters you might change the parameter and then click run, change it again and click run. But if you have to run hundreds or thousands of simulations while modifying a parameter you will want to write a script for batch simulation. You can run simulations directly from MATLAB with the sim command like so.

>> [t,x,y] = sim(sys);

This returns the root level outputs (y) and the internal states of the model (x) at each recorded time step (t). A batch script might look like this:

open_system('vdp_mu')
muSweep = .5:.1:1.5;
for i = 1:length(muSweep)
    mu = muSweep(i);
    [t,x,y] = sim('vdp_mu');
    plot(t,y); hold on;
end
title('VDP States for mu=.5 to 1.5')
xlabel('Time'); legend('x1','x2')

If you are already familiar with the sim command, then you probably know that some times you are only interested in the outputs (y) of the model, and not the states (x). For large models, or long simulations, those state variable outputs could be a waste of valuable memory. Using simset you can provide additional options to the sim command to specify that you only want time (t) and outputs (y). The state variable returned from sim will be empty.

[t,x,y] = sim('vdp_mu',[],simset('OutputVariables','ty'));
whos t x y
  Name        Size            Bytes  Class     Attributes

  t         206x1              1648  double              
  x           0x0                 0  double              
  y         206x2              3296  double              

You can learn more about sim and simset in the Simulink documentation.

What do you think?

That's your first Simulink tip. Now it's your turn. What do you like about Simulink? What would you like to talk about in future posts? Please leave a comment below. I have learned from Doug that t-shirts get comments on your blog, so I'll be randomly selecting five commenters on this post to receive a MathWorks t-shirt!


Get the MATLAB code

Published with MATLAB® 7.5


Seth Popinchalk is an Application Engineer for The MathWorks. He writes here about Simulink and other MathWorks tools used in Model-Based Design.
  • Bob: Occasionally we’ve used busses to parameterize a model. To cut down on function interface overhead, the...
  • Bob: Any particular reason you chose to specify the name of the atomic subsystem? I try to avoid that in case...
  • Justin Mellor: Seth, I have just ‘tuned in’ to this discussion about bus signals. As I am in the process...
  • Seth: @Paul J - The To Workspace block does not support bus signals, so when you are passing it a virtual bus it is...
  • Seth: @Markus - Thanks for the comments. Regarding using bus signals in libraries… The signal name information...
  • Markus: Hi Seth, here are two suggestions for your blog: If-then-else constructions are a bit awkward in Simulink....
  • dennis: Holle sir/miss i come from Taiwan. I have a question. I am planning to make the experiment. While needing to...
  • Markus: Hi Seth, very nice post with clear illustrations, thanks! I always wondered how to export a block with a bus...
  • Georg Wiedermann: Dear Seth, thank you for this blog on Simulink. With virtual vs. nonvirtual busses and bus objects...
  • Mriya: Hey Seth I want to implement a limiter for FM demodulation in simulink.dun know how to do it.It is basically...

These postings are the author's and don't necessarily represent the opinions of The MathWorks.

Related Topics