Tuesday, October 13, 2020

[Example] Creating a counter in Simulink (Block diagram approach)

Hi, today I'm going to present various solutions for implementing a counter in Simulink, along with some variations in order to enhance its functionality. The counter may start from the beginning of the simulation or get triggered by a specific event. It can also have a non-null starting value. Let's get started.

1) Objective:

Create a counter, either based on the simulation time or an external event.

2) Model configuration:

Most of my applications are used within the automotive industry, where various software components iterate at a fixed frequency. ECUs have a limited processing power and the strategies are adapted so that they do not require continuous tracking of system states, therefore I always set the solver to discrete, with a fixed simulation step. For this tutorial, the time-step will be set at 0.01s.

3) Solutions

a) Ramp

Well, first and foremost, the easiest way to implement a counter would be by using a ramp with a unitary slope. Therefore, at 0.5s simulation time, the output value will be 0.5. We can also control the starting time and value of the ramp output by entering the block parameters window (double clicking on the block). This is, however, a terrible implementation, as there is no possibility of using a more advanced logic to trigger the counter and the starting value is not visible when opening the model.

b) Sum with unit delay

Let's try something that we can have more control upon. Take a look at the block diagram below.
The 1/z block is called a unit delay. It will output the input value that was sent to it at the previous simulation step. Its initial condition can also be set in the block parameter pop-up window. By default, this will be 0. Note that this block is flipped (its input is to its right). You can do this by selecting the block and pressing Ctrl+I on your keyboard or you can Right Click->Rotate and Flip->Flip Block to achieve this. Our diagram now takes the previous value, to which it adds the value of a simulation step (0.01) every time the computation reiterates. 
Therefore every time 0.01 seconds pass, this specific amount of time will be added to the global counter value at the output of the add block. Controlling the initial condition will control the initial output.

However, there are still two issues to be considered: 
i) the initial output is still not visible; 
ii) for a default initial output (0), the counter will start at 0.01s, instead of 0 (therefore, it will always be one step ahead of the simulation time). 

Let's improve upon this.

c) Sum with unit delay and initialization

The quick way to initialize the counter is to add a unit delay after the constant block (with the initial output defined in the block parameter window of the unit delay).
We haven't even reached our final form! This still wasn't, in my opinion, the best approach to solve the issue, as we can't visualize the initial condition. Here's a better proposal below:
This implementation contains several more blocks. First of all, notice that the first port of the add block is fed by a switch. The switch outputs the value fed through the 1st (upper port) if the condition on the second port is met, else it will output the value fed through the 3rd port. In our case, I've added a constant block with a true value, followed by a unit delay with a false initial condition (these boolean values are recognized by Simulink, but make sure that they're all in lowercase). This means that, for the first simulation step, the lower port (equal to 0) will be fed , whereas afterwards, the upper port (equal to the simulation step) will be fed. Therefore, our counter will output 0 at 0s and it will increase accordingly after each simstep. 
The condition that is fed to the middle port of the switch can be replaced by anything else, in order to start our counter (see the pic below, where I've used a step triggered at 1s, followed by a unit delay with the initial condition at 0 so that I have 0.01 at 1.01 simulation time). Be careful though, as this tutorial does not cover how to reset the counter if the command falls (we'll cover that another day).

As a final note, please take into the consideration that the 0.01 constant is set at this value because it coincides with our simulation step (0.01s). If you choose a different simulation step, you should modify the constant so that both have the same values.

That should be it for now. I am soon going to write a tutorial on how to implement the same functionality using a state chart, followed by some more advanced features like holding and resetting the counter. Stay tuned!

No comments:

Post a Comment