Traffic Light Using Arduino and OLED Display

Traffic Light Using Arduino Uno and OLED Display

Traffic Light Using Arduino Uno and OLED Display

This project creates a realistic traffic light system with an OLED display timer, featuring custom PCB design and professional LED sequencing. The system follows standard traffic light patterns with visual countdown display for enhanced user experience.


How the System Works

  • Custom traffic light-shaped PCB with vertical LED arrangement (Red, Yellow, Green)
  • 0.96" OLED display shows real-time countdown timer for each light phase
  • Standard traffic light sequence: Red (15s) → Green (13s) → Yellow (3s)
  • Yellow light features blinking "00" display for clear warning indication
  • Each 10mm LED has dedicated 220 ohm current-limiting resistor
  • Professional timing with 1-second delay between Red and Green transitions
  • Powered by 7.4V battery through breadboard power distribution

Materials Required


PCB Gerber Files

Download the custom traffic light PCB design files:

Google Drive

Manufacture your PCB using JLCPCB's professional service:

Order PCB Now

Traffic Light Sequence

The system follows realistic traffic light timing patterns:

  • RED Light: 15 seconds - Stop signal with countdown display
  • GREEN Light: 13 seconds - Go signal with countdown display
  • YELLOW Light: 3 seconds - Warning with blinking "00" display
  • Transition Delay: 1 second pause between Red and Green phases

Step-by-Step Assembly

1. PCB Preparation:

  • Order the custom traffic light PCB using provided Gerber files
  • Solder L-shape male headers for LED connections
  • Install female headers for Arduino connection
  • Solder 220 ohm resistors below each LED position

2. LED Installation:

  • Install 10mm LEDs in vertical order: Red, Yellow, Green
  • Ensure proper polarity alignment for all LEDs
  • Test each LED with resistor before final assembly

3. Electronics Wiring:

  • Connect Red LED to Arduino pin 4
  • Connect Yellow LED to Arduino pin 3
  • Connect Green LED to Arduino pin 2
  • Wire OLED display to I2C pins (SDA, SCL)
  • Connect 7.4V battery through breadboard for power distribution

4. Programming & Testing:

  • Upload the Arduino code with required libraries
  • Verify OLED display initialization and countdown
  • Test complete light sequence: Red → Green → Yellow
  • Confirm blinking behavior during yellow phase
  • Adjust timing values in code if needed

🎥 Watch the video above for complete assembly and demonstration.


Arduino Code

Upload this code to your Arduino after installing the required libraries (Wire, Adafruit_GFX, Adafruit_SSD1306):

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

// OLED Display setup
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// LED pins - swapped to match your physical wiring
#define RED_LED 4      // Physical red LED is connected to pin 4
#define YELLOW_LED 3   // Unchanged
#define GREEN_LED 2    // Physical green LED is connected to pin 2

// Traffic light timings (in seconds)
int redTime = 15;     // 15 seconds
int yellowTime = 3;   // 3 seconds
int greenTime = 13;   // 12 seconds

// State variables
enum TrafficState { RED, GREEN, YELLOW }; // Changed order to match new sequence
TrafficState currentState = RED;
unsigned long stateStartTime = 0;
int remainingTime = 0;
unsigned long lastUpdateTime = 0;
bool blinkState = false;
unsigned long lastBlinkTime = 0;
bool greenDelayActive = false;
unsigned long greenDelayStartTime = 0;

void setup() {
  // Initialize LED pins
  pinMode(RED_LED, OUTPUT);
  pinMode(YELLOW_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  
  // Initialize OLED display
  if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    for(;;);
  }
  
  display.clearDisplay();
  display.setTextColor(SSD1306_WHITE);
  
  // Start with red light
  setLights(RED);
  stateStartTime = millis();
  lastUpdateTime = millis();
  lastBlinkTime = millis();
  remainingTime = redTime;
}

void loop() {
  unsigned long currentTime = millis();
  
  // Handle green light delay
  if (greenDelayActive) {
    if (currentTime - greenDelayStartTime >= 1000) { // 1 second delay
      greenDelayActive = false;
      changeState(GREEN);
    }
    return; // Don't process other logic during delay
  }
  
  // Update display every second (1000 milliseconds)
  if (currentTime - lastUpdateTime >= 1000) {
    lastUpdateTime = currentTime;
    
    // Calculate elapsed time in seconds
    unsigned long elapsedSeconds = (currentTime - stateStartTime) / 1000;
    
    // Calculate remaining time based on current state - UPDATED SEQUENCE
    switch(currentState) {
      case RED:
        remainingTime = redTime - elapsedSeconds;
        if(remainingTime <= 0) {
          startGreenDelay(); // Start 1-second delay before green
        }
        break;
        
      case GREEN:
        remainingTime = greenTime - elapsedSeconds;
        if(remainingTime <= 0) {
          changeState(YELLOW); // Green goes to Yellow now
        }
        break;
        
      case YELLOW:
        remainingTime = yellowTime - elapsedSeconds;
        if(remainingTime <= 0) {
          changeState(RED); // Yellow goes to Red
        }
        break;
    }
    
    // Ensure remaining time doesn't go below 0
    if(remainingTime < 0) remainingTime = 0;
    
    // Update display with big numbers
    updateDisplay();
  }
  
  // Handle blinking for yellow light
  if (currentState == YELLOW) {
    if (currentTime - lastBlinkTime >= 500) { // Blink every 500ms
      lastBlinkTime = currentTime;
      blinkState = !blinkState;
      updateDisplay();
    }
  }
}

