Introduction
Traditional traffic lights operate on fixed timers — green for 60 seconds, red for 60 seconds — regardless of whether there are 50 vehicles waiting or zero. This wasteful approach causes unnecessary congestion, fuel loss, and pollution every single day. A Smart Traffic Light System solves this by using IR sensors to detect actual vehicle density on each lane and dynamically adjusting signal timings in real time.
In this project, we'll build a fully functional 4-lane adaptive traffic light controller using an Arduino Uno, IR obstacle sensors, and LED traffic lights. The system detects how many vehicles are waiting in each lane and gives longer green time to busier lanes — exactly how modern smart city traffic management systems work, but built for under ₹800.
This is an outstanding project for college final year projects, smart city IoT demonstrations, school science exhibitions, and embedded systems coursework. All components are available at Anil Electronic Store, Ahmedabad.
What You'll Build
- A 4-lane traffic intersection with Red, Yellow, and Green LEDs per lane
- IR sensors on each lane detecting vehicle presence (high or low density)
- Adaptive green time — busy lane gets 10 seconds, empty lane gets 3 seconds
- Yellow warning light (2 seconds) before every red transition
- 16×2 LCD display showing current active lane and countdown timer
- Serial Monitor logging of lane status and timing decisions
- Total build time: ~2 hours
How It Works
The system models a standard 4-way road intersection with one lane in each direction — North, South, East, and West. Each lane has:
- One IR obstacle sensor pointing toward the road to detect vehicle presence
- One Red LED, one Yellow LED, and one Green LED
The Arduino cycles through each lane one by one. Before giving the green signal to a lane, it reads the IR sensor output:
- IR sensor detects vehicle (LOW output) → Lane is busy → Green time = 10 seconds
- IR sensor detects no vehicle (HIGH output) → Lane is clear → Green time = 3 seconds
This simple but effective logic means a congested lane gets more than 3× the green time of an empty lane — significantly improving traffic flow with zero human intervention.
Traffic Signal Sequence (Per Lane)
- All other lanes → Red ON
- Current lane → Read IR sensor → determine green duration (3s or 10s)
- Current lane → Green ON for calculated duration
- Current lane → Yellow ON for 2 seconds (warning)
- Current lane → Red ON
- Move to next lane → repeat
Components Required (BOM)
All components below are in stock at anilestore.com with same-day dispatch before 2 PM. See the kit panel on this page to add everything in one click.
Circuit Connections
Lane 1 (North) LEDs → Arduino Uno:
- Red LED anode → D2 via 220Ω resistor → cathode to GND
- Yellow LED anode → D3 via 220Ω resistor → cathode to GND
- Green LED anode → D4 via 220Ω resistor → cathode to GND
Lane 2 (East) LEDs → Arduino Uno:
- Red LED anode → D5 via 220Ω resistor → cathode to GND
- Yellow LED anode → D6 via 220Ω resistor → cathode to GND
- Green LED anode → D7 via 220Ω resistor → cathode to GND
Lane 3 (South) LEDs → Arduino Uno:
- Red LED anode → D8 via 220Ω resistor → cathode to GND
- Yellow LED anode → D9 via 220Ω resistor → cathode to GND
- Green LED anode → D10 via 220Ω resistor → cathode to GND
Lane 4 (West) LEDs → Arduino Uno:
- Red LED anode → D11 via 220Ω resistor → cathode to GND
- Yellow LED anode → D12 via 220Ω resistor → cathode to GND
- Green LED anode → D13 via 220Ω resistor → cathode to GND
IR Obstacle Sensors → Arduino Uno:
- IR Sensor Lane 1 (North): VCC → 5V, GND → GND, OUT → A0
- IR Sensor Lane 2 (East): VCC → 5V, GND → GND, OUT → A1
- IR Sensor Lane 3 (South): VCC → 5V, GND → GND, OUT → A2
- IR Sensor Lane 4 (West): VCC → 5V, GND → GND, OUT → A3
16×2 LCD Display (I2C) → Arduino Uno:
- VCC → 5V
- GND → GND
- SDA → A4
- SCL → A5
Power:
- Power the Arduino Uno via USB from laptop or a 5V USB adapter
- All LEDs and sensors draw well within Arduino's current limits at 5V
⚠️ Important: Every LED must have its own individual 220Ω current-limiting resistor in series. Connecting LEDs directly to Arduino pins without resistors will permanently damage the output pins.
Required Libraries
Install via Arduino IDE → Sketch → Include Library → Manage Libraries:
- LiquidCrystal_I2C by Frank de Brabander — search "LiquidCrystal I2C"
- Wire — built into Arduino IDE, no installation needed
Arduino Code — Smart Adaptive Traffic Light
// Smart Traffic Light System – Adaptive Signal Control
// Arduino Uno + IR Sensors + LEDs + I2C LCD
// Anil Electronic Store – anilestore.com
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
// ===== LED PIN DEFINITIONS =====
// Lane 1 – North
const int L1_RED = 2;
const int L1_YEL = 3;
const int L1_GRN = 4;
// Lane 2 – East
const int L2_RED = 5;
const int L2_YEL = 6;
const int L2_GRN = 7;
// Lane 3 – South
const int L3_RED = 8;
const int L3_YEL = 9;
const int L3_GRN = 10;
// Lane 4 – West
const int L4_RED = 11;
const int L4_YEL = 12;
const int L4_GRN = 13;
// ===== IR SENSOR PINS =====
const int IR1 = A0; // Lane 1 – North
const int IR2 = A1; // Lane 2 – East
const int IR3 = A2; // Lane 3 – South
const int IR4 = A3; // Lane 4 – West
// ===== TIMING SETTINGS =====
const int GREEN_BUSY = 10; // seconds — vehicle detected
const int GREEN_CLEAR = 3; // seconds — no vehicle
const int YELLOW_TIME = 2; // seconds — warning before red
// Store all pin arrays for clean looping
const int RED_PINS[4] = {L1_RED, L2_RED, L3_RED, L4_RED};
const int YEL_PINS[4] = {L1_YEL, L2_YEL, L3_YEL, L4_YEL};
const int GRN_PINS[4] = {L1_GRN, L2_GRN, L3_GRN, L4_GRN};
const int IR_PINS[4] = {IR1, IR2, IR3, IR4};
String laneNames[4] = {"North", "East", "South", "West"};
void allRed() {
for (int i = 0; i < 4; i++) {
digitalWrite(RED_PINS[i], HIGH);
digitalWrite(YEL_PINS[i], LOW);
digitalWrite(GRN_PINS[i], LOW);
}
}
void lcdCountdown(String lane, String phase, int seconds) {
for (int t = seconds; t > 0; t--) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Lane: " + lane);
lcd.setCursor(0, 1);
lcd.print(phase + " : " + String(t) + "s ");
delay(1000);
}
}
void runLane(int laneIndex) {
String laneName = laneNames[laneIndex];
// Read IR sensor — LOW = vehicle detected
int irVal = digitalRead(IR_PINS[laneIndex]);
bool vehiclePresent = (irVal == LOW);
int greenTime = vehiclePresent ? GREEN_BUSY : GREEN_CLEAR;
Serial.print("Lane: "); Serial.print(laneName);
Serial.print(" | Vehicle: "); Serial.print(vehiclePresent ? "YES" : "NO");
Serial.print(" | Green time: "); Serial.print(greenTime); Serial.println("s");
// Set all lanes RED first
allRed();
// LCD status before green
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Lane: " + laneName);
lcd.setCursor(0, 1);
lcd.print(vehiclePresent ? "Dense " : "Clear ");
lcd.print(String(greenTime) + "s green");
delay(500);
// GREEN phase — active lane
digitalWrite(RED_PINS[laneIndex], LOW);
digitalWrite(GRN_PINS[laneIndex], HIGH);
lcdCountdown(laneName, "GREEN ", greenTime);
// YELLOW phase — warning
digitalWrite(GRN_PINS[laneIndex], LOW);
digitalWrite(YEL_PINS[laneIndex], HIGH);
lcdCountdown(laneName, "YELLOW", YELLOW_TIME);
// RED phase — back to red
digitalWrite(YEL_PINS[laneIndex], LOW);
digitalWrite(RED_PINS[laneIndex], HIGH);
delay(300); // Brief pause between lane transitions
}
void setup() {
Serial.begin(9600);
// Init all LED pins
for (int i = 0; i < 4; i++) {
pinMode(RED_PINS[i], OUTPUT);
pinMode(YEL_PINS[i], OUTPUT);
pinMode(GRN_PINS[i], OUTPUT);
pinMode(IR_PINS[i], INPUT);
}
// LCD init
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("Smart Traffic Sys");
lcd.setCursor(0, 1);
lcd.print("Anil ElecStore");
delay(2000);
// Start with all red
allRed();
Serial.println("Smart Traffic Light System Ready.");
Serial.println("Adaptive timing: Dense=10s, Clear=3s");
}
void loop() {
// Cycle through all 4 lanes in order
for (int lane = 0; lane < 4; lane++) {
runLane(lane);
}
}
How the Code Works — Step by Step
- Setup: All 12 LED pins (3 per lane × 4 lanes) are configured as OUTPUT. All 4 IR sensor pins are configured as INPUT. The LCD is initialised and shows the system name on boot. All lanes start on RED.
-
Main loop: The Arduino cycles through Lanes 1 to 4 continuously. For each lane, it calls
runLane(laneIndex). - runLane() function: Reads the IR sensor for that lane. If the sensor output is LOW (object/vehicle detected), the green time is set to 10 seconds. If HIGH (no vehicle), green time is 3 seconds. All other lanes are set to RED, the active lane gets GREEN for the calculated duration with a live LCD countdown, then YELLOW for 2 seconds, then RED again.
-
LCD countdown: The
lcdCountdown()function updates the LCD every second showing the lane name, signal phase (GREEN/YELLOW), and remaining seconds — giving a clear real-time display of system state.
Building the Physical Traffic Light Model
To make this project visually impressive for exhibitions and demos, build a physical intersection model:
- Base: Use a 30×30 cm cardboard sheet or wooden board as the intersection base. Draw or print road markings on it.
- Traffic light poles: Use 15 cm lengths of wooden skewers or small PVC pipes as poles, one at each corner of the intersection.
- LED mounting: Insert Red, Yellow, and Green LEDs into small holes drilled/punched vertically on a small rectangular cardboard strip — this forms the traffic light head. Mount one on each pole.
- IR sensor placement: Mount one IR sensor at the entry of each lane, pointing across the lane to detect approaching vehicles (toy cars work great for demos).
- Arduino and LCD: Mount centrally on the base board with the LCD facing the audience.
- Wiring: Run wires neatly along the board edges using tape or cable clips.
Upgrading to Multi-Level Density Detection
The basic version uses one IR sensor per lane for a binary (vehicle / no vehicle) decision. You can upgrade to multi-level density detection using multiple IR sensors per lane:
- 1 sensor triggered: Low density → Green time = 5 seconds
- 2 sensors triggered: Medium density → Green time = 10 seconds
- 3 sensors triggered: High density → Green time = 15 seconds
Place 3 IR sensors at increasing distances from the stop line in each lane — the further the queue stretches, the more sensors get triggered, and the longer the green time becomes. This models real-world adaptive signal control very accurately.
Adding an Emergency Vehicle Override
Add a dedicated push button or IR beam sensor on each lane to simulate an emergency vehicle (ambulance, fire truck) detection:
// Emergency override — add in loop() before the for loop:
for (int i = 0; i < 4; i++) {
if (digitalRead(EMERGENCY_PINS[i]) == LOW) {
Serial.println("EMERGENCY VEHICLE on Lane " + laneNames[i]);
lcd.clear();
lcd.print("EMERGENCY!");
lcd.setCursor(0,1);
lcd.print("Lane: " + laneNames[i]);
allRed();
delay(500);
digitalWrite(RED_PINS[i], LOW);
digitalWrite(GRN_PINS[i], HIGH);
delay(10000); // 10 second emergency green
digitalWrite(GRN_PINS[i], LOW);
digitalWrite(RED_PINS[i], HIGH);
}
}
This gives any lane an instant 10-second green override when an emergency button is pressed — simulating real traffic management priority protocols.
Pedestrian Crossing Add-On
Add pedestrian crossing signals using two additional LEDs (Red Walk and Green Walk) per crossing, controlled by a push button:
- When a pedestrian presses the button, the system finishes the current green phase, sets all vehicle lanes to RED, and gives pedestrians a 15-second green walk signal
- A buzzer beeps during the pedestrian crossing phase for visually impaired pedestrians
- After 15 seconds, vehicle signals resume from the next lane in sequence
Troubleshooting Tips
- LEDs not lighting up: Check that each LED has a 220Ω resistor in series. Verify polarity — longer leg is anode (+), connect to Arduino pin side. Test each LED individually with a fresh 3.3V supply.
- IR sensor not detecting: Adjust the small blue potentiometer on the IR sensor module to change sensitivity. Turn clockwise to increase sensitivity. The indicator LED on the module should turn ON when an object is in range.
- LCD shows garbled text or nothing: Run an I2C scanner sketch to confirm the LCD's I2C address (0x27 or 0x3F are most common). Update the address in
LiquidCrystal_I2C lcd(0x27, 16, 2). Adjust the contrast potentiometer on the back of the I2C module. - All lanes stay red: Check the IR sensor wiring — if all 4 sensors read HIGH constantly, the loop logic may be skipping green phases. Add
Serial.println(digitalRead(IR_PINS[i]))to debug sensor readings. - Green time doesn't change with vehicles: Ensure IR sensors are wired to A0–A3 (used as digital pins via
digitalRead()). Check thatpinMode(IR_PINS[i], INPUT)is correctly set in setup().
Upgrades & Next Steps
- Add a NodeMCU ESP8266 alongside the Arduino to upload traffic density data to a web dashboard in real time
- Use an ultrasonic sensor (HC-SR04) instead of IR for more reliable vehicle queue length measurement
- Add a 7-segment or TM1637 display at each lane showing the countdown timer — just like real traffic lights
- Implement night mode — when ambient light (LDR sensor) drops below a threshold, all signals switch to flashing yellow with extended green times
- Add vehicle counting — count how many vehicles pass through each lane per cycle and log to SD card or serial for traffic analysis
- Upgrade to a Raspberry Pi or Arduino Mega for a more complex multi-intersection simulation with coordinated green wave timing
Why This Project Stands Out at Science Fairs
- ✅ Solves a real, visible problem — traffic congestion is relatable to every judge and viewer
- ✅ Live and interactive demo — place toy cars in front of IR sensors and watch timings change in real time
- ✅ Smart city relevance — connects directly to AI, IoT, and smart infrastructure themes
- ✅ Expandable narrative — start with 4 lanes, talk about scaling to city-wide networks with computer vision
- ✅ Clear visual output — colourful LEDs, LCD countdown, and serial log make every step of the logic visible
- ✅ Under ₹900 total cost — affordable enough to build a polished, well-mounted physical model
Real-World Applications
- 🏙️ Smart city traffic management — adaptive signals at real intersections
- 🏭 Factory floor vehicle routing — manage forklift traffic at internal junctions
- 🏫 School gate traffic control — manage entry and exit lanes during peak hours
- 🅿️ Parking lot entry management — control entry/exit flow with sensor-based signals
- 🚑 Emergency vehicle preemption systems — real hospitals and fire stations use this technology
- 🔬 Traffic engineering research — simulate and test signal timing algorithms
Why Buy from Anil Electronic Store?
- ✅ Genuine Arduino Uno boards — ATmega328P with CH340G USB, fully tested
- ✅ Quality IR obstacle sensors — adjustable sensitivity, reliable detection up to 30cm
- ✅ Bright 5mm LEDs — red, yellow/amber, and green available individually or in assorted packs
- 🚚 Same-day dispatch for orders placed before 2 PM from Ahmedabad
- 🧾 Official GST invoice — ideal for college project budget reimbursements
- 📲 Free WhatsApp engineer support — we help with wiring, code, and exhibition tips
- 📦 Delivery across 19,000+ PIN codes in India
Conclusion
The Smart Traffic Light System with Arduino and IR sensors is one of the most impactful and visually impressive projects in the embedded systems space. It combines real-world problem solving, sensor interfacing, digital logic, and display output into a single project that anyone can understand — and everyone finds impressive when they see the signal timings change automatically based on traffic.
Whether you're building it for a college final year project, a school science exhibition, a smart city prototype, or just to sharpen your Arduino skills — this project delivers a professional result with simple, affordable components from Anil Electronic Store.
All parts in the BOM are 100% genuine, tested, and in stock. Order before 2 PM for same-day dispatch across 19,000+ PIN codes in India. Build the intersection. Control the flow. 🚦⚡