ESP32 UNO - Traffic Light

Want to build a working traffic signal with the ESP32 Uno? Connect a traffic light module to the ESP32 Uno form board and make the red, yellow and green LEDs run a repeating cycle with a few lines of Arduino code. Later you will also make the cycle non-blocking.

By the end, you can:

  1. Wire a traffic light module to three Uno header pins
  2. Switch each LED with pinMode() and digitalWrite()
  3. Tidy the sketch using a function and a for loop
  4. Switch lights with millis() and no blocking delay()
ESP32 Uno traffic light

Hardware Preparation

1×ESP32 Uno-form Board
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×Traffic Light Module
1×Jumper Wires

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

Overview of Traffic Light Module

By the end of this part, you know what each pin of the module does.

The module is a small board with one red, one yellow and one green LED. Each LED already has a resistor on the board, so you can connect it straight to a GPIO pin.

Pinout

Module Pin Role
GND Ground, goes to a GND pin of the board
R Red LED control, goes to a digital output
Y Yellow LED control, goes to a digital output
G Green LED control, goes to a digital output
Traffic Light Pinout

How It Works

Drive a color pin HIGH and its LED lights up. Drive it LOW and the LED goes dark. A traffic signal is only a timed sequence of these states, so one pin is HIGH while the other two are LOW.

Good to know: ESP32 Uno pins output 3.3V. That is enough for these LEDs, which may look slightly dimmer than on a 5V board.

ESP32 Uno Pinout

Each Uno header pin on the ESP32 Uno form board maps to one GPIO number, and your code uses that GPIO number. Look at the diagram first, then match D2, D3 and D4 to their GPIOs before you connect any wire.

ESP32 Uno pinout diagram

Wiring Diagram

By the end of this part, the three color pins and ground are connected.

The wiring diagram between ESP32 Uno traffic light

This image is created using Fritzing. Click to enlarge image

Module Pin ESP32 Uno Pin
R D2 (GPIO26)
Y D3 (GPIO25)
G D4 (GPIO17)
GND GND

Good to know: None of these three pins is a boot strapping pin, so the board starts and uploads normally with the module connected.

How To Program For Traffic Light Module

By the end of this part, you know the two functions that do all the work.

Step 1 — Set the pins as outputs

Call pinMode() once for each color pin inside setup().

pinMode(PIN_RED, OUTPUT); pinMode(PIN_YELLOW, OUTPUT); pinMode(PIN_GREEN, OUTPUT);

Step 2 — Light one color

Call digitalWrite() to turn red on and the other two off, then hold that state with delay().

digitalWrite(PIN_RED, HIGH); // red on digitalWrite(PIN_YELLOW, LOW); // yellow off digitalWrite(PIN_GREEN, LOW); // green off delay(RED_TIME); // keep this state for RED_TIME ms

ESP32 Uno Code

This sketch shows red, yellow and green for 4 seconds each, in a loop. It uses GPIO26 for red, GPIO25 for yellow and GPIO17 for green.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-traffic-light */ #define PIN_RED 26 // D2 (GPIO26) goes to the R pin of the traffic light module #define PIN_YELLOW 25 // D3 (GPIO25) goes to the Y pin of the traffic light module #define PIN_GREEN 17 // D4 (GPIO17) goes to the G pin of the traffic light module #define RED_TIME 4000 // how long red stays lit, in ms #define YELLOW_TIME 4000 // how long yellow stays lit, in ms #define GREEN_TIME 4000 // how long green stays lit, in ms void setup() { // all three light pins are outputs pinMode(PIN_RED, OUTPUT); pinMode(PIN_YELLOW, OUTPUT); pinMode(PIN_GREEN, OUTPUT); } // loop() repeats the red, yellow, green cycle forever void loop() { // step 1: red only digitalWrite(PIN_RED, HIGH); // red on digitalWrite(PIN_YELLOW, LOW); // yellow off digitalWrite(PIN_GREEN, LOW); // green off delay(RED_TIME); // wait while red is shown // step 2: yellow only digitalWrite(PIN_RED, LOW); // red off digitalWrite(PIN_YELLOW, HIGH); // yellow on digitalWrite(PIN_GREEN, LOW); // green off delay(YELLOW_TIME); // wait while yellow is shown // step 3: green only digitalWrite(PIN_RED, LOW); // red off digitalWrite(PIN_YELLOW, LOW); // yellow off digitalWrite(PIN_GREEN, HIGH); // green on delay(GREEN_TIME); // wait while green is shown }
Code Part What It Does
#define PIN_RED / PIN_YELLOW / PIN_GREEN Store the GPIO numbers 26, 25 and 17
#define RED_TIME / YELLOW_TIME / GREEN_TIME Set how long each color stays on, in ms
setup() Puts the three pins in output mode
loop() Lights one color, waits, then moves to the next

The result is a red, yellow, green cycle that never stops.

