When do you implement a state machine [SOLVED].

Thread Starter

Pushkar1

Joined Apr 5, 2021
416
There are many ways to write c code for a embedded System. I see that many people use state machines. When do you think you should implement a state machine in an embedded project. What are the benefits of implementing a state machine?
 

Thread Starter

Pushkar1

Joined Apr 5, 2021
416
I asked this question because I have seen that many people use state machines. I just wanted to know when and in which situation we should use state machine for real-world project. Maybe a better help would be if you explain the reason with project
 

DickCappels

Joined Aug 21, 2008
10,152
The last time I created a simple state machine it was with an EPROM and D-latch to get the clock rate down below 10 kHz so the equipment would not have to pass RFI/EMI tests.

Sate diagrams are great for specifying the performance of complex systems - it allows the top view description while leaving the details until later. For example the power management behavior of a computer and a display monitor were neatly specified as a state machine, thought the software architect took some convincing to use that instead of a flow chart.
 

BobTPH

Joined Jun 5, 2013
8,813
My take: the state machine is a formality that we teach to students in order to get them thinking about how you can organize a program logically. In real use, it is rarely implemented in the formal way that is taught, but the ideas are still used in a less obvious way, (my original response was already taken by Mr Chips.)

Bob
 

dcbingaman

Joined Jun 30, 2021
1,065
There are many ways to write c code for a embedded System. I see that many people use state machines. When do you think you should implement a state machine in an embedded project. What are the benefits of implementing a state machine?
There are plenty of examples. In my last project I have a set of wireless receivers that must communicate with one transmitter the transmitter being the master. Each receiver has a specific address and the communications protocol is very specific. In this case we must first have the correct address to move to the next state. In this state machine if we sit in any state for more than a set period of time we automatically move back to the starting state.
There are many ways to write c code for a embedded System. I see that many people use state machines. When do you think you should implement a state machine in an embedded project. What are the benefits of implementing a state machine?
Here is a simple example. This code is used in a wireless network with one 'master' and multiple 'slaves'. Only one slave is allowed to respond to a message in order to avoid collisions and because wireless communications must deal with possible errors in messages. Each message has a header/footer, address command etc.
 

Attachments

strantor

Joined Oct 3, 2010
6,782
My take: the state machine is a formality that we teach to students in order to get them thinking about how you can organize a program logically. In real use, it is rarely implemented in the formal way that is taught, but the ideas are still used in a less obvious way, (my original response was already taken by Mr Chips.)

Bob
I offer a different perspective. I began programming before I had any formal training. I had years of experience before I broke open a book and came across the concept of a Finite State Machine. It has profoundly changed the way the way I do things. I use state machines (I think) in exactly the formal way that is taught, and what I write now is much better than what I wrote years ago; I am confronted with the stark difference every time I have to go back and look at my old work. This is mostly referring to PLC programming but also some other things.
 

MrChips

Joined Oct 2, 2009
30,712
Have you created a state machine for a project. If your answer is yes, then I want to ask you why do you think you should create a state machine for the project?
Every MCU program is a Finite State Machine.

When you write the structure:

if (...)
then ...
else ...


This is a Finite State Machine.
 

strantor

Joined Oct 3, 2010
6,782
Every MCU program is a Finite State Machine.

When you write the structure:

if (...)
then ...
else ...


This is a Finite State Machine.
I won't say that's not correct but I think that's a narrow interpretation and TS's question was meant to address the concept of a state machine for a complex application from top down. Or maybe I'm projecting; that's what it means to me when someone says "state machine."
 

Thread Starter

Pushkar1

Joined Apr 5, 2021
416
I won't say that's not correct but I think that's a narrow interpretation and TS's question was meant to address the concept of a state machine for a complex application from top down. Or maybe I'm projecting; that's what it means to me when someone says "state machine."
@strantor I am agree with you that's what i mean. If we are using state machine in our project then we should know the solid reason why we are using it.

@MrChips Then it would not be wrong that every flow chart is a mcu program. but i don't disagree with your answer.
 

nsaspook

