Using delays in a state machine - delay

I'm using a finite state machine to control the voltage of power supply.
I've three states programmed:
OFF
ON
Stop
OFF state: the output voltage is 0V, the microcontroller is waiting for an input if there is no input it remains in the same state.
ON state: In this state the output voltage will increase progressively until it reaches some preset value if this value is reached the power supply will turn off. From this state the power supply can also change to Stop or to OFF if the proper signal is received
Stop: In this state, the output voltage will reaming constant at the last reached in the ON state. From this state, the power supply can return to ON and continue increasing the output or go to OFF.
My concern is the following, while in the ON state if the voltage limit is reached the state won't change immediately, the output will remain constant for a time delta_t, and then it will go to OFF I'm already implementing that behavior in the ON state, should I add a different state for this time for this transition when the voltage isn't increasing? or it is correct to have the delay within the state? This new state will basically just be a delay.
Edit.
This is the ideal output when the power supply is in ON state, It starts at 0, the increase until it reaches a preset value, remains in this value for a given time and the it goes to OFF state.
I've put current instead off voltage in this image, but since the load is pure resistive it makes no difference.

If the voltage plateau is an intended behavior (i.e. you have instantaneous control over the voltage, and your state machine is deliberately holding it high): It could make sense to split the 'ON' state into separate 'RAMP' and 'HOLD' states.
If the voltage plateau is a consequence of external hardware (e.g. your state machine stops sending the 'on' signal, but there's some delay before the actual behavior of the system catches up: It could make sense to add a separate 'WAIT' state, which either waits for a fixed time (if the delay is very repeatable), or operates in closed-loop fashion (e.g. measure the voltage, stay in 'WAIT' while it's nonzero, then transition to 'OFF').
In either case, it seems like the system is doing something different than during the voltage ramping phase, so a separate state makes sense.

Related

How can a parallel region change state of the other region in UML state machine diagram

I have a state machine diagram for an application that has a UI and a thread that runs parallel. I model this using a state with 2 parallel regions. Now I want when that thread gives some message, for example an error, that the state of the UI changes, for example to an error screen state.
I was wondering what the correct method to do this is, as I was not able to find any example of this situation online.
The options that I thought of were creating a transition from every state to this error state when the error state is called, which in a big diagram would mean a lot of transitions. Or by just creating a transition from the thread to the error state (As shown in the image), which could possible be unclear.
Example of second option
You don't need a transition from every state. Just use a transition from the State State to the Error window state. It will then fire no matter what states are currently active.
Such a transition will also leave the Some process state. Since you didn't define initial states in the orthogonal regions, the right region of the state machine will then be in an undefined state. Some people allow this to happen, but for me it is not good practice. So, I suggest to add initial states to both regions. Then it is clear, which sub state will become active, when the State state is entered for any reason. The fork would also not be necessary then.
How you have done it in your example would also be Ok. However, since the Some process state is left by this transition, this region is now in an undefined state. Again, the solution to this is to have an initial state here. I would only use such a transition between regions, when it contains more than one state and the On error event shall not trigger a transition in all of the states.
If the Some process state is only there to allow for concurrent execution, there is an easier way to achieve this: The State state can have a do behavior, that is running while the sub states are active. Orthogonal regions should be used wisely, since they add a lot complexity.

What does 'do' do in an UML Statechart diagram?

