Built-in project · Arduino Uno R3

Traffic light on an Arduino Uno

An Uno runs a pelican crossing, with a 74HC04 lighting the WAIT lamp straight off the button. The whole build, an Arduino Uno and 12 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.

IntermediateRuns in your browser. Free, and no account needed.

Step by step, with the wiring and the common mistakes: Arduino Traffic Light with a Crossing Button

Traffic light · Arduino Uno R3live0.000 s 0.00x
Hold the button
The circuit itself, running here on the simulator. Press what can be pressed; click anything else to open it in the editor.

The code

The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.

sketch.ino · Arduino Uno R3
// Traffic light: a pelican crossing with a button that actually does
// something.
//
//   pin 8   red      pin 11  walk
//   pin 9   amber    pin 2   request button, to GND, internal pull-up
//   pin 10  green
//
// The button is on INT0, so a press is caught by the interrupt even while
// loop() is asleep inside delay(). Without that the sketch would only notice a
// press if you happened to be holding the button when it got round to looking,
// which is exactly the bug every first crossing sketch has.
//
// Green is the resting state and it waits there for a request, but never for
// less than MIN_GREEN: a crossing that stopped the traffic the instant anyone
// asked would never let a car through.
//
// The WAIT lamp on the breadboard is not driven from here at all. It hangs off
// a 74HC04 inverter wired straight to the button line, so it lights the moment
// the contact closes, a reminder that not everything has to be the
// microcontroller's job.

const int RED = 8;
const int AMBER = 9;
const int GREEN = 10;
const int WALK = 11;
const int BUTTON = 2;

const unsigned long MIN_GREEN = 3000;
const unsigned long MAX_GREEN = 9000;
const unsigned long AMBER_MS = 1500;
const unsigned long WALK_MS = 4000;

volatile bool requested = false;

static void onPress() { requested = true; }

static void lights(int red, int amber, int green) {
  digitalWrite(RED, red ? HIGH : LOW);
  digitalWrite(AMBER, amber ? HIGH : LOW);
  digitalWrite(GREEN, green ? HIGH : LOW);
}

// Hold green until someone asks, or until the maximum runs out.
static void waitForRequest() {
  unsigned long started = millis();
  for (;;) {
    unsigned long waited = millis() - started;
    if (waited >= MAX_GREEN) return;
    noInterrupts();
    bool asked = requested;
    interrupts();
    if (asked && waited >= MIN_GREEN) return;
    delay(20);
  }
}

void setup() {
  pinMode(RED, OUTPUT);
  pinMode(AMBER, OUTPUT);
  pinMode(GREEN, OUTPUT);
  pinMode(WALK, OUTPUT);
  pinMode(BUTTON, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(BUTTON), onPress, FALLING);
  Serial.begin(115200);
  Serial.println("Mokxi Arduino Uno: crossing ready, press the button");
}

void loop() {
  lights(0, 0, 1);
  Serial.println("green");
  waitForRequest();

  lights(0, 1, 0);
  Serial.println("amber");
  delay(AMBER_MS);

  lights(1, 0, 0);
  digitalWrite(WALK, HIGH);
  Serial.println("walk");
  delay(WALK_MS);

  // the flashing period at the end of the walk phase
  // The pelican's own ending: the walk lamp flashes to say "finish crossing"
  // while the drivers get a flashing amber, which means "go if the crossing
  // is clear". Then straight back to green. (A red-and-amber pair before
  // green is the junction signal's sequence, not a crossing's.)
  Serial.println("flashing amber");
  for (int i = 0; i < 12; i++) {
    int on = (i & 1) ? LOW : HIGH;
    digitalWrite(WALK, on);
    lights(0, on == HIGH, 0);
    delay(500);
  }
  digitalWrite(WALK, LOW);
  noInterrupts();
  requested = false;
  interrupts();
}

Parts list

14 parts, plus the jumper wires. Every one is in the editor's parts bin.

How it is wired

13 connections, pin by pin, read from the circuit itself. Each line is one set of pins joined together, by a jumper wire or a breadboard strip.

  • Ground: Arduino Uno R3 pin GND; 74HC04 hex inverter pin GND; Pushbutton pin 2a; LED, red pin C; LED, yellow pin C; LED, green pin C; LED, white pin C; LED, blue pin C
  • Arduino Uno R3 pin 11; Resistor, 220 Ω (4) pin 1
  • Arduino Uno R3 pin 10; Resistor, 220 Ω (3) pin 1
  • Arduino Uno R3 pin 9; Resistor, 220 Ω (2) pin 1
  • Arduino Uno R3 pin 8; Resistor, 220 Ω (1) pin 1
  • Arduino Uno R3 pin 2; 74HC04 hex inverter pin 1A; Pushbutton pin 1a
  • Arduino Uno R3 pin 5V; 74HC04 hex inverter pin VCC
  • 74HC04 hex inverter pin 1Y; Resistor, 220 Ω (5) pin 1
  • Resistor, 220 Ω (1) pin 2; LED, red pin A
  • Resistor, 220 Ω (2) pin 2; LED, yellow pin A
  • Resistor, 220 Ω (3) pin 2; LED, green pin A
  • Resistor, 220 Ω (4) pin 2; LED, white pin A
  • Resistor, 220 Ω (5) pin 2; LED, blue pin A

Change it and keep it

Open it in the editor, change the circuit or the code, and keep your version in a free account.