If you need reliable Arduino code for traffic light simulations, you need more than just a basic blink sketch. A proper traffic sequence requires precise timing, correct current limiting for the LEDs, and a state-machine approach to handle future expansions like pedestrian buttons. The code and wiring guide below targets the Arduino Uno R3 (and any compatible ATmega328P-based board), providing a production-ready baseline for your embedded project.
Project Spec Sheet & Parts List
Do not wire 5mm LEDs directly to Arduino GPIO pins without current-limiting resistors. The ATmega328P absolute maximum DC current per I/O pin is 40mA, but the recommended operating current is 20mA. Exceeding this will degrade the silicon and eventually brick the microcontroller.
| Component | Exact Variant / Specification | Quantity | Notes |
|---|---|---|---|
| Microcontroller | Arduino Uno R3 (Rev3) or Elegoo Uno R3 | 1 | ATmega328P based. 5V logic level. |
| Red LED | 5mm Diffused Red (Vf ~2.0V, 20mA) | 1 | Standard through-hole. |
| Yellow LED | 5mm Diffused Yellow (Vf ~2.1V, 20mA) | 1 | Standard through-hole. |
| Green LED | 5mm Diffused Green (Vf ~2.2V, 20mA) | 1 | Standard through-hole. |
| Resistors | 220Ω 1/4W Carbon Film (Red-Red-Brown-Gold) | 3 | Yields ~13mA at 5V. Safe for all three colors. |
| Wiring | 22 AWG Solid Core Jumper Wires | 6 | Male-to-male for breadboard use. |
| Prototyping | 830 Tie-Point Solderless Breadboard | 1 | Half-size (400-point) also works. |
Pin Mapping & Wiring Steps
Consistent pin mapping is critical when scaling up to intersection logic later. We use digital pins 2, 3, and 4, keeping pins 0 and 1 (RX/TX) free for Serial debugging.
| Arduino Pin | Component | Connection Details |
|---|---|---|
| D4 | Red LED | Pin -> 220Ω Resistor -> LED Anode (+) |
| D3 | Yellow LED | Pin -> 220Ω Resistor -> LED Anode (+) |
| D2 | Green LED | Pin -> 220Ω Resistor -> LED Anode (+) |
| GND | Common Ground | Arduino GND -> Breadboard Ground Rail -> All LED Cathodes (-) |
Numbered Wiring Procedure
- Place the LEDs: Insert the three 5mm LEDs into the breadboard. Ensure the longer leg (anode) and shorter leg (cathode) are in separate rows. The flat edge on the LED bulb indicates the cathode side.
- Install Resistors: Insert one leg of a 220Ω resistor into the same row as the LED anode. Insert the other leg into an empty row on the positive power rail side.
- Wire the Signals: Connect jumper wires from Arduino pins D4, D3, and D2 to the open legs of the Red, Yellow, and Green resistors, respectively.
- Establish Ground: Connect a jumper wire from any Arduino GND pin to the negative (blue/black) rail on the breadboard. Connect all LED cathodes to this ground rail using short jumper wires.
- Verify: Before plugging in the USB cable, trace every path with your finger. A shorted resistor or backward LED is the most common cause of immediate failure.
Complete Compilable Arduino Code for Traffic Light
The following C++ code uses a non-blocking-friendly structure (though it utilizes delay() for simplicity in this baseline). It includes Serial error handling to confirm pin states during setup, ensuring you aren't chasing hardware ghosts if a pin is dead.
// Target Board: Arduino Uno R3 (ATmega328P)
// Project: Standard UK/US Traffic Light Sequence
const int PIN_RED = 4;
const int PIN_YELLOW = 3;
const int PIN_GREEN = 2;
// Timing constants (in milliseconds)
const unsigned long TIME_GREEN = 5000;
const unsigned long TIME_YELLOW = 2000;
const unsigned long TIME_RED = 5000;
const unsigned long TIME_RED_YELLOW = 1000; // UK style transition
void setup() {
Serial.begin(9600);
while (!Serial) {
; // Wait for serial port to connect (needed for native USB boards)
}
// Initialize pins as outputs
pinMode(PIN_RED, OUTPUT);
pinMode(PIN_YELLOW, OUTPUT);
pinMode(PIN_GREEN, OUTPUT);
// Hardware validation: Flash all LEDs to confirm wiring
Serial.println("[INIT] Running hardware validation...");
digitalWrite(PIN_RED, HIGH);
digitalWrite(PIN_YELLOW, HIGH);
digitalWrite(PIN_GREEN, HIGH);
delay(1000);
// Check for shorts or dead pins (Basic error handling feedback)
// Note: Arduino cannot natively read back output pin state reliably without specific register reads,
// so visual confirmation is required here.
Serial.println("[INIT] Visual check: Are all 3 LEDs illuminated?");
digitalWrite(PIN_RED, LOW);
digitalWrite(PIN_YELLOW, LOW);
digitalWrite(PIN_GREEN, LOW);
Serial.println("[INIT] Traffic Light Sequence Starting.");
}
void loop() {
// State 1: Green (Traffic flows)
setLights(HIGH, LOW, LOW);
delay(TIME_GREEN);
// State 2: Yellow (Traffic slowing)
setLights(LOW, HIGH, LOW);
delay(TIME_YELLOW);
// State 3: Red (Traffic stopped)
setLights(LOW, LOW, HIGH);
delay(TIME_RED);
// State 4: Red + Yellow (Preparing to go - common in UK/EU)
setLights(LOW, HIGH, HIGH);
delay(TIME_RED_YELLOW);
}
// Helper function to manage states and prevent conflicting outputs
void setLights(int red, int yellow, int green) {
digitalWrite(PIN_RED, red);
digitalWrite(PIN_YELLOW, yellow);
digitalWrite(PIN_GREEN, green);
}
loop() and adjust the timing constants. US lights typically transition directly from Red to Green.
Debugging: First Three Things to Check When It Fails
When your traffic light sequence fails, do not immediately rewrite the code. Hardware and environment issues account for 90% of beginner failures. Check these three items first:
- LED Polarity and Resistor Continuity: Use your multimeter in continuity/diode mode. Touch the red probe to the LED anode and black to the cathode. It should light up dimly and show a voltage drop (around 2.0V). If it reads "OL" (Open Loop), the LED is backward or blown.
- USB Cable Data Lines: Many micro-USB cables are "charge-only" and lack the internal D+ and D- data wires. If the Arduino IDE cannot find the COM port, swap the cable. A known-good data cable is mandatory.
- COM Port and Board Selection: In the Arduino IDE, go to Tools > Port. If the port is greyed out, your PC isn't seeing the ATmega16U2 USB-to-Serial chip. Reinstall the CH340 drivers if you are using a clone board.
Exact Error Strings and Ranked Causes
If the IDE throws an error during compilation or upload, match it to these exact strings:
Error 1: avrdude: stk500_getsync() attempt 1 of 10: not in sync: resp=0x00
- Cause A (Most Likely): Wrong COM port selected, or the board is not physically connected.
- Cause B: Something is wired to pins 0 (RX) or 1 (TX). Disconnect any wires from D0 and D1 during upload.
- Cause C: Corrupted bootloader on the ATmega328P. Requires an ISP programmer to reburn.
Error 2: expected ';' before '}'
- Cause A: Missing semicolon at the end of a
digitalWriteordelaystatement. The compiler points to the line after the actual mistake. - Cause B: Using a comma instead of a semicolon inside the
setLights()function calls.
Extending and Simplifying the Build
Once the baseline sequence is working, you will likely want to adapt the hardware or software for a specific application.
How to Simplify: Use an RGB Module
If breadboard wiring is too cumbersome, replace the three discrete LEDs and resistors with a KY-016 RGB LED module. This module has built-in resistors and breaks out to just 4 pins (GND, R, G, B). You will need to map the Arduino pins to the module's R, G, and B pins, and invert the logic if using a common-cathode vs common-anode variant (KY-016 is typically common cathode, so HIGH = ON).
How to Extend: Non-Blocking Code and Sensors
The delay() function halts the microcontroller, meaning the Arduino cannot read buttons or sensors while waiting for a light to change. To fix this, replace delay() with a millis() based state machine. Furthermore, add an HC-SR04 Ultrasonic Sensor to detect "cars" waiting at the red light, triggering an early green cycle. According to the official Arduino millis() reference, tracking elapsed time without blocking is essential for responsive embedded systems.
FAQ: Arduino Traffic Light Sequence Questions
How do I change the timing in the Arduino code for traffic light sequences?
Locate the timing constants at the top of the sketch: TIME_GREEN, TIME_YELLOW, TIME_RED, and TIME_RED_YELLOW. These values are in milliseconds. To make the green light stay on for 10 seconds instead of 5, change const unsigned long TIME_GREEN = 5000; to 10000. Always use unsigned long for timing variables to prevent integer overflow errors when dealing with values over 32,767.
Why is my yellow traffic light LED glowing dimly on the Arduino?
Dim LEDs usually indicate insufficient current. First, verify you are using a 220Ω or 330Ω resistor; a 10kΩ resistor will severely starve the LED. Second, check the breadboard contacts. Cheap breadboards often have loose internal leaf springs. Move the LED and resistor to a different row on the breadboard to rule out a poor physical connection.
Can I use an Arduino Nano instead of the Uno R3 for this traffic light code?
Yes. The Arduino Nano uses the exact same ATmega328P microcontroller as the Uno R3. The pinout numbers (D2, D3, D4, GND) map identically in the code. The only difference is the physical form factor and the USB connector (Nano uses Mini-USB or USB-C on newer 2026 revisions). Ensure you select "Arduino Nano" and the correct processor (ATmega328P Old Bootloader vs New Bootloader) in the IDE Tools menu to avoid upload errors.
How do I make the traffic light code non-blocking without using delay()?
To make the code non-blocking, implement a state machine using the millis() function. Create an enum for your states (GREEN, YELLOW, RED), a variable to store the previousMillis, and an if (currentMillis - previousMillis >= interval) check inside the loop(). This allows the Arduino to process other tasks, like reading a pedestrian crosswalk button via digitalRead(), without pausing the main sequence loop.