Upload and Test

  1. First time with this board? Set it up with ESP32 Uno - Getting Started before you continue.
  2. Build the circuit by following the wiring table above.
  3. Plug in the USB Type-C cable between the ESP32 Uno and your computer.
  4. Select the board in Arduino IDE: pick ESP32 Dev Module and the COM port of the board (CH340).
  5. Copy the code above into Arduino IDE.
  6. Press Upload to flash the sketch.
  7. Watch the module. The order is red, yellow, green, then red again.
  8. Pro tip: Set YELLOW_TIME to 1000 and RED_TIME to 6000 to get a more realistic crossing timing.

Real signals differ from country to country. This sketch only shows the basic idea.

Video Tutorial

See the ESP32 Uno build in action in the video below.

Code Optimization

By the end of this part, the sketch is shorter and does not block.

Version 1 — Use a function

A function trafic_light_on() turns one light on and the other two off. Arrays hold the pins and the times, so loop() needs one line per color.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-traffic-light */ #define PIN_RED 26 // D2 (GPIO26) goes to the R pin of the module #define PIN_YELLOW 25 // D3 (GPIO25) goes to the Y pin of the module #define PIN_GREEN 17 // D4 (GPIO17) goes to the G pin of the module #define RED_TIME 2000 // red duration in ms #define YELLOW_TIME 1000 // yellow duration in ms #define GREEN_TIME 2000 // green duration in ms #define RED 0 // array index of red #define YELLOW 1 // array index of yellow #define GREEN 2 // array index of green const int pins[] = { PIN_RED, PIN_YELLOW, PIN_GREEN }; const int times[] = { RED_TIME, YELLOW_TIME, GREEN_TIME }; void setup() { // light pins work as outputs pinMode(PIN_RED, OUTPUT); pinMode(PIN_YELLOW, OUTPUT); pinMode(PIN_GREEN, OUTPUT); } // loop() shows each light in turn, again and again void loop() { // show red trafic_light_on(RED); delay(times[RED]); // hold red for its time // show yellow trafic_light_on(YELLOW); delay(times[YELLOW]); // hold yellow for its time // show green trafic_light_on(GREEN); delay(times[GREEN]); // hold green for its time } // turns on one light and turns the other two off void trafic_light_on(int light) { for (int i = RED; i <= GREEN; i++) { if (i == light) digitalWrite(pins[i], HIGH); // selected light on else digitalWrite(pins[i], LOW); // other lights off } }

Version 2 — Use a for loop

The arrays let a for loop visit red, yellow and green in order. loop() shrinks to a few lines.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-traffic-light */ #define PIN_RED 26 // D2 (GPIO26) goes to the R pin of the module #define PIN_YELLOW 25 // D3 (GPIO25) goes to the Y pin of the module #define PIN_GREEN 17 // D4 (GPIO17) goes to the G pin of the module #define RED_TIME 2000 // red duration in ms #define YELLOW_TIME 1000 // yellow duration in ms #define GREEN_TIME 2000 // green duration in ms #define RED 0 // array index of red #define YELLOW 1 // array index of yellow #define GREEN 2 // array index of green const int pins[] = {PIN_RED, PIN_YELLOW, PIN_GREEN}; const int times[] = {RED_TIME, YELLOW_TIME, GREEN_TIME}; void setup() { // light pins work as outputs pinMode(PIN_RED, OUTPUT); pinMode(PIN_YELLOW, OUTPUT); pinMode(PIN_GREEN, OUTPUT); } // loop() walks through the three lights with a for loop void loop() { for (int light = RED; light <= GREEN; light ++) { trafic_light_on(light); delay(times[light]); // hold this light for its own time } } // turns on one light and turns the other two off void trafic_light_on(int light) { for (int i = RED; i <= GREEN; i ++) { if (i == light) digitalWrite(pins[i], HIGH); // selected light on else digitalWrite(pins[i], LOW); // other lights off } }

Version 3 — Use millis() instead of delay()

delay() freezes the sketch. This version compares millis() with the last change time and switches the light only when the time is up, so other code can run in between.

/* * This ESP32 Uno code was developed by newbiely.com * * This ESP32 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-uno/esp32-uno-traffic-light */ #define PIN_RED 26 // D2 (GPIO26) goes to the R pin of the module #define PIN_YELLOW 25 // D3 (GPIO25) goes to the Y pin of the module #define PIN_GREEN 17 // D4 (GPIO17) goes to the G pin of the module #define RED_TIME 2000 // red duration in ms #define YELLOW_TIME 1000 // yellow duration in ms #define GREEN_TIME 2000 // green duration in ms #define RED 0 // array index of red #define YELLOW 1 // array index of yellow #define GREEN 2 // array index of green const int pins[] = { PIN_RED, PIN_YELLOW, PIN_GREEN }; const int times[] = { RED_TIME, YELLOW_TIME, GREEN_TIME }; unsigned long last_time = 0; // moment of the last light change int light = RED; // the light that is on now, starts with red void setup() { // light pins work as outputs pinMode(PIN_RED, OUTPUT); pinMode(PIN_YELLOW, OUTPUT); pinMode(PIN_GREEN, OUTPUT); trafic_light_on(light); // show red at power-up last_time = millis(); // remember when red started } // loop() never blocks, it only checks the clock void loop() { if ((millis() - last_time) > times[light]) { light++; if (light >= 3) light = RED; // go back to red after green trafic_light_on(light); last_time = millis(); // restart the timer } // TO DO: put your other non-blocking code here } // turns on one light and turns the other two off void trafic_light_on(int light) { for (int i = RED; i <= GREEN; i++) { if (i == light) digitalWrite(pins[i], HIGH); // selected light on else digitalWrite(pins[i], LOW); // other lights off } }

