ESP32 Traffic Light: Three LEDs and a Sequence of States
A classic learning project: red, yellow and green LEDs with resistors and a traffic-light cycle with a blinking green. We learn to move repeated code into a function and plan a sequence of states.
About the project
A traffic light is the perfect exercise in driving several outputs at once: three LEDs, a clear sequence of states and timings. Along the way we learn not to repeat three digitalWrite() calls on every line.
What you need
- ESP32 DevKit
- LEDs: red, yellow, green
- 3 × 220 Ω resistors
- Breadboard and jumper wires
Wiring
| Colour | GPIO | Circuit |
|---|---|---|
| Red | GPIO25 | GPIO → 220 Ω → anode; cathode → GND |
| Yellow | GPIO26 | same |
| Green | GPIO27 | same |
Every LED gets its own resistor. One shared resistor on all the cathodes is a bad idea: the brightness would depend on how many LEDs are on, and the red one (lower voltage) would hog the current.
The sequence
The cycle, as on Ukrainian traffic lights:
| Step | Red | Yellow | Green | Duration |
|---|---|---|---|---|
| Stop | ● | 3 s | ||
| Get ready | ● | ● | 1 s | |
| Go | ● | 3 s | ||
| Green blinks | ◐ ×3 | ~2 s | ||
| Caution | ● | 1 s |
Each state is three on/off values, so one function set(r, y, g) sets them all.
Code
// Traffic light: red, yellow, green on GPIO25, 26, 27
const int RED = 25, YELLOW = 26, GREEN = 27;
// one traffic-light state — one function instead of three digitalWrite calls
void set(bool r, bool y, bool g) {
digitalWrite(RED, r);
digitalWrite(YELLOW, y);
digitalWrite(GREEN, g);
}
void setup() {
pinMode(RED, OUTPUT);
pinMode(YELLOW, OUTPUT);
pinMode(GREEN, OUTPUT);
}
void loop() {
set(1, 0, 0); delay(3000); // stop
set(1, 1, 0); delay(1000); // get ready
set(0, 0, 1); delay(3000); // go
for (int i = 0; i < 3; i++) { set(0, 0, 0); delay(300); set(0, 0, 1); delay(300); } // green blinks
set(0, 1, 0); delay(1000); // caution
}
Taking it further
- Pedestrian button. Right now
delay()blocks everything, so a button would not respond mid-cycle. Rewrite the light as a state machine: astatevariable and the time you entered it,stateSince = millis(). Inloop(), check whether it is time to move on, and poll the button at the same time. - Night mode. Blink yellow when a photoresistor sees darkness.
- Crossroads. A second set of LEDs runs in opposite phase to the first.
Good to know
GPIO25–27 are convenient outputs: they take no part in booting and are not used by the flash. For outputs avoid GPIO6–11 (flash) and GPIO34–39 (input-only).