#include <EEPROM.h>
// Define pin numbers for LEDs and buttons
const int redPin = 13;
const int yellowPin = 12;
const int greenPin = 11;
const int pedestrianButtonPin = 2;
const int modeButtonPin = 3;
const int buzzerPin = 9;
// Variables to store state
int currentState = 0;
unsigned long lastStateChangeTime = 0;
boolean pedestrianButtonPressed = false;
String currentMode = "Normal";
// Debounce variables
unsigned long lastDebounceTimePedestrian = 0;
unsigned long lastDebounceTimeMode = 0;
const unsigned long debounceDelay = 200; // Debounce time in milliseconds
// Function prototypes
void changeState(int newState); // Change the state of the traffic light
void blinkLED(int pin, int times, int delayTime); // Blink an LED a specified number of times with a delay
void countdown(int ledPin, int duration, const char* color); // Countdown with an LED for a specified duration
void normalModeOperation(); // Operation logic for normal mode
void rushHourModeOperation(); // Operation logic for rush hour mode
void nightModeOperation(); // Operation logic for night mode
void pulseLight(int pin); // Pulse the light on a specified pin
String getTrafficLightState(); // Get the current state of the traffic light
String getModeName(); // Get the current mode name
void printDebugInfo(); // Print debug information
void saveCurrentMode(); // Save the current mode to EEPROM
void loadCurrentMode(); // Load the current mode from EEPROM
void playPedestrianCrossingSound(); // Play sound for pedestrian crossing
void playModeChangeSound(); // Play sound for mode change
void handleError(); // Handle errors by resetting to a known state
void pedestrianButtonPush(); // Handle pedestrian button press
void toggleMode(); // Toggle between traffic light modes
void setup() {
// Initialize LED pins as outputs
pinMode(redPin, OUTPUT);
pinMode(yellowPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(buzzerPin, OUTPUT);
// Initialize button pins as inputs with pull-up resistors
pinMode(pedestrianButtonPin, INPUT_PULLUP);
pinMode(modeButtonPin, INPUT_PULLUP);
// Attach interrupts for buttons
attachInterrupt(digitalPinToInterrupt(pedestrianButtonPin), pedestrianButtonPush, FALLING);
attachInterrupt(digitalPinToInterrupt(modeButtonPin), toggleMode, FALLING);
// Initialize serial communication
Serial.begin(9600);
Serial.println("Traffic Light Simulator Started");
// Load the saved mode from EEPROM
loadCurrentMode();
}
void loop() {
unsigned long currentTime = millis();
if (currentMode == "Night") {
nightModeOperation();
} else if (currentMode == "Rush Hour") {
rushHourModeOperation();
} else {
normalModeOperation();
}
// Print debug information every second
static unsigned long lastDebugTime = 0;
if (currentTime - lastDebugTime >= 1000) {
printDebugInfo();
lastDebugTime = currentTime;
}
}
void normalModeOperation() {
switch (currentState) {
case 0: // Green light
countdown(greenPin, 10, "Green");
changeState(1);
break;
case 1: // Yellow light
countdown(yellowPin, 3, "Yellow");
changeState(2);
break;
case 2: // Red light
countdown(redPin, 7, "Red");
changeState(0);
break;
default:
handleError();
break;
}
}
void rushHourModeOperation() {
switch (currentState) {
case 0: // Green light
countdown(greenPin, 12, "Green");
changeState(1);
break;
case 1: // Yellow light
countdown(yellowPin, 2, "Yellow");
changeState(2);
break;
case 2: // Red light
countdown(redPin, 6, "Red");
changeState(0);
break;
default:
handleError();
break;
}
}
void nightModeOperation() {
digitalWrite(redPin, LOW); // Ensure the red LED is off
digitalWrite(greenPin, LOW); // Ensure the green LED is off
pulseLight(yellowPin); // Apply the pulsing effect to the yellow LED
}
void changeState(int newState) {
currentState = newState;
lastStateChangeTime = millis();
Serial.print("Changing to ");
Serial.println(getTrafficLightState());
}
void countdown(int ledPin, int duration, const char* color) {
for (int i = duration; i > 0; i--) {
digitalWrite(ledPin, HIGH);
Serial.print(color);
Serial.print(" light will be on for ");
Serial.print(i);
Serial.println(" more seconds.");
delay(1000);
digitalWrite(ledPin, LOW);
}
}
void pulseLight(int pin) {
// Gradually increase the brightness
for (int brightness = 0; brightness <= 255; brightness++) {
analogWrite(pin, brightness); // Set the brightness
delay(5); // Adjust this delay to control the speed of the fade
}
// Gradually decrease the brightness
for (int brightness = 255; brightness >= 0; brightness--) {
analogWrite(pin, brightness); // Set the brightness
delay(5); // Adjust this delay to control the speed of the fade
}
}
String getTrafficLightState() {
switch (currentState) {
case 0: return "Green";
case 1: return "Yellow";
case 2: return "Red";
default: return "Unknown";
}
}
String getModeName() {
return currentMode;
}
void printDebugInfo() {
String stateInfo = "State: " + getTrafficLightState();
String modeInfo = "Mode: " + getModeName();
String timeInfo = "Time in state: " + String(millis() - lastStateChangeTime) + "ms";
Serial.println(stateInfo + " | " + modeInfo + " | " + timeInfo);
}
void saveCurrentMode() {
EEPROM.write(0, currentMode[0]);
}
void loadCurrentMode() {
char modeChar = EEPROM.read(0);
if (modeChar == 'N') {
currentMode = "Normal";
} else if (modeChar == 'I') {
currentMode = "Night";
} else if (modeChar == 'R') {
currentMode = "Rush Hour";
}
}
void playPedestrianCrossingSound() {
tone(buzzerPin, 1000, 500);
delay(500);
}
void playModeChangeSound() {
tone(buzzerPin, 500, 250);
delay(250);
tone(buzzerPin, 1000, 250);
delay(250);
}
void handleError() {
Serial.println("Error: Invalid state detected! Resetting to green light state.");
currentState = 0;
lastStateChangeTime = millis();
}
void pedestrianButtonPush() {
unsigned long currentDebounceTime = millis();
if (currentDebounceTime - lastDebounceTimePedestrian > debounceDelay) {
pedestrianButtonPressed = true;
Serial.println("Pedestrian button pressed!");
playPedestrianCrossingSound();
lastDebounceTimePedestrian = currentDebounceTime;
}
}
void toggleMode() {
unsigned long currentDebounceTime = millis();
if (currentDebounceTime - lastDebounceTimeMode > debounceDelay) {
if (currentMode == "Normal") {
currentMode = "Night";
} else if (currentMode == "Night") {
currentMode = "Rush Hour";
} else {
currentMode = "Normal";
}
playModeChangeSound();
saveCurrentMode();
Serial.print("Switched to ");
Serial.print(currentMode);
Serial.println(" mode");
lastDebounceTimeMode = currentDebounceTime;
// Reset the traffic light state immediately upon mode change
currentState = 0;
lastStateChangeTime = millis();
}
}