ESP32 S3 UNO - Traffic Light
This ESP32 S3 Uno traffic light tutorial shows you how to wire a traffic light module to the ESP32 S3 Uno form board and switch its red, yellow and green lights with Arduino code. You will build a simple traffic signal that cycles through the three colors, then make the code shorter and non-blocking.
In this tutorial, you will:
- Wire a traffic light module to the ESP32 S3 Uno
- Turn the red, yellow and green LEDs on and off with digitalWrite()
- Clean up the traffic signal code with a function and a for loop
- Run the traffic lights without delay() by using millis()

Hardware Preparation
| 1 | × | ESP32 S3 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
A traffic light module is a small board with a red, a yellow and a green LED, just like a real traffic signal. The current-limiting resistors are already on the board, so you can drive each LED straight from a GPIO pin.
Pinout
The module has only four pins. One is ground, and the other three each control one color.
| Pin | What It Does |
|---|---|
| GND | Ground. Connect it to a GND pin on the ESP32 S3 Uno |
| R | Controls the red light. Connect it to a digital output pin |
| Y | Controls the yellow light. Connect it to a digital output pin |
| G | Controls the green light. Connect it to a digital output pin |

How It Works
Each color pin works like a normal LED input. When you set the pin HIGH, that LED turns on. When you set it LOW, the LED turns off. A traffic signal is just a sequence: red on for a while, then yellow, then green, and then the cycle starts again.
The ESP32 S3 Uno outputs 3.3V on its GPIO pins. This is enough to light the module's LEDs, so you do not need any extra parts.
ESP32 S3 Uno Pinout
The image below shows the pinout diagram of the ESP32 S3 Uno form board. Use it to find the Uno header pins (D2, D3, D4…) and their GPIO numbers when you wire the traffic light.

Wiring Diagram
Connect the three color pins to D2, D3 and D4, and the GND pin to GND, as shown below.

This image is created using Fritzing. Click to enlarge image
| Traffic Light Pin | ESP32 S3 Uno Pin |
|---|---|
| R | D2 (GPIO18) |
| Y | D3 (GPIO17) |
| G | D4 (GPIO19) |
| GND | GND |
How To Program For Traffic Light module
Controlling the module takes only two Arduino functions. You set the pins as outputs once, and then switch each color on or off when you need it.
Set the pins as outputs
Use pinMode() inside setup() for all three color pins:
Turn on one light
Use digitalWrite() to turn the red light on and the other two off, then wait with delay():
ESP32 S3 Uno Code
This sketch turns on red, then yellow, then green, and keeps each one on for 4 seconds. The pins are GPIO18, GPIO17 and GPIO19, which are the D2, D3 and D4 headers on the ESP32 S3 Uno.
Detailed Instructions
- New to the ESP32 S3 Uno? Follow ESP32 S3 Uno - Getting Started first.
- Wire it up as shown in the diagram.
- Connect the board to your computer with a USB Type-C cable.
- Open Arduino IDE, choose the ESP32S3 Dev Module board and the correct COM port.
- Copy the code above and paste it into Arduino IDE.
- Upload the code by clicking the Upload button.
- Watch the module. The lights should go red, yellow, green, and then start again.
- Tip: Change RED_TIME, YELLOW_TIME and GREEN_TIME to try different timings.
Real traffic lights use different sequences and timings in different countries. This example only shows the basic idea of how a traffic signal controls the flow of cars.
The code above controls each light with its own lines. It works, but it repeats a lot. The next section makes it shorter and better.
ESP32 S3 Uno Code Optimization
Repeated code is hard to read and easy to break. Here are three better versions, each one a small step up from the last.
Use a function
This version moves the "one light on, others off" logic into a function called trafic_light_on(). The pins and times are stored in arrays, so loop() only needs one line per color.
Use a for loop
Since the colors are stored in arrays, a for loop can walk through red, yellow and green. The loop() function becomes only a few lines long.
Use millis() instead of delay()
delay() stops the whole program, so the ESP32 S3 Uno cannot do anything else while it waits. This version checks the time with millis() and changes the light only when its time is up. You can add other code at the "TO DO" line, such as reading a button or a sensor.
Video Tutorial
Watch the video below to see this ESP32 S3 Uno project step by step.
Function References
FAQ
Can the ESP32 S3 Uno drive a traffic light module directly?
Yes. The module has its own resistors, and the ESP32 S3 Uno's 3.3V output is enough to light the LEDs. The LEDs may look a little less bright than on a 5V board, but they work well.
Do I need to change the code from an Arduino UNO for the ESP32 S3 Uno?
The logic stays the same. You only need to use GPIO numbers in code: D2 is GPIO18, D3 is GPIO17 and D4 is GPIO19. Writing 2, 3 and 4 would control the wrong pins on the ESP32 S3 Uno.
Can I use other pins for the traffic light?
Yes. Any output pin works. Avoid D0 and D1 (USB serial), and avoid D6 (GPIO3) and D9 (GPIO46) because they are boot strapping pins. Remember to update the #define lines in the code.
Why use millis() instead of delay()?
delay() blocks the program, so nothing else can run while a light is on. With millis(), the ESP32 S3 Uno keeps looping, so you can read buttons, sensors or WiFi at the same time.
What if my project needs more pins than the Uno headers give?
The ESP32 S3 Uno has two extra rows of holes with more GPIOs: GPIO15 and GPIO16 (I/O, PWM, analog), GPIO45 and GPIO35 to GPIO42 (I/O, PWM), and GPIO47/GPIO48 (output only, PWM). Solder pin headers to use them and write the GPIO number in code. For extra traffic lights, GPIO35 to GPIO42 are a good choice. Be careful: GPIO47 and GPIO48 may run at 1.8V instead of 3.3V on some modules (especially ones with "V" in the name, like R8V or R16V), so 3.3V devices can be damaged or act strangely. Also, GPIO0, GPIO3 (D6), GPIO45 and GPIO46 (D9) are boot strapping pins, and a wrong connection can stop the board from booting or uploading code. Use the other extra pins first.
Troubleshooting
| Problem | Possible Cause | Solution |
|---|---|---|
| No COM port in Arduino IDE | USB driver missing or board not in upload mode | Install the CP210x or CH340 driver, or hold BOOT while pressing RESET, then upload again |
| No light turns on | GND not connected or loose jumper wires | Check that the module GND goes to a GND pin and all wires are firm |
| Wrong color lights up | R, Y and G wires swapped | Match the wiring table, R to D2, Y to D3, G to D4 |
| One light never turns on | Code uses Uno numbers like 2, 3, 4 instead of GPIO numbers | Use 18, 17 and 19 in the #define lines |
| Board does not boot after wiring | A light is wired to a boot strapping pin like D6 or D9 | Move it back to D2, D3 or D4 as in the diagram |
| Lights change too fast or too slow | Timing values are in milliseconds | Set RED_TIME, YELLOW_TIME and GREEN_TIME in milliseconds, for example 4000 for 4 seconds |