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:

  1. Wire a traffic light module to the ESP32 S3 Uno
  2. Turn the red, yellow and green LEDs on and off with digitalWrite()
  3. Clean up the traffic signal code with a function and a for loop
  4. Run the traffic lights without delay() by using millis()
ESP32 S3 Uno traffic light

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

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
Traffic Light Pinout

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.

ESP32 S3 Uno pinout diagram

Wiring Diagram

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

The wiring diagram between ESP32 S3 Uno traffic light

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:

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

Turn on one light

Use digitalWrite() to turn the red light on and the other two off, then wait with delay():

digitalWrite(PIN_RED, HIGH); // Set the RED LED to on digitalWrite(PIN_YELLOW, LOW); // Set the YELLOW LED to off digitalWrite(PIN_GREEN, LOW); // Set the GREEN LED to off delay(RED_TIME); // Keep the RED LED on for the time set by RED_TIME

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.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-traffic-light */ #define PIN_RED 18 // The ESP32 S3 Uno pin connected to R pin of traffic light module #define PIN_YELLOW 17 // The ESP32 S3 Uno pin connected to Y pin of traffic light module #define PIN_GREEN 19 // The ESP32 S3 Uno pin connected to G pin of traffic light module #define RED_TIME 4000 // RED time in millisecond #define YELLOW_TIME 4000 // YELLOW time in millisecond #define GREEN_TIME 4000 // GREEN time in millisecond void setup() { pinMode(PIN_RED, OUTPUT); pinMode(PIN_YELLOW, OUTPUT); pinMode(PIN_GREEN, OUTPUT); } // the loop function runs over and over again forever void loop() { // red light on digitalWrite(PIN_RED, HIGH); // turn on digitalWrite(PIN_YELLOW, LOW); // turn off digitalWrite(PIN_GREEN, LOW); // turn off delay(RED_TIME); // keep red light on during a period of time // yellow light on digitalWrite(PIN_RED, LOW); // turn off digitalWrite(PIN_YELLOW, HIGH); // turn on digitalWrite(PIN_GREEN, LOW); // turn off delay(YELLOW_TIME); // keep yellow light on during a period of time // green light on digitalWrite(PIN_RED, LOW); // turn off digitalWrite(PIN_YELLOW, LOW); // turn off digitalWrite(PIN_GREEN, HIGH); // turn on delay(GREEN_TIME); // keep green light on during a period of time }

Detailed Instructions

  1. New to the ESP32 S3 Uno? Follow ESP32 S3 Uno - Getting Started first.
  2. Wire it up as shown in the diagram.
  3. Connect the board to your computer with a USB Type-C cable.
  4. Open Arduino IDE, choose the ESP32S3 Dev Module board and the correct COM port.
  5. Copy the code above and paste it into Arduino IDE.
  6. Upload the code by clicking the Upload button.
  7. Watch the module. The lights should go red, yellow, green, and then start again.
  8. 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.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-traffic-light */ #define PIN_RED 18 // The ESP32 S3 Uno pin connected to R pin of traffic light module #define PIN_YELLOW 17 // The ESP32 S3 Uno pin connected to Y pin of traffic light module #define PIN_GREEN 19 // The ESP32 S3 Uno pin connected to G pin of traffic light module #define RED_TIME 2000 // RED time in millisecond #define YELLOW_TIME 1000 // YELLOW time in millisecond #define GREEN_TIME 2000 // GREEN time in millisecond #define RED 0 // Index in array #define YELLOW 1 // Index in array #define GREEN 2 // Index in array const int pins[] = { PIN_RED, PIN_YELLOW, PIN_GREEN }; const int times[] = { RED_TIME, YELLOW_TIME, GREEN_TIME }; void setup() { pinMode(PIN_RED, OUTPUT); pinMode(PIN_YELLOW, OUTPUT); pinMode(PIN_GREEN, OUTPUT); } // the loop function runs over and over again forever void loop() { // red light on trafic_light_on(RED); delay(times[RED]); // keep red light on during a period of time // yellow light on trafic_light_on(YELLOW); delay(times[YELLOW]); // keep yellow light on during a period of time // green light on trafic_light_on(GREEN); delay(times[GREEN]); // keep green light on during a period of time } void trafic_light_on(int light) { for (int i = RED; i <= GREEN; i++) { if (i == light) digitalWrite(pins[i], HIGH); // turn on else digitalWrite(pins[i], LOW); // turn off } }

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.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-traffic-light */ #define PIN_RED 18 // The ESP32 S3 Uno pin connected to R pin of traffic light module #define PIN_YELLOW 17 // The ESP32 S3 Uno pin connected to Y pin of traffic light module #define PIN_GREEN 19 // The ESP32 S3 Uno pin connected to G pin of traffic light module #define RED_TIME 2000 // RED time in millisecond #define YELLOW_TIME 1000 // YELLOW time in millisecond #define GREEN_TIME 2000 // GREEN time in millisecond #define RED 0 // Index in array #define YELLOW 1 // Index in array #define GREEN 2 // Index in array const int pins[] = {PIN_RED, PIN_YELLOW, PIN_GREEN}; const int times[] = {RED_TIME, YELLOW_TIME, GREEN_TIME}; void setup() { pinMode(PIN_RED, OUTPUT); pinMode(PIN_YELLOW, OUTPUT); pinMode(PIN_GREEN, OUTPUT); } // the loop function runs over and over again forever void loop() { for (int light = RED; light <= GREEN; light ++) { trafic_light_on(light); delay(times[light]); // keep light on during a period of time } } void trafic_light_on(int light) { for (int i = RED; i <= GREEN; i ++) { if (i == light) digitalWrite(pins[i], HIGH); // turn on else digitalWrite(pins[i], LOW); // turn off } }

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.

/* * This ESP32 S3 Uno code was developed by newbiely.com * * This ESP32 S3 Uno code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/tutorials/esp32-s3-uno/esp32-s3-uno-traffic-light */ #define PIN_RED 18 // The ESP32 S3 Uno pin connected to R pin of traffic light module #define PIN_YELLOW 17 // The ESP32 S3 Uno pin connected to Y pin of traffic light module #define PIN_GREEN 19 // The ESP32 S3 Uno pin connected to G pin of traffic light module #define RED_TIME 2000 // RED time in millisecond #define YELLOW_TIME 1000 // YELLOW time in millisecond #define GREEN_TIME 2000 // GREEN time in millisecond #define RED 0 // Index in array #define YELLOW 1 // Index in array #define GREEN 2 // Index in array const int pins[] = { PIN_RED, PIN_YELLOW, PIN_GREEN }; const int times[] = { RED_TIME, YELLOW_TIME, GREEN_TIME }; unsigned long last_time = 0; int light = RED; // start with RED light void setup() { pinMode(PIN_RED, OUTPUT); pinMode(PIN_YELLOW, OUTPUT); pinMode(PIN_GREEN, OUTPUT); trafic_light_on(light); last_time = millis(); } // the loop function runs over and over again forever void loop() { if ((millis() - last_time) > times[light]) { light++; if (light >= 3) light = RED; // new circle trafic_light_on(light); last_time = millis(); } // TO DO: your other code } void trafic_light_on(int light) { for (int i = RED; i <= GREEN; i++) { if (i == light) digitalWrite(pins[i], HIGH); // turn on else digitalWrite(pins[i], LOW); // turn off } }

Video Tutorial

Watch the video below to see this ESP32 S3 Uno project step by step.

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

※ 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!