ESP32 Uno vs UNO R4 for This Project

By the end of this part, you know what to change when you move this project from the UNO R4 to the ESP32 Uno.

Item Arduino UNO R4 ESP32 Uno
Logic voltage 5V 3.3V
Red pin R D2 D2 (GPIO26)
Yellow pin Y D3 D3 (GPIO25)
Green pin G D4 D4 (GPIO17)
Pin number in code 2, 3, 4 26, 25, 17
Arduino IDE board Arduino UNO R4 WiFi ESP32 Dev Module

The wiring stays on the same header positions. Only the numbers in the #define lines change, because the ESP32 Uno code uses GPIO numbers.

Go Wireless: Control the Lights from a Phone

By the end of this part, you have an idea for controlling the traffic light without touching the board.

The ESP32 Uno has WiFi and Bluetooth, so the three LEDs can be switched from a web page or a phone app. Use the digital pin controls to turn red, yellow and green on or off by hand, and try a manual override on top of the automatic cycle.

Try These Next

  • Add a pedestrian push button and make the light turn red when someone presses it.
  • Add a second module on GPIO27, GPIO14 and GPIO13 to build a two-way crossing.
  • Add a buzzer that beeps while the light is green.

Troubleshooting

Problem Possible Cause Solution
No COM port in Arduino IDE CH340 driver missing or a charge-only USB cable Install the CH340 driver and use a data USB cable
Upload fails with "Failed to connect" or "Waiting for download" Board is not in download mode Hold the BOOT button while the upload starts, then release it
No light turns on GND not connected or a loose jumper wire Connect module GND to a GND pin and push the wires in firmly
Colors come in the wrong order R, Y and G wires are swapped Compare each wire with the wiring table
One light never turns on Code still uses Uno numbers 2, 3, 4 Use 26, 25 and 17 in the #define lines
All lights stay on at once Pin wired to the wrong header position Compare your wires with the wiring diagram
Cycle is too fast or too slow Times are in milliseconds Use 4000 for 4 seconds in RED_TIME, YELLOW_TIME and GREEN_TIME
LEDs look dim 3.3V output is lower than 5V This is normal, the lights still work
The program does nothing else while lights change delay() blocks the loop Use the millis() version

FAQ

Do I need a resistor between the ESP32 Uno and the traffic light module?

No. Resistors are already on the module, and the 3.3V pin output lights the LEDs well. They can look a little dimmer than on a 5V board.

What does the traffic light module contain?

It holds a red, a yellow and a green LED on one small board. It has four pins: GND, R, Y and G.

Which pin numbers do I write in the code?

Use GPIO numbers, not Uno labels: 26 for D2, 25 for D3 and 17 for D4. The numbers 2, 3 and 4 point to different pins.

Can I use different pins for the lights?

Yes. Any output pin works. Avoid D0 and D1 (USB serial), D8, D10 and A0 (boot strapping), and A2 to A5 (input only). Update the #define lines to match.

When should I pick millis() over delay()?

Choose millis() when the board must do other jobs, such as reading a button, while the lights change. delay() pauses everything.

How do I make the yellow light blink?

Switch the yellow pin on and off every 500 ms with millis(), and keep the other two pins LOW. This is a common night mode for a signal.

Can I use more than one traffic light module?

Yes. Use three more output pins for each module, for example D6 (GPIO27), D7 (GPIO14) and D9 (GPIO13). Extend the arrays in the code.

Can I use UNO shields with the ESP32 Uno?

Many shields fit because the header has the Uno shape, but the logic is 3.3V and the GPIO numbers differ. Check that a shield works with 3.3V signals first.

How is the code different from the UNO R4 version?

The logic is the same. Only the pin numbers change to GPIO numbers, and the IDE board becomes ESP32 Dev Module.

Can I control the traffic light from a web page?

Yes. The ESP32 Uno has WiFi, so you can switch the lights from a browser. See the web digital pins tutorial linked in the Go Wireless section.

What if my project needs more pins than the Uno headers give?

The ESP32 Uno has a few extra holes near the power header: GPIO32 and GPIO33 (I/O, PWM, analog on ADC1, so they also work while WiFi is on) and GPIO15 (I/O, PWM, analog on ADC2). Solder headers into the holes, then use the GPIO number in your sketch. For extra traffic lights, GPIO32 and GPIO33 are the best choice. Be careful: GPIO15 and GPIO0 (the IO0 pin at the unused Uno NC position) are boot strapping pins, so a wrong connection can stop the board from booting or uploading code. Use GPIO32 and GPIO33 first. Never use the six holes under the digital header (SD0 to SD3, CMD, CLK = GPIO6 to GPIO11). They are wired to the flash chip, and using them crashes the board.

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!