Arduino Tutorial on Finite State Machine Implementation

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in this video we're going to be talking about something called a finite state machine which is a very useful structure for thinking about designing firmware for embedded systems and for mechatronic systems and we're going to show a couple of or walk through a couple of different ways of coding up a finite state machine and just to remind you of what's connected here to my arduino in case you skipped the blinking led series of videos here i have three leds which we're going to make use of in this finite state machine i've got a green led connected to pin d13 we've got a yellow led connected to pin d12 and we've got a red led connected to pin d11 and these are in series with a 200 ohm current limiting resistor in each case and we've got two tactile switches the switch pulls high the two different inputs d10 is connected to switch 1 and d9 is connected to switch 2. and and so when we push the tactile switch that pin is going to go high and then we've got a 10 kilo ohm pull down resistor that's going to be responsible for restoring the voltage on the digital inputs back low once the switch lets go so we also have the pot here connected to a0 but we're not going to make use of the pot in in this particular example and so a finite state machine is a system a computing system that has a certain finite number of different discrete modes of operation or states that it can be in and you'll make a transition from one state to another when certain um certain events take place and we usually represent the sort of state transition behavior for one of these things as a graph and so here i'm going to represent the behavior of my simple state machine example here with three circles so the nodes in the graph represent the different states and we're going to call this one red we're going to call this one yellow i'm sorry this one is green this one's going to be green yellow and red and the behavior in the green state is going to be very simple the led is the green led is going to be on steadily in the green state in the red state the behavior is also going to be very simple the red led will be on constantly in the red state the yellow state is a little bit more interesting in the yellow state the led the oled is going to be flashing at 1 hertz so it'll be on for 500 milliseconds and off for 500 milliseconds tremendously interesting and so um what we do is we represent a state transition by a directed uh edge in the graph and so in this particular case and we're going to be able to go from the green state to the yellow state and we label the edge with the event or with something that denotes the event that will late initiate the state transition so we're going to say switch one high so when we push switch 1 switch 1 goes high and if we're in the green state that will initiate a transition to the yellow state if we're in the yellow state we can get back to the green state by pressing switch 2. also in the yellow state we're going to be able to make a transition to the red state after 10 seconds have passed and that's going to be equal to or equivalent to 20 toggles of the led and once we're in the red state we stay in the red state there is no getting out of the red state so there are many different interpretations that you might be able to give to a system like this one which is a little on the ominous side would be that this is kind of like a simple bomb with a the green state being kind of a ready state and when we push switch one we arm the bomb and there's a 10 second fuse and then we enter the red state and that is boom and there's no getting out of the red state but once we're in the countdown phase we can go back to the the ready state and just disarm the bomb there are probably less ominous interpretations or stories you could tell to go along with this i'll leave that to your devisel or devising if you care too but i have this the state machine running and so we can see what it does if i push switch 1 you can see i'm going into the yellow state and if i'm in the yellow state i can push switch 2 and get back into the green state if i wait for 10 on off cycles to occur i go from the yellow state into the red state and i can push these buttons all i want to and i don't get out of the red state now i can of course reset the arduino by pushing this little reset switch here and after a few flashes i get back into the code and i run the code again and i'm in the green state switch to the yellow state switch back to the green state switch back to the yellow state and then if i wait long enough i go back to the red state so how does this code work well here we have um our blink interval just like we had in the blink led blink millis sequence of programs we have three different pins one for the green led one for the yellow led one for the red led we've got two pins defined for the tactile switches here we have something called a enumerated type which is going to be basically an integer variable that can take on a certain finite number of values which are named here these are going to be the value that represents the different states our finite state machine could be in we have the green state the yellow state and the red state and by default i believe green will have the value of zero yellow will have the value of one and red would have the value of two but we never really need to know exactly what those values are because we're going to be testing against green yellow and red instead of actual numbers like 0 1 and 2. and so this enumerated type we're defining has the name states and so we're going to make a variable called state which holds the current state of our finite state machine and it is of type states and then for the behavior in the yellow state we're going to have two global variables one remembers the time at which the yellow led last change state and then we have a 16 bit unsigned integer which is going to keep track of number of times that we've toggled the yellow led and so our setup function initializes the three led pins to the outputs the two tactile switch pins to the inputs and then we're going to set the green led high initially because we're going to be in the green state and that's what happens in the green state so we set that high initially we set the yellow and red leds low and we set the initial state of our state machine to be green and then inside the the event loop or the loop body um we're going to be doing a switch statement here we're going to look at the value of state and in the case that the value is green we're going to do this block of code in the case that it's yellow we're going to do this block of code and in the case of red we're going to do this very simple empty block of code because the there's no getting out of the red state and nothing happens in the red state so if we're in the green state we're going to basically check to see the value of switch 1 is high and if it is then we have to initiate a transition to the yellow state and so some things have to happen in that case we're going to have to set the green led to low and make the state assume the value of yellow then we're going to turn on the yellow led and we have to remember the time at which that happened and then we have to initialize the yellow count value to zero and then we'll be all set up to get into the yellow state now if we are in the yellow state we've got a little bit more work to do we have to keep track of the animation of the led so we have to check to see if it's time to toggle the yellow led and if it is we toggle the yellow led remember that time is the new yellow time and then we have to bump up the yellow count so this is very similar to what we did in our blink millis sketches and then we we start checking for the state transitions so in the yellow state if switch 2 is high then we want to go back into the green state so to do that we have to turn the yellow led off change the state to green and then we have to turn the green led on if we're not doing that then we check to see if yellow count is equal to 20 which means that 10 seconds have passed and that'll be time to enter the red state so we have to turn the yellow led off change the state value to red and then turn the red led on and then we're set up to go into the red state now this way of coding the state machine works it implements the behavior that we described and that we intended but it's not particularly great code for one thing we've got all of these cases all in one ginormous switch statement now this isn't really huge it fits on one page but you can imagine that if we had many more states or the behavior in each state was much more complicated then this could get to be a very long switch statement and we have these sort of you know if statements inside of the switch statement and um and that's that's not great the other problem with this code is that we've got stuff pertaining to the yellow state in the green state we've got stuff pertaining to the green state and the yellow state block and we've got stuff pertaining to the red state in the yellow state block and and that's really not very maintainable you could imagine that if multiple states if you can enter a state from multiple states then you've got the initialization code for that state in multiple places so you've got redundancy because you've got extra copies of the initialization code and if you were to have to change that you would have to find all the different places in the code where you do that same behavior and so that just makes the code very uh very unmaintainable and not very clean and so for a very simple state machine you can probably get away with this but it's it's not not super good practice to do so so i want to show you a second version of this which is basically a reorganization of this code into something which is much cleaner and much more maintainable um i didn't want to do that i want to lower this and where do i find my other one there we go i didn't want to make that big i want to make that there okay so here we have the same basic constants as we had in the in the first version here we're adding a fourth value of none to our enumerated data type and that's going to represent not one of the actual states but it'll represent sort of like a null state for us you'll see why that is in just a minute here and so we we have now two variables of type state one encodes the current state just like it did before and we're going to also remember the prior state like the last state that we were in and now instead of having one giant switch statement we're going to have we're going to break up the behavior of each of the states into separate functions and if these were complicated we might even put them in separate source files but we're going to call the state handler function for the green state green we're going to call the one for the yellow state yellow we're going to call the red one red strangely enough and these are going to be simple functions that don't return any values and don't have any any parameters and so what we're going to do is when we first enter the state handler function we're going to check to see if the value of the current state is different than or different from the value of the prior state if they are out of sync with each other that's going to be an indication to us that we just made a state transition and we're calling the state handler for the first time since we made that transition and what we're going to do here is we're going to basically put the initialization code that handles what happens when we enter a state here and so this happens only once in the code and that's that's going to be very nice so if we see a discrepancy between state and prior state then we make prior state the same as state so that the next time we enter this code we will not enter the body of this if statement and here our initialization code for the green state is to turn the green led on by setting green led high after we've done the initialization if necessary then we have a place to put code that performs state tasks in the case of the green led there's nothing no ongoing tasks that need to be performed and then we have code that checks for state transitions and here we only have one state transition and if switch 1 is high then we want to change the state to yellow but we don't need to do the stuff to clean up the green state to exit the green state or the initialization stuff to go into the yellow state so this is very very nice very clean so if we're going to make a state transition all we do is we change the value of the state variable to the new value to the next state and then the last thing we do before we leave the state handler function is we again check for a discrepancy between state and prior state so the only way that that will happen is if we've made a state transition and that'll be our signal to do any cleanup tasks that need to be done when we leave a state and so in this case for the green state we need to turn the green led off when we leave the state and so by using this sort of state not equal to prior state check at the beginning and the end we can actually very nicely encapsulate all of the behavior associated with the green state in the green state handler function and not have duplicate code running around in other states that pertains to this state so that that's a very nice way of partitioning the code into a separate chunks that make it very maintainable so all the stuff that pertains to the green state is in this green state handler function so the yellow state handler function is going to have a very similar structure it'll be more interesting in this case because the yellow state is a more complicated and more interesting state so if if in the yellow state handler function if we find that state is not the same as prior state then we sync up prior state to the same value as state and we turn the yellow led on remember that time and set the yellow count to zero so this was the initialization code that we needed to do when we entered the yellow state but now it's here in one place only so our state tasks for the yellow state are to check the time and to see if it's time to toggle the yellow led and if it is we do so and we bump up the yellow count state transitions okay so if switch 2 is high we change the state to green else if yellow count is 20. then we change the state to red and so again this is just changing the state variable to a new value and then on exit we check to see if we've made a state transition up here somewhere and if so then we turn the yellow led off and that's all there is to the yellow state function now the red led state or state handler function has the initialization part that turns the red led on there's no state tasks there's no state transitions and here i have included an exit condition here that turns the red led off and that i figured this would be useful in case we ever wanted to add to this state machine and make a transition out of the red state we would already have that that code here in place there's no chance that this code will ever be executed in the case of the red led or in the case of the red state as the state machine stands so you know you could comment this out if you wanted to but i generally i guess i would probably keep it in myself but that would be up to you so our initialization is a little bit different in this case or a setup function sets up the configures the output in the input pins but in this case we're setting all of the yellow red green and yellow leds to be low instead of setting the green one high because we're going to set the green one high when we first enter the green state handler function for the first time so this is all uniform now instead of having a special one that we deal with separately and then we have to initialize prior state to a value that's different than the initial state so that we will execute the initialization code for the green state when we first enter that so here i've used that value of none because there had there hasn't been a prior state yet when we first are starting up so that seemed to make sense to me and then i set the initial state to green and that's it our loop function is a very simple switch statement that basically just in the green case calls the green state handler and the yellow state calls the yellow state handler and the red state calls the red state handler and so that is a very clean very short loop function and this code is much cleaner much more maintainable than the original code so it looks a little bit longer but that's because we've added some comments and because we've kind of added these new functions here so anyway this is this is a very nice way of coding up a finite state machine so if i push this out it'll behave the same way as the original code did now we're in the green state or in the yellow state and go back to the green state we can wait the 10 seconds and transition into the red state and there you have it so that's it for now thanks for watching
Info
Channel: bminch
Views: 10,099
Rating: undefined out of 5
Keywords:
Id: TRgUtG_C3FI
Channel Id: undefined
Length: 22min 0sec (1320 seconds)
Published: Mon Sep 20 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.