jbellavance:
Someone new to the state machine concept are not necessarily new to programming. This tutorial is not about C++. It is about implanting a state machine in Arduino's environment which happens to be written in C++.
I my mind, using a "switch" construct is not easier than using enum, since I have met on this site, a few persons that only uses "if" constructs, "since you can to everything with that construct" and won't have anything to do with "switch". But I insist in using it because the "switch" construct is , IMHO, ideal to describe a state machine's behaviour.
A switch-case state machine is a good way to break a large or long top-down process into small pieces and wait intervals. A function with a state machine can achieve a whole process by running over and over. Your void loop() may run > 60 times a millisecond, over and over can get somewhere fast at that rate.
I have a demo showing how to use switch-case to remove calls to delay(). It hit me while I was de-blocking a greenhouse automation with a lot of wait-for's that one come-back-later code before the switch could replace any number of cases with timing code (the original GSM code had 10 delays).
// add-a-sketch_un-delay 2018 by GoForSmoke @ Arduino.cc Forum
// Free for use, Apr 30/18 by GFS. Compiled on Arduino IDE 1.6.9.
// This sketch shows a general method to get rid of delays in code.
// You could upgrade code with delays to work with add-a-sketch.
#include <avr/io.h>
#include "Arduino.h"
const byte ledPin = 13;
unsigned long delayStart, delayWait;
void setup()
{
Serial.begin( 115200 );
Serial.println( F( "\n\n\n Un-Delay Example, free by GoForSmoke\n" ));
Serial.println( F( "This sketch shows how to get rid of delays in code.\n" ));
pinMode( ledPin, OUTPUT );
};
/* The section of the original sketch with delays:
*
* digitalWrite( ledPin, HIGH ); -- 0
* delay( 500 );
* digitalWrite( ledPin, LOW ); -- 1
* delay( 250 );
* digitalWrite( ledPin, HIGH ); -- 2
* delay( 250 );
* digitalWrite( ledPin, LOW ); -- 3
* delay( 250 );
* digitalWrite( ledPin, HIGH ); -- 4
* delay( 1000 );
* digitalWrite( ledPin, LOW ); -- 5
* delay( 1000 );
*/
byte blinkStep; // state tracking for BlinkPattern() below
void BlinkPattern()
{
// This one-shot timer replaces every delay() removed in one spot.
// start of one-shot timer
if ( delayWait > 0 ) // one-shot timer only runs when set
{
if ( millis() - delayStart < delayWait )
{
return; // instead of blocking, the undelayed function returns
}
else
{
delayWait = 0; // time's up! turn off the timer and run the blinkStep case
}
}
// end of one-shot timer
// here each case has a timed wait but cases could change Step on pin or serial events.
switch( blinkStep ) // runs the case numbered in blinkStep
{
case 0 :
digitalWrite( ledPin, HIGH );
Serial.println( F( "Case 0 doing something unspecified here at " ));
Serial.println( delayStart = millis()); // able to set a var to a value I pass to function
delayWait = 500; // for the next half second, this function will return on entry.
blinkStep = 1; // when the switch-case runs again it will be case 1 that runs
break; // exit switch-case
case 1 :
digitalWrite( ledPin, LOW );
Serial.println( F( "Case 1 doing something unspecified here at " ));
Serial.println( delayStart = millis());
delayWait = 250;
blinkStep = 2;
break;
case 2 :
digitalWrite( ledPin, HIGH );
Serial.println( F( "Case 2 doing something unspecified here at " ));
Serial.println( delayStart = millis());
delayWait = 250;
blinkStep = 3;
break;
case 3 :
digitalWrite( ledPin, LOW );
Serial.println( F( "Case 3 doing something unspecified here at " ));
Serial.println( delayStart = millis());
delayWait = 250;
blinkStep = 4;
break;
case 4 :
digitalWrite( ledPin, HIGH );
Serial.println( F( "Case 4 doing something unspecified here at " ));
Serial.println( delayStart = millis());
delayWait = 1000;
blinkStep = 5;
break;
case 5 :
digitalWrite( ledPin, LOW );
Serial.print( F( "Case 5 doing something unspecified here at " ));
Serial.println( delayStart = millis());
delayWait = 1000;
blinkStep = 0;
break;
}
}
void loop() // runs over and over, see how often
{
BlinkPattern();
}
A full state machine tutorial would show a state machine embedded in a state machine to handle delays indented to the ones you just replaced.