This example shows how to model a two-car elevator system with some of the common features expected in modern elevators such as call queuing, fire alarm responses, hall calls, etc.
Showcases the advantages of using atomic subcharts in such an application by comparing a model before and after introducing this construct.
Illustrates the workflow needed to modify the elevator system model to use atomic subcharts.
Simulating the model brings up this graphical user interface (UI):
In the UI, you click buttons on each floor hallway (the empty squares under each floor number) and inside the individual elevator cars (the numbered white buttons on a yellow background at the bottom of the UI).
The chart Elevator System consists of three main components.
The workhorses of this chart are the subcharts
Elevator_B: these subcharts represent the elevator cars in the model. The elevator cars are controlled by the
Each of these subcharts manages a queue of user requests:
Elevator_Manager subchart manages the hall queue. This queue holds all the requests generated when pressing a button at any of the floors.
Each of the elevator cars has its own queue that represents all the user requests that it needs to process.
The main purpose of the
Elevator_Manager subchart is to process and delegate all incoming user requests (represented as input events in the model) to either
Elevator_B depending on criteria such as proximity to the request and availability.
Each elevator car iteratively processes requests in its queue and continually updates both its status (
IDLE) and its position. The updated position is then used to drive the UI representation of the elevator car (to move the car or open its doors).
To open the original model, click here.
The elevator car subcharts have almost identical code (states, functions, and local variables) to process their individual user request queues. Because the elevator cars respond the same way to different inputs, the subcharts used to represent their behavior are prime candidates for linked atomic subcharts.
You can replace the elevator car subcharts with two links to a library atomic subchart that represents an elevator car.
In this example,
Elevator_B both refer to chart
Elevator in the library model sf_elevator_lib. You can then adjust the library atomic subchart without having to modify the linked instances.
Another use of atomic subcharts in the new model is in the UI Controller chart. Since the logic for controlling each UI elevator car is identical, we can also make the UI car controller a library atomic subchart and just link to it twice.
To open the UI Controller chart in the original chart, click here.
To open the UI Controller chart with linked atomic subcharts, click here.
To open up the final model that uses atomic subcharts, click here.
All the logic specific to a elevator car is now housed inside a separate Stateflow® chart. This design has several benefits:
Team development is easier. Because the elevator logic and the elevator manager logic are now in different model files, different users can work on these different portions without merge conflicts at submission time.
Because Stateflow does simulation through code-generation, separating the chart into two speeds up the process of testing incremental changes during simulation.
Because the library elevator chart is now reused, changes to the logic can be made once instead of being duplicated in multiple places.
This reuse also assists Simulink® Coder™ in generating reusable code for both elevators. In this case, the code for the elevator subsystem reduces by almost 500 lines of code: from about 1500 lines to about 1000 lines.
Separating the logic for an elevator into a chart also allows users to control code generation file-packaging options for the elevator chart.
To convert the elevator car subcharts to atomic subcharts, a few steps are needed. These steps reflect the rules that govern the use of atomic subcharts. For a description of these rules, see Rules for Using Atomic Subcharts.
The approach taken here is to make a library atomic subchart out of the
Elevator_A subchart and then use linked instances of this library instead of the elevator car subcharts.
Step 1. Export
Elevator_Manager functions and data to make them visible to atomic subcharts
Because atomic subcharts cannot call functions defined in a container chart unless they are exported, we need to pull the functions that are called by
Elevator_B from the
Elevator_Manager subchart to the chart level: doing so will make these functions visible to the atomic subcharts.
To export the functions at the chart level, migrate all the functions used by the elevator car subcharts out of the
Elevator_Manager subchart and into the parent chart as shown below:
The migrated graphical functions need to be renamed to distinguish them from the functions inside the elevator car subcharts. For example, the function
deregister can be renamed to
After that, in the Elevator System chart, you need to set the
Export Chart Level Functions property to be true. Now modify the
Elevator_Manager subchart to use these functions.
Note: The elevator car subcharts directly access a local variable (
hall_call_status) defined in the
Elevator_Manager subchart. Because atomic subcharts can only access chart-level data these variables need to be re-parented to the containing chart (Elevator System). The variable
hall_call_queue also needs to be re-parented to Elevator System because it is used by one of the exported functions.
Elevator_A subchart should then be modified to use the newly scoped variable.
Step 2. Make
Elevator_A fully defined and independent of Elevator System
To make the
Elevator_A subchart fully defined, do the following:
Using the Model explorer, migrate the constant Stateflow data objects such as
Elevator_A. These constants are used by both elevator cars.
Elevator_A to call the newly renamed exported functions of Elevator System.
Step 3. Create a library atomic subchart to replace elevator car subcharts
Once you have satisfied all the requirements to make
Elevator_A an atomic subchart, right-click on the subchart and select Make Contents > Atomic Subcharted. Subchart
Elevator_A will now have the label (Atomic) as shown below:
For more information on how to convert a state to an atomic subchart, see Example of an Atomic Subchart.
Next, create a library atomic subchart using
Elevator_A. Once you have created the library atomic subchart:
Change the Scope of the Stateflow data object
Output. This will enable you to link the atomic subchart output to that of the containing chart.
(Optional) Rename the inputs and outputs of the atomic subchart to be more general. For example, replace
Once you are finished, save the library model and then copy and paste the atomic subchart twice inside the Elevator System chart to replace the subcharts
To open the library model, click here.
Step 4. Map data and events for both linked atomic subcharts to those of parent chart
The chart Elevator System has 4 outputs, 2 outputs for each elevator car subchart: each elevator car subchart outputs the current position and the current status on whether the elevator door is open. These outputs need to be mapped appropriately to the individual elevator car subcharts.
One of the Elevator System inputs (
fire_alarm) is fed directly to the elevator car subcharts so that also needs to be mapped.
Since the elevator cars need to know about the status of each hall floor button (stored in the
hall_call_status variable in Elevator System), we need to map that to a data store memory in the atomic subchart.
Lastly, the input events used by each elevator car, namely the clock and car call request events, need to be mapped to those of Elevator System.