Let's Learn How To Use Finite State Machine With Arduino

You might also like

Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 8

Let's learn how to use finite state machine

with Arduino © Apache-2.0
The finite state machines (FSMs) are significant for understanding the
decision making logic as well as control the digital systems.

 automation
 traffic light
COMPONENTS AND SUPPLIES
LED (generic)
You can use any led you want, preferably of a different color

× 3

Resistor 330 ohm

× 3

SparkFun Pushbutton switch 12mm

× 1

Arduino UNO
Or any other development board you have, it doesn't matter which
one it is
× 1

NECESSARY TOOLS AND MACHINES


Breadboard, 170 Pin

ABOUT THIS PROJECT


As Wikipedia says:
a finite-state machine (FSM) or finite-state automaton (FSA, plural: automata), finite
automaton, or simply a state machine, is a mathematical model of computation. It is an
abstract machine that can be in exactly one of a finite number of states at any given time. The
FSM can change from one state to another in response to some inputs; the change from one
state to another is called a transition.An FSM is defined by a list of its states, its initial state,
and the inputs that trigger each transition.

In other words, a FSM can be the right choice on many occasions with our development
board for a number of very good reasons:

 Finite state machines are flexible


 Easy to move from a significant abstract to a code execution
 Low processor overhead
 Easy determination of reachability of a state
The theory behind it is fantastic, but how does this translate into a working Arduino sketch?
In this little tutorial we'll be using a the YA_FSM Arduino library that does all the dirty work
behind the scenes.
This way we can focus on what's really important with FSM: the model!
Among the many types of graphic modeling, something that closely resembles GRAFCET /
SFC will be used which lends itself very well to describing sequential operations that can be
easily translated into code (it was created precisely for this purpose). Despite to
GRAFCET /SFC rules, this library will allow only one active state at time (at least for now)
and only some action qualifiers are supported: N, S, R, D, L (i would say the most usefuls).

As automation, we will make a small variation on the very classic green / orange / red traffic
light algorithm. We will implement the code for a pedestrian traffic light: normally the green
light is on; when the pedestrian presses the call button he waits, after a short waiting time the
yellow light turns on and finally the red light
This is the graphic representation of this simple automation model:
PedestrainLight SFC model

In order to get familiarity with SFC and library, try to add an additional and helpfully
functionality!
Would be nice for pedestrians having a feedback led that will light up on the call button
pressed in order to identify that input was acquired from the controller.
CODE
PedestrianLight.inoArduino
The sketch is quite simple as you can see, it is all "declarative".
The real job you you have to done carefully is define the automation model on paper, and then easily "translate" to
states, transitions and actions.
#include <YA_FSM.h> // https://github.com/cotestatnt/YA_FSM

const byte BTN_CALL = 2;


const byte GREEN_LED = 12;
const byte YELLOW_LED = 11;
const byte RED_LED = 10;

// Create new FSM


YA_FSM stateMachine;

// State Alias
enum State {RED, GREEN, YELLOW, CALL};

// Helper for print labels instead integer when state change


const char * const stateName[] PROGMEM = { "RED", "GREEN", "YELLOW",
"CALL"};

// Pedestrian traffic light -> green ligth ON until button pressed


#define YELLOW_TIME 2000
#define RED_TIME 10000
#define CALL_DELAY 5000

// Input (trig transition from GREEN to CALL state, the others


transitions on timeout)
bool callButton = false;

// Output variables
bool redLed = false;
bool greenLed = false;
bool yellowLed = false;

/////////// STATE MACHINE CALLBACK FUNCTIONS //////////////////


// Define "on entering" callback function (the same for all "light"
states)
void onEnter() {
Serial.print(stateMachine.ActiveStateName());
Serial.println(F(" light ON"));
}
// Define "on leaving" callback function (the same for all "light"
states)
void onExit() {
Serial.print(stateMachine.ActiveStateName());
Serial.println(F(" light OFF\n"));
}
// Define "on enter" for CALL button state
void onEnterCall() {
Serial.println(F("Call registered, please wait a little time."));
}

// Setup the State Machine


void setupStateMachine() {

// Follow the order of defined enumeration for the state definition


(will be used as index)
// Add States => name,timeout, onEnter cb, onState cb, onLeave cb
stateMachine.AddState(stateName[RED], RED_TIME, onEnter, nullptr,
onExit);
stateMachine.AddState(stateName[GREEN], 0, onEnter, nullptr, onExit);
stateMachine.AddState(stateName[YELLOW], YELLOW_TIME, onEnter,
nullptr, onExit);
stateMachine.AddState(stateName[CALL], CALL_DELAY, onEnterCall,
nullptr, nullptr);

stateMachine.AddAction(RED, YA_FSM::N, redLed); // N -> while


state is active red led is ON
stateMachine.AddAction(GREEN, YA_FSM::S, greenLed); // S -> SET
green led on
stateMachine.AddAction(YELLOW, YA_FSM::R, greenLed); // R -> RESET
the green led
stateMachine.AddAction(YELLOW, YA_FSM::N, yellowLed); // N -> while
state is active yellow led is ON

// Add transitions with related trigger input callback functions


// In this example it's just a simple lambda function that return
state timeout value
stateMachine.AddTransition(RED, GREEN, [](){return
stateMachine.CurrentState()->timeout;} );
stateMachine.AddTransition(YELLOW, RED, [](){return
stateMachine.CurrentState()->timeout;} );
stateMachine.AddTransition(CALL, YELLOW, [](){return
stateMachine.CurrentState()->timeout;});
stateMachine.AddTransition(GREEN, CALL, callButton);
}

void setup() {
// Setup Input/Output
pinMode(BTN_CALL, INPUT_PULLUP);
pinMode(GREEN_LED, OUTPUT);
pinMode(YELLOW_LED, OUTPUT);
pinMode(RED_LED, OUTPUT);

Serial.begin(115200);
while(!Serial) {} // Needed for native USB port only
Serial.println(F("Starting the Finite State Machine...\n"));
setupStateMachine();
}

void loop() {
// Read inputs
callButton = (digitalRead(BTN_CALL) == LOW);

// Update State Machine


if(stateMachine.Update()){
Serial.print(F("Active state: "));
Serial.println(stateMachine.ActiveStateName());
}
// Set outputs
digitalWrite(RED_LED, redLed);
digitalWrite(GREEN_LED, greenLed);
digitalWrite(YELLOW_LED, yellowLed);
}

PedestrianLight
cotestatnt / YA_FSM
19 5
Simple state machine. Implements a "Petri net" (GRAFCET/SFC) inspired state machine with states,
transitions and actions — Read More
Latest commit to the master branch on 7-28-2022
Download as zip
SCHEMATICS
Schematic
DOWNLOAD

You might also like