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:
- Wire a traffic light module to three Uno header pins
- Switch each LED with pinMode() and digitalWrite()
- Tidy the sketch using a function and a for loop
- Switch lights with millis() and no blocking delay()

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) |
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 |

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.

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

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().
Step 2 — Light one color
Call digitalWrite() to turn red on and the other two off, then hold that state with delay().
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.
| 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
- First time with this board? Set it up with ESP32 Uno - Getting Started before you continue.
- Build the circuit by following the wiring table above.
- Plug in the USB Type-C cable between the ESP32 Uno and your computer.
- Select the board in Arduino IDE: pick ESP32 Dev Module and the COM port of the board (CH340).
- Copy the code above into Arduino IDE.
- Press Upload to flash the sketch.
- Watch the module. The order is red, yellow, green, then red again.
- 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.
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.
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.
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.
Function References
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.