What do you recommend for me to use as my first state machine design?
Found at least two different approaches and would like to hear your personal opinions about your favorite state machine design.
So far I have two real time inputs - optical encoder and “option select” button ( state machine) , nothing too time critical.
Basically looking for a design which is well documented to be able learn how state machine works.
.
Cheers
Vaclav
Seen this one of mine?
http://www.thebox.myzen.co.uk/Tutorial/State_Machine.html
Nick has an example here that may be of interested:
And here:
http://forum.arduino.cc/index.php?topic=136853.0
http://forum.arduino.cc/index.php?topic=169862.0
http://forum.arduino.cc/index.php?action=profile;u=38681;sa=showPosts
I use a simple approach like this
void loop(){
currentMillis = millis();
if ( (digitalRead(buttonPin) == LOW) && ((currentMillis -buttonPressTime) >=buttonDebounceTime) ){ // allow another press (also press & hold) if long enough since last press
buttonPressTime = currentMillis;
codeState = codeState +1;
if (codeState == endState){ // reset to beginning
codeState = 0;
}
}
// execute selected state - could be same state if nothing changed it
switch (codeState):
case 0:
// code
// may include changing codeState to another value if conditions warrant
break;
case 1:
//
break;
:
code state n:
//
break;
}
// do other stuff if needed, Serial.reads, updating output displays, etc.
} // end loop
I have written a statemachine library. Gives very clean code and very easy to use provided you have done your state diagrams and verified them. Concurrent states are supported as are multiple machines sharing states. Timing functions are built in
http://playground.arduino.cc/Code/SMlib
feel free to ask for guidance and examples
two different approaches
Which two approaches? switch or table? Moore/Mealy or Turing?
Mark
nilton61:
I have written a statemachine library
Ah, thank you for that - good timing. I had come here to look for one! I very much enjoyed your writeup and explanation.
In fact, all the links provided are good - and Nick Gammon's links are always bursting with useful info.
Looking at my requirement, I'm not now sure whether a state machine is actually what I want. Here's a sort of mock-up in javascript:
If I could find an easy way to translate that to Arduino/C/C++, then I'd be very happy!
(In case anyone's wondering - no, I haven't found a magical way of making an Arduino play a podcast - it'll be controlling something else, but needs to keep track of where it is in the menu).
But that's some reading up I need to do. But just to say thanks for the good links, even though it wasn't my thread it was perfect timing!
nilton61:
I have written a statemachine library. Gives very clean code and very easy to use provided you have done your state diagrams and verified them. Concurrent states are supported as are multiple machines sharing states. Timing functions are built inArduino Playground - HomePage
feel free to ask for guidance and examples
Thanks
this will "solve" three "problem" for me - adding new library to Arduino , work with functions pointers and make real state machine since I did used switch and it just turned into hard to manage spaghetti code.
Let me do some reading before I start asking questions.
Thanks again
Vaclav
holmes4:
two different approaches
Which two approaches? switch or table? Moore/Mealy or Turing?
Mark
Normally you choose a approach where output is dependent on current state only. If i remeber right this is called a moore machine.
When you build a state machine in hardware you use tabulated boolean functions, this is very efficient but quite hard. In software there is no need for that. And switch statement are not that easy to read either. So a function pointer approach is probably the most readable.
So a function pointer approach is probably the most readable.
My sediments exactly.
I've got a series of macros that set up an array of function pointers. The definition of a state machine goes like this
FSM_TABLE_BEGIN (keypad, FSM_PIN_N_STATES, FSM_PIN_N_EVENTS)
FSM_STATE_BEGIN // STATE_IDLE
FSM_ACTION (handleKey) // EVENT_KEY STATE_IN_PIN/STATE_IDLE
FSM_ACTION (NULL) // EVENT_KEY_HASH STATE_IDLE
FSM_ACTION (NULL) // EVENT_KEY_STAR STATE_IDLE
FSM_STATE_END
FSM_STATE_BEGIN // STATE_IN_PIN
FSM_ACTION (handleKey) // EVENT_KEY STATE_IN_PIN/STATE_IDLE
FSM_ACTION (handleKey) // EVENT_KEY_HASH STATE_IDLE
FSM_ACTION (handleKey) // EVENT_KEY_STAR STATE_IN_PIN
FSM_STATE_END
FSM_TABLE_END
This is a PIN number handler with only a single function (handleKey), not the best example but that's as far as I got at the time. This FSM has 2 states and 3 possible events, actually just one event but three values passed to that event.
It was just a first pass at an easy way to set up an FSM, needs a lot more work yet.
Rob
Is this what you are trying to do? My #1 tip is: always start with a state diagram. Then the code will write itself
With my library it results in this code:
#include <SM.h>
#include <Keypad.h>
const byte rows = 4;
const byte cols = 3;
char keys[rows][cols] = {{'1', '2', '3'},
{'4', '5', '6'},
{'7', '8', '9'},
{'*', '0', '#'}};
byte rowPins[rows] = { 2, 3, 4, 5};
byte colPins[cols] = { 6, 7, 8};
Keypad keypad(makeKeymap(keys), rowPins, colPins, rows, cols );
SM pinNo(Idle);
unsigned long pin;
void setup(){
Serial.begin(115200);
}//setup()
void loop(){
EXEC(pinNo);
if(pinNo.Finished){
Serial.println(pin);
pinNo.Set(Idle);
pin = 0;
}//if(pinNo.Finished)
}//loop()
State Idle(){
if(keypad.getKey()=='*') pinNo.Set(readKey);
}//Idle()
State readKey(){
char ch = keypad.getKey();
switch(ch){//get char from keypad, non blocking
case '#': pinNo.Finish();
case '*':
case 0 : break;
default : pin = 10*pin+ch-'0';
}//switch
}//readkey()
Yes, that looks like it would do the same.
Rob
Here's another thread on the topic Finite State Machine Using Switch Statement. - Programming Questions - Arduino Forum
It's got three examples I wrote in Crossroad's style except that each state has a function to handle it rather than making it inline. Doesn't satisfy your desire to use function pointers though.
You can implement states as objects, or as functions, or as values. And there are endless more complicated approaches. The complexity of the problem will determine how complicated the solution needs to be, but for a problem small/simple enough to be implemented on an Arduino I would be surprised if it called for anything more complicated than a state variable and a switch statement to perform the logic associated with that state.
The important thing is to have states and transitions worked out before you start to code
Thanks guys.
Since I have some functions I'll go for Moore.
A real stupid question - at this point I prefer pencil and ERASER to start with.
What would be a simple UI approach?
I think OpenOffice may have some flow chart option, but I like KISS!
Cheers
Vaclav
Im using visio to create state diagrams. It works fine and has ready made shapes that are suitable. I'm sure other charting/drawing programs have that to
MS Powerpoint has lots of shapes too.
Hi Nilton,
I need to discuss your SM library. Maybe there should be another thread??
I have written a working collision-avoiding robot that uses a State Machine implemented with your library. That was great and makes sense.
BUT I need the equivalent of delay(ms); that is non-blocking. I tried your LED-blink example and it works but I was not able to apply that to my situation. I envision a State that looks like this:
---------------------( COPY )---------------------
State RoboStartState()
{
Serial.println("+++ RoboStartState");
digitalWrite(PIN13_LED,LOW); // LED Means Target Too Close
ForwardFast(); // Start moving forward
delay(25);
ForwardSlow(); // Start moving forward
delay(600);
RoboGo.Set(RoboStopLookState);
}// END State RoboStartState
-----------------( END COPY )----------------------
There would be a non-blocking Delay function so the State would re-enter to that Delay until it expired, and the State would then transition to another State.
Or would each such delay have to be in it's own State?
The complete working (with regular delays) code is HERE:
How should we communicate about this? I'd like to keep it public if possible.
Thanks! for you work on SM.