A finite-state machine (FSM) is a mathematical model of computation. It is an abstract machine that can only be one state, out of a limited number of states at any given time. The FSM can change state in response to an input or event. An FSM is defined by a list of its states, its initial state, and the inputs that trigger each transition. FSM are useful for a number of situations to code interactive behaviour.
This simple FSM below describes the behaviour of a robot that attempts to avoid obstacles based on a distance sensor pointing forward. Whenever the distance sensor measures an obstacle less than 100 millimetres in front, it will reverse and then try to steer to the left. Similar algorithms allow vacuum-cleaning robots to navigate around complex spaces.
A change from one state to another is called a transition. In the example state diagram above, these transitions are sometimes triggered by timing events and sometimes by external inputs.
The example below demonstrates the same simple FSM using the switch statement, and one variable to store the state.
const byte START = 0; const byte FORWARD = 1; const byte LEFT = 2; const byte REVERSE = 3; byte myState; void setup() { Serial.begin(9600); myState = START; // Initial State } void loop() { switch (myState) { case START: Serial.println("Enter START state"); delay(10); myState = FORWARD; break; case FORWARD: Serial.println("Enter FORWARD state"); Serial.println("Move Forward"); // action if (analogRead(A0)<100) { myState = REVERSE; } delay(500); break; case REVERSE: Serial.println("Enter REVERSE state"); Serial.println("Move Backward"); // action myState = LEFT; delay(500); break; case LEFT: Serial.println("Enter LEFT state"); Serial.println("Move Left"); // action delay(500); myState = FORWARD; break; } }
If you use an FSM library for Arduino, you can use some more advanced features such as enter, exit and transition functions that might be useful for organising your code and for solving some more specific challenges. For example, you can use the enter function to record a timestamp, then use the exit function to print out over serial how long the Arduino was in a given state based on the timestamp. You can also code behaviour for entering and exiting a given state.
It’s also common to see an enumeration declaration used to keep track of states.
enum machineStates { START, // blink disable FORWARD, // blink enable LEFT, // we want the led to be on for interval REVERSE // we want the led to be off for interval }; enum machineStates myState;