void startGreenDelay() {
  greenDelayActive = true;
  greenDelayStartTime = millis();
  // Turn off all lights during delay
  digitalWrite(RED_LED, LOW);
  digitalWrite(YELLOW_LED, LOW);
  digitalWrite(GREEN_LED, LOW);
  
  // Update display to show "00" during delay
  display.clearDisplay();
  display.setTextSize(4);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor((SCREEN_WIDTH - 64) / 2, (SCREEN_HEIGHT - 32) / 2);
  display.print("00");
  display.display();
}

void changeState(TrafficState newState) {
  currentState = newState;
  stateStartTime = millis();
  lastUpdateTime = millis();
  lastBlinkTime = millis();
  blinkState = true; // Start with display ON
  setLights(newState);
}

void setLights(TrafficState state) {
  // Turn off all LEDs first
  digitalWrite(RED_LED, LOW);
  digitalWrite(YELLOW_LED, LOW);
  digitalWrite(GREEN_LED, LOW);
  
  // Turn on the appropriate LED
  switch(state) {
    case RED:
      digitalWrite(RED_LED, HIGH);  // This will now activate pin 4 (your physical red LED)
      remainingTime = redTime;
      break;
      
    case GREEN:
      digitalWrite(GREEN_LED, HIGH);  // This will now activate pin 2 (your physical green LED)
      remainingTime = greenTime;
      break;
      
    case YELLOW:
      digitalWrite(YELLOW_LED, HIGH); // This activates pin 3 (unchanged)
      remainingTime = yellowTime;
      break;
  }
}

void updateDisplay() {
  display.clearDisplay();
  
  // Display big centered two-digit number
  display.setTextSize(7); // Large text size
  display.setTextColor(SSD1306_WHITE);
  
  char timeStr[3];
  
  // For yellow light, show blinking "00" instead of countdown
  if (currentState == YELLOW) {
    if (blinkState) {
      sprintf(timeStr, "00");
    } else {
      // Don't display anything during off phase (creates blink effect)
      display.display();
      return;
    }
  } else {
    // For red and green, show normal countdown
    sprintf(timeStr, "%02d", remainingTime);
  }
  
  // Calculate position to center the text
  int16_t x1, y1;
  uint16_t w, h;
  display.getTextBounds(timeStr, 0, 0, &x1, &y1, &w, &h);
  
  int x = (SCREEN_WIDTH - w) / 2;
  int y = (SCREEN_HEIGHT - h) / 2;
  
  // Display the big centered number
  display.setCursor(x, y);
  display.print(timeStr);
  
  display.display();
}

Code Explanation:

Setup:

Initializes LED pins (Red-pin4, Yellow-pin3, Green-pin2), OLED display, and starts with Red light state. Sets up timing variables for the traffic light sequence.

Loop:

Manages the complete traffic light cycle: Red (15s) → 1s delay → Green (13s) → Yellow (3s) → Red. Updates OLED display every second with countdown, and handles yellow light blinking with "00" display.


Why Choose This Design?

  • Professional PCB: Custom traffic light-shaped board for authentic appearance
  • 📱 Visual Feedback: OLED display shows real-time countdown for each phase
  • 🚦 Realistic Timing: Standard traffic light sequences with proper transitions
  • Quality Components: 10mm LEDs with proper current-limiting resistors
  • 🔧 Easy Assembly: Pre-designed PCB simplifies construction
  • 🎯 Educational Value: Perfect for learning Arduino, PCB design, and traffic systems

Learning Outcomes

  • PCB Design: Understanding custom circuit board layout and manufacturing
  • Arduino Programming: State machines, timing control, and display interfaces
  • OLED Integration: Working with I2C displays and graphics libraries
  • LED Control: Proper current limiting and sequencing techniques
  • Real-world Systems: Implementing practical traffic control logic

Comments

Popular posts from this blog

Arduino Code Car Parking System

Arduino Code

Solar Tracking System