/* a modified copy of https://wokwi.com/projects/383746814655260673
from https://forum.arduino.cc/t/yet-another-finite-state-machine-introduction/1198997 by @J-M-L
*/
// Button management library
#include <Toggle.h> // https://github.com/Dlloydev/Toggle
const byte buttonPin = 4; // Our button is on pin 4
const byte redButtonPin = 5; // Red button is on pin 5
const byte switchLeftPin = 7;
const byte potPin = A0; // Potentiometer is on pin A0
Toggle button;
Toggle redButton;
Toggle switchLeft;
// Pins used for LEDs
const byte pinRedLed = 8;
const byte pinOrangeLed = 9;
const byte pinYellowLed = 10;
const byte pinGreenLed = 11;
// Introducing time as an additional event
unsigned long chrono; // Note: unsigned long, like millis()
const unsigned long TimeOut = 15000ul; // 15 seconds (ul at the end for unsigned long, a good habit to adopt)
// The list of possible states of our system
// along with a currentState variable taking one of these values
enum {REST, STATE_G, STATE_GY, STATE_GYO, STATE_GYOR} currentState;
void turnLedsOff() {
digitalWrite(pinGreenLed, LOW);
digitalWrite(pinYellowLed, LOW);
digitalWrite(pinOrangeLed, LOW);
digitalWrite(pinRedLed, LOW);
}
void runStateMachine() {
// TEST FOR CLICK
switch (currentState) {
case REST: // we are at rest and if we get a click, turn on the green LED
if (button.onPress()) { // this is our event detection
digitalWrite(pinGreenLed, HIGH); // execute the associated action. Green LED powered
chrono = millis(); // We just had an action, so we reset our stopwatch
currentState = STATE_G; // note the new state of our system
}
if( redButton.onPress()) {
Serial.print(millis());
digitalWrite(pinGreenLed, HIGH);
digitalWrite(pinYellowLed, HIGH);
digitalWrite(pinOrangeLed, HIGH);
digitalWrite(pinRedLed, HIGH);
chrono = millis();
currentState = STATE_GYOR;
}
break;
case STATE_G: // green LED was on and if we get a click, turn on the yellow LED
if (button.onPress()) { // this is our event detection
digitalWrite(pinYellowLed, HIGH); // execute the associated action. Yellow LED powered
chrono = millis(); // We just had an action, so we reset our stopwatch
currentState = STATE_GY; // note the new state of our system
}
break;
case STATE_GY: // green and yellow were on, if we get a click, turn on the orange LED
if (button.onPress()) { // this is our event detection
digitalWrite(pinOrangeLed, HIGH); // execute the associated action. Orange LED powered
chrono = millis(); // We just had an action, so we reset our stopwatch
currentState = STATE_GYO; // note the new state of our system
}
break;
case STATE_GYO: // green, orange, and yellow were on, if we get a click, turn on the red LED
if (button.onPress()) { // this is our event detection
digitalWrite(pinRedLed, HIGH); // execute the associated action. Red LED powered
chrono = millis(); // We just had an action, so we reset our stopwatch
currentState = STATE_GYOR; // note the new state of our system
}
break;
case STATE_GYOR: // everything was on, if we get a click a click, return to rest
if (button.onPress()) { // this is our event detection
turnLedsOff(); // execute the associated action. return to the initial state
chrono = millis(); // We just had an action, so we reset our stopwatch
currentState = REST;
}
break;
}
// TEST FOR TIMEOUT
if ((currentState != REST) && (millis() - chrono >= TimeOut)) { // timeout event
turnLedsOff();
currentState = REST;
}
}
// ------------------------------------------------------
// We initialize our system in the setup
// ------------------------------------------------------
void setup() {
// configure
pinMode(pinRedLed, OUTPUT);
pinMode(pinOrangeLed, OUTPUT);
pinMode(pinYellowLed, OUTPUT);
pinMode(pinGreenLed, OUTPUT);
button.begin(buttonPin);
button.begin(redButtonPin);
button.begin(switchLeftPin);
Serial.begin(115200);
// define Initial conditions
turnLedsOff();
currentState = REST;
Serial.print(
F("Expanded FSM Tutorial. See https://wokwi.com/projects/383746814655260673\n"
"and https://forum.arduino.cc/t/yet-another-finite-state-machine-introduction/1198997\n"
"for more material.\n"
"Adjust the inputs to move the FSM.\n"
)
);
}
int potVal = 0, lastPotVal = 0, potDiff = 0;
void loop() {
// Inputs
button.poll(); // update the state of the button
redButton.poll(); // update the state of the button
switchLeft.poll(); // update the state of the switch
potVal = analogRead(potPin);
// preprocessing for some derived inputs
potDiff = potVal - lastPotVal;
if (potDiff != 0) {
lastPotVal = potVal;
}
// Processing
// we update ou system based on possible events
runStateMachine();
// Outputs
report();
// Here, we can do other things as long as it doesn't take too long and is non blocking
}
void report(){}