Build a traffic light with a pedestrian button

A working road crossing: car lights, a walk light and a button. Press it, and the lights change in the right order, with ticking for blind pedestrians.
  • Level:Beginner
  • Duration: 45 min
  • Ages 10+
  • Platform: Arduino

Tools for this lesson

Helpful for this build. Open a tool to see tips and more projects that use it.

Build a traffic light with a pedestrian button – EEMENTOR STEM™ lesson

Every road crossing is a small computer program. It keeps the cars moving until someone presses the button, then switches the car lights through yellow to red, gives the pedestrians green, warns them before it ends and lets the cars go again. In this lesson you build the whole sequence with five LEDs, a push button and a buzzer, and you learn to write it as a state machine, the way real traffic controllers are programmed.

What you'll learn

  • How to plan a program as a list of states
  • How to time each state with millis() instead of delay()
  • How to remember a button press until the program is ready for it
  • How to make blinking and ticking without stopping the program

What you need

  • UNO R3 board and USB cable (UNO R3 Starter Kit)
  • Red, yellow and green LEDs for the cars, and a red and a green LED for the pedestrians (UNO R3 Starter Kit)
  • 5 resistors, 220 Ω (UNO R3 Starter Kit)
  • 1 push button (UNO R3 Starter Kit)
  • Active buzzer (UNO R3 Starter Kit)
  • Breadboard and jumper wires (UNO R3 Starter Kit)

Make it real: stand the car lights in a column on the breadboard, and draw a small road crossing on paper to put in front of it.

Wiring

Breadboard wiring diagram: Build a traffic light with a pedestrian button
Breadboard view. Check each connection against the wiring table below.
From To
UNO pin 4 220 Ω resistor, then the car red LED's long leg
UNO pin 3 220 Ω resistor, then the car yellow LED's long leg
UNO pin 2 220 Ω resistor, then the car green LED's long leg
UNO pin 6 220 Ω resistor, then the walk red LED's long leg
UNO pin 5 220 Ω resistor, then the walk green LED's long leg
All LED short legs GND
Push button, one leg UNO pin 7
Push button, the diagonally opposite leg GND
Active buzzer + UNO pin 8
Active buzzer − GND

The five states

State Cars Pedestrians Ends when
Cars go Green Red Button pressed, after at least 5 s of green
Cars slow down Yellow Red After 2 s
Walk Red Green, slow ticking After 6 s
Walk ends Red Green flashing, fast ticking After 3 s
Cars get ready Red and yellow Red After 1.5 s

The sketch

const int CAR_RED = 4;
const int CAR_YELLOW = 3;
const int CAR_GREEN = 2;
const int WALK_RED = 6;
const int WALK_GREEN = 5;
const int BUTTON_PIN = 7;
const int BUZZER_PIN = 8;

const byte CARS_GO = 0, CARS_SLOW = 1, WALK = 2, WALK_ENDS = 3, CARS_READY = 4;
byte state = CARS_GO;
unsigned long stateStart = 0;
bool requested = false;            // someone pressed the button

void enter(byte newState) {
  state = newState;
  stateStart = millis();
}

void lights(bool carRed, bool carYellow, bool carGreen, bool walkRed, bool walkGreen) {
  digitalWrite(CAR_RED, carRed);
  digitalWrite(CAR_YELLOW, carYellow);
  digitalWrite(CAR_GREEN, carGreen);
  digitalWrite(WALK_RED, walkRed);
  digitalWrite(WALK_GREEN, walkGreen);
}

void setup() {
  for (int pin = 2; pin <= 6; pin++) pinMode(pin, OUTPUT);
  pinMode(BUZZER_PIN, OUTPUT);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
}

void loop() {
  unsigned long now = millis();
  unsigned long inState = now - stateStart;

  if (digitalRead(BUTTON_PIN) == LOW && state == CARS_GO) requested = true;

  switch (state) {
    case CARS_GO:
      lights(false, false, true, true, false);
      digitalWrite(BUZZER_PIN, LOW);
      if (requested && inState >= 5000) {      // cars always get 5 s of green
        requested = false;
        enter(CARS_SLOW);
      }
      break;

    case CARS_SLOW:
      lights(false, true, false, true, false);
      if (inState >= 2000) enter(WALK);
      break;

    case WALK:
      lights(true, false, false, false, true);
      digitalWrite(BUZZER_PIN, now % 600 < 40);           // slow tick
      if (inState >= 6000) enter(WALK_ENDS);
      break;

    case WALK_ENDS:
      lights(true, false, false, false, (now / 250) % 2);  // flashing green
      digitalWrite(BUZZER_PIN, now % 200 < 30);           // fast tick
      if (inState >= 3000) enter(CARS_READY);
      break;

    case CARS_READY:
      lights(true, true, false, true, false);
      digitalWrite(BUZZER_PIN, LOW);
      if (inState >= 1500) enter(CARS_GO);
      break;
  }
}

How it works

The variable state says which of the five steps the crossing is in, and switch runs only the code for that step. Each step sets its lights and checks one thing: has enough time passed, or has someone pressed the button? enter() moves to the next step and notes the time, so inState always says how long the current step has lasted.

Because nothing in loop() waits, the button is checked thousands of times per second. A press is stored in requested and handled only when the cars have had at least 5 seconds of green, just like a real crossing. The ticking comes from the clock: now % 600 < 40 is true for 40 ms out of every 600, which makes a short click. Many real crossings tick like this so that blind pedestrians know when to cross. The red-and-yellow step before green is how traffic lights work in many European countries; leave it out if yours go straight from red to green.

Try this next

  • Light a small "Wait" LED as soon as the button has been pressed.
  • Count the pedestrians who pressed the button and print the number in the Serial Monitor.
  • At night (ask a photoresistor), let the car lights flash yellow and skip the pedestrian cycle.

Troubleshooting

  • One LED never lights: check that its long leg goes to the resistor and its short leg to GND.
  • The button does nothing: the two legs you use may always be connected. Turn the button a quarter turn.
  • The buzzer clicks all the time: it must be the active buzzer, with its + leg on pin 8.

Build it yourself

Everything used in this lesson comes in one kit, with parts tested by our engineers.

UNO R3 Starter Kit | Arduino IDE Compatible | Free Tutorials $56.00

Shop the kit