Menu
CoddyTech

Traffic Light State Machine

Part of the Timing Without Delay section of Coddy's Arduino journey. Lesson 10 of 18.

A traffic light is a state machine: it is always in one state (green, yellow or red), each state lasts a set time, and each state knows which one comes next:

  • GREEN: green on; after 2 s, go to YELLOW
  • YELLOW: yellow on; after 1 s, go to RED
  • RED: red on; after 2 s, go to GREEN

Each line becomes one case:

case GREEN:
  setLights(HIGH, LOW, LOW);
  if (now - lightStart >= 2000) {
    light = YELLOW;
    lightStart = now;
  }
  break;

With delay(2000) the light would work too, but nothing else could run. With millis(), each pass through loop() takes microseconds, so the board has time for other jobs: here, a status LED that blinks the whole time to show the controller is alive.

challenge icon

Challenge

Medium

The status LED on pin 13 already blinks, and the enum and lightStart are ready. Write the traffic light as a switch (light) with one case per light:

  • green 2 s, yellow 1 s, red 2 s, then green again
  • one LED at a time, with setLights()
  • no delay(), so the status LED keeps blinking

Press Run, then Check.

Try it yourself

const int greenLed = 10;
const int yellowLed = 11;
const int redLed = 12;
const int statusLed = 13;   // the board's own LED

enum Light { GREEN, YELLOW, RED };
Light light = GREEN;
unsigned long lightStart = 0;   // when the current light came on

unsigned long statusPrevious = 0;
int statusState = LOW;

void setup() {
  pinMode(greenLed, OUTPUT);
  pinMode(yellowLed, OUTPUT);
  pinMode(redLed, OUTPUT);
  pinMode(statusLed, OUTPUT);
}

void setLights(int green, int yellow, int red) {
  digitalWrite(greenLed, green);
  digitalWrite(yellowLed, yellow);
  digitalWrite(redLed, red);
}

void loop() {
  unsigned long now = millis();

  // the status LED switches every 250 ms, to show the controller is alive
  if (now - statusPrevious >= 250) {
    statusPrevious = now;
    if (statusState == LOW) {
      statusState = HIGH;
    } else {
      statusState = LOW;
    }
    digitalWrite(statusLed, statusState);
  }

  // the traffic light: a switch (light) with one case per light
  // green 2 s, yellow 1 s, red 2 s, then green again
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Timing Without Delay

Practice on your own: Arduino playground