#include <Arduino.
h>
// Pin setup for Arduino Nano
const uint8_t GREEN_PINS[4] = {2, 5, 8, 11};
const uint8_t YELLOW_PINS[4] = {3, 6, 9, 12};
const uint8_t RED_PINS[4] = {4, 7, 10, 13};
// Ultrasonic sensors pins (trigger, echo)
const uint8_t TRIGGER_PINS[4] = {14, 16, 18, 20}; // A0, A2, A4, A6
const uint8_t ECHO_PINS[4] = {15, 17, 19, 21}; // A1, A3, A5, A7
// Buzzer on TX pin (D1)
const uint8_t BUZZER_PIN = 1; // TX pin (D1)
// Timing parameters
const unsigned long MIN_GREEN_MS = 6000;
const unsigned long MAX_GREEN_MS = 20000;
const unsigned long YELLOW_MS = 3000;
const unsigned long ALL_RED_MS = 1000;
const unsigned long BASE_GREEN_MS = 8000;
const unsigned long LOOP_DELAY_MS = 250;
// Sensor calibration and smoothing
const float SENSOR_NOISE_MM = 80.0;
const float VEHICLE_LENGTH_MM = 4500.0;
const float MAX_DIST_MM = 100.0;
const float MIN_DIST_MM = 80.0;
const uint8_t SMOOTHING_SAMPLES = 8;
// Lane sensor state struct
struct LaneState {
uint16_t distances[SMOOTHING_SAMPLES];
uint8_t bufferIndex = 0;
float smoothedDistance = MAX_DIST_MM;
float queueEstimate = 0.0;
bool sensorHealthy = false;
};
LaneState lanes[4];
// -------- Utility functions --------
void buzz(uint16_t duration = 200) {
digitalWrite(BUZZER_PIN, HIGH);
delay(duration);
digitalWrite(BUZZER_PIN, LOW);
}
float readDistanceMM(uint8_t lane) {
digitalWrite(TRIGGER_PINS[lane], LOW);
delayMicroseconds(2);
digitalWrite(TRIGGER_PINS[lane], HIGH);
delayMicroseconds(10);
digitalWrite(TRIGGER_PINS[lane], LOW);
unsigned long duration = pulseIn(ECHO_PINS[lane], HIGH, 30000UL);
if (duration == 0) return MAX_DIST_MM;
float distance = duration * 0.343f / 2.0f;
return constrain(distance, MIN_DIST_MM, MAX_DIST_MM);
}
void updateSensor(uint8_t lane) {
LaneState& state = lanes[lane];
float reading = readDistanceMM(lane);
[Link][[Link]] = static_cast<uint16_t>(reading);
[Link] = ([Link] + 1) % SMOOTHING_SAMPLES;
uint32_t sum = 0;
for (uint8_t i = 0; i < SMOOTHING_SAMPLES; ++i) {
sum += [Link][i];
}
[Link] = static_cast<float>(sum) / SMOOTHING_SAMPLES;
float effectiveQueue = max(0.0f, MAX_DIST_MM - [Link] -
SENSOR_NOISE_MM);
[Link] = effectiveQueue / VEHICLE_LENGTH_MM;
[Link] = ([Link] <= MAX_DIST_MM - 10.0f);
}
unsigned long calculateGreenTime(uint8_t lane) {
float vehicles = lanes[lane].queueEstimate;
unsigned long adaptive = BASE_GREEN_MS + (unsigned long)(vehicles * 2000.0);
return constrain(adaptive, MIN_GREEN_MS, MAX_GREEN_MS);
}
void setLights(uint8_t lane, bool green, bool yellow, bool red) {
digitalWrite(GREEN_PINS[lane], green ? HIGH : LOW);
digitalWrite(YELLOW_PINS[lane], yellow ? HIGH : LOW);
digitalWrite(RED_PINS[lane], red ? HIGH : LOW);
}
void setAllRed() {
for (uint8_t i = 0; i < 4; ++i) {
setLights(i, false, false, true);
}
}
// -------- Main cycle per lane --------
void serveLane(uint8_t lane) {
// Update sensor for current lane
updateSensor(lane);
unsigned long greenTime = calculateGreenTime(lane);
// 1) All red for safety
setAllRed();
delay(ALL_RED_MS);
// 2) Green on current lane, red on others
for (uint8_t i = 0; i < 4; ++i) {
if (i == lane) {
setLights(i, true, false, false);
} else {
setLights(i, false, false, true);
}
}
// Buzz only ONCE when green turns on AND vehicle detected
if (lanes[lane].queueEstimate > 0) {
buzz(200); // short beep
}
unsigned long start = millis();
while (millis() - start < greenTime) {
updateSensor(lane);
delay(LOOP_DELAY_MS);
}
// 3) Yellow on current lane, red on others
for (uint8_t i = 0; i < 4; ++i) {
if (i == lane) {
setLights(i, false, true, false);
} else {
setLights(i, false, false, true);
}
}
buzz(150);
delay(YELLOW_MS);
// 4) Back to red on current lane (others already red)
setLights(lane, false, false, true);
}
// -------- Setup & loop --------
void setup() {
for (uint8_t i = 0; i < 4; ++i) {
pinMode(GREEN_PINS[i], OUTPUT);
pinMode(YELLOW_PINS[i], OUTPUT);
pinMode(RED_PINS[i], OUTPUT);
// Initialize with red ON
digitalWrite(GREEN_PINS[i], LOW);
digitalWrite(YELLOW_PINS[i], LOW);
digitalWrite(RED_PINS[i], HIGH);
pinMode(TRIGGER_PINS[i], OUTPUT);
pinMode(ECHO_PINS[i], INPUT);
digitalWrite(TRIGGER_PINS[i], LOW);
for (uint8_t j = 0; j < SMOOTHING_SAMPLES; ++j)
lanes[i].distances[j] = MAX_DIST_MM;
}
pinMode(BUZZER_PIN, OUTPUT);
digitalWrite(BUZZER_PIN, LOW);
[Link](115200);
delay(1000);
[Link](F("Traffic signal controller initialized"));
}
void loop() {
static uint8_t currentLane = 0;
serveLane(currentLane);
currentLane = (currentLane + 1) % 4;
}