Arduino Tutorial: How to make a state machine

How to use a state machine in Arduino

State Machine background

State Machine Example

 

/*
A traffic light for an intersection of a
highway and a country road. Normally, the light
should be green for the highway and red for the
country road, but when traffic approaches on
the country road, the highway gets a red light
and the country road gets a green light.
 
When a light turns red it transitions from green to
red it goes through yellow, but a red light changing
to green transitions directly to green.
 
A pushbutton represents a car approaching on
the country road.
 
Implement the solution with a Finite State
Machine or FSM.
 
Following the excellent description at
http://hacking.majenko.co.uk/finite-state-machine
first break down the problem into states.
 
Identify which states are Transitional (T) and
which are Static (S). A Static state is one in
which the FSM is waiting for stimulus, and is
taking no actions. A Transitional State is a
state which causes actions, but doesn't look
for stimulus.
 
A Transitional State runs once and immediately
moves on to a Static State.
 
State 0: highway = green, country = red; (T)
State 1: wait for car on country road (S)
State 2: highway = yellow, make note of current time (T)
State 3: wait for yellow time to pass (S)
State 4: highway = red, country =  green, make note of current time (T)
State 5: wait for highway red time to pass (S)
State 6: country = yellow, make note of current time (T)
state 7: wait for yellow time to pass (S) then go to 0
*/
 
// Use names for states so it's easier to
// understand what the code is doing
const int S_HIGHWAYGREEN = 0;
const int S_WAITCARCOUNTRY = 1;
const int S_HIGHWAYYELLOW = 2;
const int S_WAITHIGHWAYYELLOW = 3;
const int S_HIGHWAYRED = 4;
const int S_WAITHIGHWAYRED = 5;
const int S_COUNTRYYELLOW = 6;
const int S_WAITCOUNTRYYELLOW = 7;
 
// Pin numbers
const int countrySensorPin = 2;
 
const int highwayGreenLEDPin = 3;
const int highwayYellowLEDPin = 4;
const int highwayRedLEDPin = 5;
 
const int countryGreenLEDPin = 6;
const int countryYellowLEDPin = 7;
const int countryRedLEDPin = 8;
 
void setup()
{
  pinMode(highwayGreenLEDPin, OUTPUT);
  pinMode(highwayYellowLEDPin, OUTPUT);
  pinMode(highwayRedLEDPin, OUTPUT);
  pinMode(countryGreenLEDPin, OUTPUT);
  pinMode(countryYellowLEDPin, OUTPUT);
  pinMode(countryRedLEDPin, OUTPUT);
}
 
void loop()
{
 
  // start off with the highway getting green
  // The keyword "static" makes sure the variable
  // isn't destroyed after each loop
  static int state = S_HIGHWAYGREEN ;
 
  // To store the current time  for delays
  static unsigned long ts;
 
  switch (state)
  {
    case S_HIGHWAYGREEN:
      // Highway gets green, country road red
      digitalWrite( highwayGreenLEDPin, HIGH);
      digitalWrite( highwayYellowLEDPin, LOW);
      digitalWrite( highwayRedLEDPin, LOW);
 
      digitalWrite( countryGreenLEDPin, LOW);
      digitalWrite( countryYellowLEDPin, LOW);
      digitalWrite( countryRedLEDPin, HIGH);
 
      state = S_WAITCARCOUNTRY;
 
      break;
 
    case S_WAITCARCOUNTRY:
 
      if ( digitalRead (countrySensorPin) == HIGH) {
        state = S_HIGHWAYYELLOW;
      }
 
      break;
 
    case S_HIGHWAYYELLOW:
      digitalWrite( highwayGreenLEDPin, LOW);
      digitalWrite( highwayYellowLEDPin, HIGH);
      digitalWrite( highwayRedLEDPin, LOW);
 
      digitalWrite( countryGreenLEDPin, LOW);
      digitalWrite( countryYellowLEDPin, LOW);
      digitalWrite( countryRedLEDPin, HIGH);
 
      ts = millis();  // Remember the current time
 
      state = S_WAITHIGHWAYYELLOW;  // Move to the next state
 
      break;
 
    case S_WAITHIGHWAYYELLOW:
      // If two seconds have passed, then move on to the next state.
      if (millis() > ts + 2000)
      {
        state = S_HIGHWAYRED;
      }
 
      break;
 
    case S_HIGHWAYRED:
      // Highway red, country road green
      digitalWrite( highwayGreenLEDPin, LOW);
      digitalWrite( highwayYellowLEDPin, LOW);
      digitalWrite( highwayRedLEDPin, HIGH);
 
      digitalWrite( countryGreenLEDPin, HIGH);
      digitalWrite( countryYellowLEDPin, LOW);
      digitalWrite( countryRedLEDPin, LOW);
 
      ts = millis();  // Remember the current time
 
      state = S_WAITHIGHWAYRED;
 
      break;
 
    case S_WAITHIGHWAYRED:
 
      // If five seconds have passed, then start
      // transition to a red light for the country 
      // road
      if (millis() > ts + 5000)
      {
        state = S_COUNTRYYELLOW;
      }
 
      break;
 
    case S_COUNTRYYELLOW:
      digitalWrite( highwayGreenLEDPin, LOW);
      digitalWrite( highwayYellowLEDPin, LOW);
      digitalWrite( highwayRedLEDPin, HIGH);
 
      digitalWrite( countryGreenLEDPin, LOW);
      digitalWrite( countryYellowLEDPin, HIGH);
      digitalWrite( countryRedLEDPin, LOW);
 
      ts = millis();  // Remember the current time
 
      state = S_WAITCOUNTRYYELLOW;
 
      break;
 
    case S_WAITCOUNTRYYELLOW:
 
      // If two seconds have passed, then go
      // back to the beginning with the highway 
      // getting the green light
      if (millis() > ts + 2000)
      {
        state = S_HIGHWAYGREEN;
      }
 
      break;
 
  } // end of switch
 
  // other things could go on here, and they would not affect the timing 
  // of the traffic light
 
} // end of loop
Print Friendly
Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.

One thought on “Arduino Tutorial: How to make a state machine

  1. Hi – this is the one of code I really love. What is the reason for my love. It’s simple. No library, no hidden tricks – but only the explanation and coding of a really hot piece of software. Why can I tell such words. Because I studied in the 80ties microelctronics and robotic. Yes it’s really a long time ago. But the underlying theoretical basics like bool, Karnaugh and logic junctions are never out of date. Thank you for your publishing. I wished, I had such a good example and teacher in the time I’ve studied and not understood a lot of things – you have managed it. Wow, my old brain and now this……… Have a good time and I hope, many readers will recognize that ‘golden’ code.

Leave a Reply

Your email address will not be published. Required fields are marked *