I am not 100% sure what 'do' does in an UML statechart diagram.
Is my thinking correct:
If a transition happens, 'entry' will be executed first and then 'do' will be executed.
And if we are leaving the state only 'exit' will be executed.
Does this logic apply to reflexive transitions as well?
And what if a trigger happens, that does not set off a transition? Does this only execute 'do'?
The UML Specification tells us:
14.2.3.4.3 State entry, exit, and doActivity Behaviors
. . .
A State may also have an associated doActivity Behavior. This Behavior commences execution when the State is entered (but only after the State entry Behavior has completed) and executes concurrently with any other Behaviors that may be associated with the State, until:
it completes (in which case a completion event is generated) or
the State is exited, in which case execution of the doActivity Behavior is aborted.
The execution of a doActivity Behavior of a State is not affected by the firing of an internal transition of that State.
You :
Does this logic apply to reflexive transitions as well?
As said by the last sentence above that depends if the reflexive transition is internal or external.
To add to bruno's answer something more specific.
As stated in the UML specification (and quoted by bruno in his answer) the do activity is performed while the system is in a certain state (after entry activities were completed). It is performed during the whole time the system is in the state. The do activities cease to be performed only in two situations:
The transition taking you out of the State is triggered; in such case, the do activities are interrupted, exit activities if any, are performed and then the transition occurs. The transition can be reflexive (i.e. once completed the system returns to the same state), in which case first entry activities will be carried out and once they are completed, the do activities will start again.
The do activities finish on its own; in such case, once the do activities finish it's time to leave the state. So the eventual exit activities are performed and the transition is performed. A valid system should have one or more transitions without a triggering event (if more than one then they should have conditions allowing to uniquely determine which one will be used) that would be followed once the exit activities (or do if there was no exit) completes.
Let's have a more tangible example. Consider a washing machine. There are two interesting states in it, one is filling with water, the other one is drum rolling.
For the filling with water state, one can expect the following activities:
entry: open water valve
do: monitor water level
exit: close water valve
Now, once the washing machine gets into the state, the valve is being open (entry) and immediately afterwards the machine starts the do: to monitor the level of water (as water now flows in freely). Once the set water level for the current program and step is reached, the event "water level reached" is sent, initiating next transition. As a result the do activity is stopped (there is no more point in monitoring the water level) and the exit is carried out (valve is being closed), followed by the transition to the next state (e.g. heating or drum rolling depending on the program stage).
As you can clearly see, in such case the do activity is interrupted once the transition trigger is captured.
For the drum rolling the situation is quite different though. For the sake of simplicity we will have just one *do( activity, with no entry or exit activities:
do: rotate the drum for n seconds with n speed
When the washing machine enters this state, it immediately starts rolling the drum and (unless interrupted by some exceptional event) keeps doing it for the predefined amount of time. Once that time elapses, the do activity interrupts immediately and the transition to the next state happens. In such case, it is the do activity that controls when the next state transition occurs, at least in the typical scenario.

State machine program design in FreeRTOS - Task managing the state changes

Following on the discussion at State machine program design in FreeRTOS - vTaskStartScheduler in a switch statement, I have a state machine with 4 states, each of them with different tasks reading sensor data.
When a sensor data reaches a threshold, its task has to cause a state change.
The idea is to have a superior task which controls the states (and suspends/resumes corresponding tasks) with a switch statement. My question is: how should the sensor tasks communicate the STATE with the superior task?
One proposed solution is to have a set_state function which is called by the event generating task, but I read that having global variables in FreeRTOS is discouraged. I thought to implement it through Queues:
1- Task1 detects sensor threshold, and sends STATE to a Queue.
2- Superior task is blocked waiting to receive data from Queue. When it receives STATE, the switch statement processes the state change.
If this approach is correct, my doubt relates on how and where should be STATE defined (global, or just existing in the stack of each task, or the superior task...)
STATE should exist only where it needs to, 'in' the superior task. I'm presuming you're using C, so declare STATE as a static variable in "superior_task.c" (or whatever it's called). This means it can then only be affected within that file - the C equivalent to a private member variable in C++.
Then, if your inferior tasks need to affect a state change, they post a state change event to a queue managed by the superior task. When the queue is processed, the superior state makes the change to the private STATE variable.
If other tasks need to know what the state is for their own processing, they can use an accessor for the private variable, e.g., State get_state() { return STATE; }. As Martin says though, the other tasks shouldn't need to know the state, as otherwise there's inter-dependencies between tasks that shouldn't exist.

In Verilog, whether always #(*) expects the actions to be completed in 1 clock period?

In Verilog, my peripherals are running at 100MHz = 10 nano seconds. In once always#(positive) block I was trying to do operations that exceeds 10 nano seconds. I rearranged the code so that the operations are performed now in an always#(*) block. Even now I have the same issue and my bitstream is not getting generated. So my question is why should always block should worry about the period ? as synchronization between clock and always#(*) block is not expected
While I cannot be certain that this is your problem without knowing more about your code and the synthesis results; it is possible you are running into a timing problem where the logic in your design cannot complete in a single 100MHz cycle.
When creating a sequential designs, one must always be aware that real logic has propagation delay. This means that the more logic is in between to registers (ie, that needs to be completed in a single clock cycle), the longer that logic will take in real time. Thus, what it seems you might be facing is that the amount of calculations you are trying to do in a single step takes longer than the clock period (minus the setup time of the registers that store the result).
Its also important to note that while changing your design from using a single always #(posedge) to an always #(*) will not result in any major changes in the synthesized result as the design you are describing is effectively the same (ie, a bunch of logic doing some calculations, followed by a set of registers to store the result). While simulating the design might be different, the hardware synthesized from the code will be very similar, thus the problem will remain.
In order to fix such timing problems, you can either break the logic into smaller pieces and pipeline it or you can change the design to bew iterative (taking multiple clock cycles). It is possible you might be able to change the logic in the design to convert long chains into tree structures or other things to try and break up the longest paths through the logic (thus decreasing overall propagation delay), but depending on the design, that might not be possible.

State machine for an Embedded System

I have implemented a simple state machine for an embedded system using C's switch statement. I know it would be better if I used function pointers with a look up table but I'm saving that as a next step.
My state machine has the following states:
Startup (the initial state)
Startup Error.
Idle (the system only checks for input in this state. It does not update the display or anything else. It's just 'idle').
Check (this is the actual application)
Program
Copy to Internal Memory
When the system starts up, it enter the startup state which configures the ports, initializes the display and does a hand-shake with the ICs connected on the SPI bus to ensure everything is A-OK. If so, the system enters the Idle state. If not, it enters the Startup Error state, displays an error on the LCD, flags a variable and then enters the Idle state.
In the Idle state, the program polls 3 pins on the microcontroller to check if one of the 3 buttons (Check, Program, Copy to Mem.) is pressed. Depending on which button is pressed, it enters the appropriate state, executes some code, updates the LCD and then returns back to the Idle state. NOTE: The system does NOT care if a button is pressed if there was a hardware fault in the system. The Startup Error state flags a variable called hardware_fault which, if set, ensures that the Idle state does not bother polling any of the input buttons.
This is the first time I'm implementing a state machine and I was just unsure if this was a good design. I haven't really seen any examples of FSMs where they poll for input in an Idle state. Instead, it seems, most examples are rather sequential in nature (like a counter, for instance). So, my question is, is my design reasonable? It DOES work but as everyone here knows, there is bad design and then there is good design.
You should refactor your code away from a switch statement and use a transition table as you mention. Code around a switch doesn't scale, is messy and quickly becomes difficult to read and update.
To answer your question, I would say that most state machines are actually like yours: they react to events (in your case, the poll). If they are purely sequential, without events at all, they are for specialized usages, like implementing a regex...
As a note, the Idle state is equivalent to the runtime core of a state machine library: it intercepts events and posts them to the state machine. With a state machine library, it would be "hidden" from the client code, while a bare bones implementation like yours has to do event polling explicitly.
And now a design critique: one should avoid global variables in general, and especially so in a state machine. State Idle should not know about a hardware_fault global variable. With state machines, one should strive to "embed" global variables in the state machine itself, by adding states (when it makes sense!). A very good introduction to (hierarchical) state machines and explanation of the rationale is here.
Using the UML notation (see here for a tutorial), your state machine is:
An easy refactoring to remove the hardware_fault dependency all together is:
That is, we just stay forever in the StartupError state, without transitioning to Idle.
The ε (epsilon) represents an empty transition, that is, a transition that is taken as soon as the activity associated with the source node is over, without any event. This is what you mean by "sequential" state machines.
I am also including the sources to the first diagram (the second one is very similar), generated with the very easy and powerful PlantUML.
#startuml
skinparam shadowing false
title Embedded v1
state Startup
state StartupError
state Idle
state Program
state Check
state Copy
Startup : entry/ init HW
StartupError: entry/\n display error\n hw_fault = true
Idle : do/ if not hw_fault: poll
Program : do/ program
Check : do/ check
Copy : do/ copy
[*] -> Startup
Startup -> StartupError : ε [error]
Startup --> Idle : ε [not error]
StartupError --> Idle : ε
Idle --> Program : program_btn
Idle --> Check : check_btn
Idle --> Copy : copy_btn
Program --> Idle : ε
Check --> Idle : ε
Copy --> Idle : ε
#enduml

Resources