const int GREEN_TRAFFIC = 13;
const int AMBER_TRAFFIC = 12;
const int RED_TRAFFIC = 11;
const int RED_PEDESTRIAN = 5;
const int GREEN_PEDESTRIAN = 6;
unsigned long timeTrafficAllowedToGo = 0;
volatile bool buttonHasBeenPressed = false;
enum States {TRAFFIC_FLOWING, TRAFFIC_STOPPING, PEDESTRIANS_CROSSING, PEDESTRIANS_CROSSING_LIMITED_TIME};
volatile States trafficState = TRAFFIC_FLOWING;
bool firstButtonPress = true;
void setup() {
const int BUTTON_INP = 3;
const int BUTTON_INT = digitalPinToInterrupt(BUTTON_INP);
const int LED_PIN_ARRAY[] = {GREEN_TRAFFIC, AMBER_TRAFFIC, RED_TRAFFIC, GREEN_PEDESTRIAN, RED_PEDESTRIAN};
for (int pin : LED_PIN_ARRAY){
pinMode(pin, OUTPUT);
}
attachInterrupt(BUTTON_INT, button_ISR, FALLING);
trafficFlowing();
}
void button_ISR(){
delayMicroseconds(5000); // to combat bouncing
if (trafficState == PEDESTRIANS_CROSSING_LIMITED_TIME || trafficState == TRAFFIC_FLOWING){
buttonHasBeenPressed = true;
}
}
}
void loop() {
const unsigned long MINIMUM_TRAFFIC_FLOW_TIME_s = 60; // has to be unsigned long, not int, or later errors with ms conversion
const unsigned long MINIMUM_TRAFFIC_FLOW_TIME_ms = MINIMUM_TRAFFIC_FLOW_TIME_s * 1000;
if (buttonHasBeenPressed == true && (millis() - timeTrafficAllowedToGo > MINIMUM_TRAFFIC_FLOW_TIME_ms || firstButtonPress == true)){
buttonHasBeenPressed = false;
firstButtonPress = false;
allowCrossing();
trafficFlowing();
}
}
void allowCrossing(){
warnTrafficToStop();
allowPedestriansToCross();
warnLimitedCrossingTimeLeft();
}
void trafficFlowing(){
trafficState = TRAFFIC_FLOWING;
timeTrafficAllowedToGo = millis();
lightsToAllowTrafficFlow();
}
void lightsToAllowTrafficFlow(){
digitalWrite(GREEN_TRAFFIC, HIGH);
digitalWrite(RED_PEDESTRIAN, HIGH);
}
void warnTrafficToStop(){
const int STOPPING_TRAFFIC_ms = 3000;
trafficState = TRAFFIC_STOPPING;
lightsToWarnTrafficToStop();
delay(STOPPING_TRAFFIC_ms);
}
void lightsToWarnTrafficToStop(){
digitalWrite(GREEN_TRAFFIC, LOW);
digitalWrite(AMBER_TRAFFIC, HIGH);
}
void allowPedestriansToCross(){
const int CROSSING_TIME_ms = 10000;
trafficState = PEDESTRIANS_CROSSING;
lightsToStopTraffic();
lightsToStartPedestrians();
delay(CROSSING_TIME_ms);
lightsToPrepareTrafficToMove();
}
void lightsToStopTraffic(){
digitalWrite(AMBER_TRAFFIC, LOW);
digitalWrite(RED_TRAFFIC, HIGH);
}
void lightsToStartPedestrians(){
digitalWrite(GREEN_PEDESTRIAN, HIGH);
digitalWrite(RED_PEDESTRIAN, LOW);
}
void lightsToPrepareTrafficToMove(){
digitalWrite(RED_TRAFFIC, LOW);
}
void warnLimitedCrossingTimeLeft(){
trafficState = PEDESTRIANS_CROSSING_LIMITED_TIME;
flashingLightsToWarnPedestrians();
}
void flashingLightsToWarnPedestrians(){
const int FLASH_PERIOD_ms = 500;
const int NUMBER_OF_FLASHES = 5;
for (int i = 0; i < NUMBER_OF_FLASHES; ++i){
digitalWrite(AMBER_TRAFFIC, HIGH);
digitalWrite(GREEN_PEDESTRIAN, HIGH);
delay(FLASH_PERIOD_ms);
digitalWrite(AMBER_TRAFFIC, LOW);
digitalWrite(GREEN_PEDESTRIAN, LOW);
delay(FLASH_PERIOD_ms);
}
}