Joined Aug 27, 2009
13,086
The are many types of FSM. I use communicating finite-state machines when I need concurrency without the multitasking . They are very useful for modeling a communication protocol.
https://www.cs.utexas.edu/users/lam/Vita/Cpapers/GCL84.pdf

Stripped of code simple MODBUS master FSM with hierarchy and concurrency.
C:
/*
* simple modbus master state machine
*/
int8_t controller_work(void)
{

    switch (cstate) {
    case CLEAR:

        /*
         * command specific tx buffer setup
         */
        switch (modbus_command) {
        case G_SET: // write code request

            break;
        case G_AUX: // write code request

            break;
        case G_ERROR: // read code request

            break;
        case G_MODE: // operating mode request
        default:

            break;
        }
        break;
    case INIT:

        break;
    case SEND:

        break;
    case RECV:

            /*
             * check received response data for size and format for each command sent
             */
            switch (modbus_command) {
            case G_SET: // check for controller error codes

                break;
            case G_AUX: // check for controller error codes

                break;
            case G_ERROR: // check for controller error codes

               break
            case G_MODE: // check for current operating mode
            default:

        break;
    default:
        break;
    }
    return 0;
}

void main(void)
{
    /* Loop forever */
    while (true) { // busy work
        controller_work();
    }
}
http://beethoven.site.uottawa.ca/ELG7187C/CourseNotes/Literature/Boch78i - from Computer Networks.pdf
 

MrChips

Joined Oct 2, 2009
30,712
I won't say that's not correct but I think that's a narrow interpretation and TS's question was meant to address the concept of a state machine for a complex application from top down. Or maybe I'm projecting; that's what it means to me when someone says "state machine."
You are correct. I just want TS to understand that there is nothing special about state machine when applied to embedded application.

It simply means:

When the machine is in state 1, do A.
When the machine is in state 2, do B.
 

xox

Joined Sep 8, 2017
838
Another rather interesting thing about FSM's is that they can be easily implemented in the form of a software library which can then be used to quickly put together complex state machines. Maybe not efficiently enough for the most time-critical applications but in most cases anyway it won't have much of an impact on program performance.

I've used them for years now in that format for things like parsing text, flow control, coordinating complex interactions between software components, etc. Especially when it comes to quickly prototype something you can pretty much just "glue" programs together with different FSM objects...
 

strantor

Joined Oct 3, 2010
6,782
There has been some good discussion so far but most of it is not addressing the bold portion of the OP. I wanted to do so and my answer was going to be "state machines should be used: always. The benefits are: all." But I think my experience is very specific and therefore my answer would be not applicable to all. So I will do my best to answer big picture, from my small picture perspective.

In the opinion of strantor... State machines should be used when the operation is sequential and the status of inputs and outputs mean different things depending on the step of the sequence (which is almost always, for me). The benefits are greatly simplified handling of conditions and readability of code.

For example, a side-load clothes washing machine. It goes through a very clear sequence, and the handling of the inputs and outputs depends on the step of the sequence. What should happen when you press the "pause" button while the door is open vs. when during the spin cycle? What should happen if the door switch input goes low during fill cycle vs end of sequence? During which steps of the sequence should the door lock solenoid be powered? How about the drain pump? All of these questions are much more clearly answered by a state machine rather than a bunch of if-then statements.

To illustrate, I will first use pseudo-code if-then statements to begin describing the operation of the washing machine (not complete, just enough to illustrate) :
Code:
If startButton and doorSwitch = true:
   doorSolenoid = true
   playStartSound = true
   fillValve = true
   fillTimerRun = true
If levelSwitch or fillTimerFinished = true:
   fillTimerRun = false
   fillValve = false
   drumMotorRun = true
   drumTimerRun = true
If drumTimerFinished = true:
   drumTimerRun = false
   drumMotorRun = false
   drainPumpRun = true
   drainPumpTimerRun = true
If stopButton or drainPumpTimerFinished = true:
   drainPumpRun = false
   drainPumpTimerRun = false
   If levelSwitch = false:
      doorSolenoid = false
      playStopSound = true
There are a few issues with the above code:
  1. The start sound (assuming a little tune/jingle like my washer has) will keep playing until the stop button is pressed, when it will be canceled by the playStopSound (and then it will playStopSound until start is pressed again). Sure, we could add a timer for this, let's assume we go ahead and do that.
  2. If we press the stop button while the machine is filling, it will keep filling. The only way filling gets canceled is if the level switch goes high or it times out. We have to go back and add to the if-then statement for the stop button, that it will also cancel the filling. On top of that, we would need to add another timer to make sure it actually drained all the way.
  3. Same as #2, but for the drum motor. The above code would have the motor still spinning if you stop and open the door, so also need to add [drumTimerRun = false, drumMotorRun = false] to the if-then statement for the stop button.
  4. The doorSwitch with is only examined at startup, but what happens if the door wasn't 100% properly closed and comes ajar as soon as the drum starts spinning? We need to go in and add error handling for the door switch to each if-then statement.
  5. If at any time during the sequence, someone mistakenly presses start again, the fill valve will open again, so we need to modify that first if-then statement to be like If [startButton = true and doorSwitch = true and fillTimerRun = false and drumTimerRun = false and drainPumpTimerRun = false]
Our if-then statements are already growing a bit out of control, and we have only just begun. As we add more steps to the sequence (weight distribution, spin cycle, detergent metering, bleaching, etc) they will grow exponentially! There will be ifs nested in ifs nested in ifs nested in ifs to the Nth level in order to handle every possible condition of all the inputs and outputs. It is hard to consider every possibility and remember to handle every condition (in every place it needs to be handled) when programming this way. A state machine is a much better way to handle it. Here's how I would do it:
Code:
If state = 0: # waiting
   If startButton and doorSwitch = true:
      copy (10) to state
If state = 10: # play start tune
   copy (5sec) to stateTimerPreset
   If stateTimerDone = true:
      resetStateTimer
      copy (20) to state
If state = 20: # filling
   copy (50sec) to stateTimerPreset
   If stateTimerDone or levelSwitch = true:
      resetStateTimer
      copy (30) to state
If state = 30: # drum run
   copy (600sec) to stateTimerPreset
   If stateTimerDone = true:
      resetStateTimer
      copy (40) to state
If state = 40: # drain
   copy (55sec) to stateTimerPreset
   If stateTimerDone = true and levelSwitch = false:
      resetStateTimer
      copy (50) to state
If state = 50: # play stop tune
   copy (5sec) to stateTimerPreset
   If stateTimerDone = true:
      resetStateTimer
      copy (0) to state


If state >0: stateTimerRun = true; Else: false
If state >0: doorLockSolenoid = true; Else: false
If state = 10: playStartSound = true; Else: false
If state = 20: fillValve = true; Else: false
If state = 30: drumMotorRun = true; Else: false
If state = 40: drainPumpRun = true; Else: false
If state = 50: playStopSound = true; Else: false
If stopButton = true or doorSwitch = false:
   if state <20:
      copy (0) to state
   Else:
      copy (40) to state
From here, it is easy to add steps (states) to the sequence in the top half of the code and also easy to handle input and output conditions to the bottom half.

Hopefully this example illustrates the benefits of a state machine and also gives some context you can use develop your own opinion about when/where they should be used.
 
Last edited:

nsaspook

Joined Aug 27, 2009
13,086
Just a style note for C:
Using ENUM's, switch blocks and maybe function pointers makes the C FSM code more readable and maintainable than "if then else logic".

State machines are a form of declarative programming/logic that can simplify implied or real concurrency, when you're at state x you know that preconditions [x0,x1,x3,..] are satisfied so that reduces conditional checking for processing at state x.

https://en.wikipedia.org/wiki/Declarative_programming
 

MrChips

Joined Oct 2, 2009
30,712
Agreed. Use enum to make the code easier to follow.

Here is a typical example of using enum in a state machine.

enum State {POST, STARTUP, IDLE, ARMED, TRIGGERED, RUNNING, PAUSED, SLEEP, FAULT};
 
Top