/*
Project: Traffic Light
Description: Just your basic traffic light...
Creation date: 10/3/22
Author: AnonEngineering
License: Beerware
*/
// Constants
// LED pins, a pair of Red, Yellow, and Green LEDs for "North & South",
// another set of pairs for "East & West". (Two LEDs and resistors per pin.)
const byte NS_RED_PIN = 5; const byte NS_YEL_PIN = 6; const byte NS_GRN_PIN = 7;
const byte EW_RED_PIN = 4; const byte EW_YEL_PIN = 3; const byte EW_GRN_PIN = 2;
// Crosswalk buttons
const byte NS_BTN_PIN = 8;
const byte EW_BTN_PIN = 9;
// Optional buzzer (not implemented here)
//const byte buzzer = 10;
// State constants
const byte NUM_STATES = 6; // States = 0 to 5, (6 total)
// State delay array, EW go, EW caution, All stop, NS go, NS caution, All stop
const long STATE_DELAY[NUM_STATES] = {10000, 2000, 1000, 10000, 2000, 1000};
// Light array
const bool LIGHT_ARR[][NUM_STATES] = {
{false, false, true, true, false, false}, // state "1" (0 actually)
{false, false, true, false, true, false}, // state "2"
{false, false, true, false, false, true}, // state "3"
{true, false, false, false, false, true}, // state "4"
{false, true, false, false, false, true}, // state "5"
{false, false, true, false, false, true} // state "6"
};
// Globals
// Stores state variable
byte currState = 0;
// Stores last time state changed
unsigned long lastMillis = 0;
// Flags for pedestrian requests
bool nsFlag = false;
bool ewFlag = false;
void checkButtons() {
// Button handling bools
static bool btnNSState = 0;
static bool lastNSBtnState = 0;
static bool btnEWState = 0;
static bool lastEWBtnState = 0;
// Read the NS pedestrian pushbutton input pin
btnNSState = digitalRead(NS_BTN_PIN);
// check if the button is pressed or released
// by comparing the buttonState to its previous state
if (btnNSState != lastNSBtnState) {
if (btnNSState == 0) {
Serial.println(F("NS Crosswalk request!"));
nsFlag = true;
}
// remember the current state of the button
lastNSBtnState = btnNSState;
// add a small debounce delay
delay(20);
}
// Read the EW pedestrian pushbutton input pin
btnEWState = digitalRead(EW_BTN_PIN);
// check if the button is pressed or released
// by comparing the buttonState to its previous state
if (btnEWState != lastEWBtnState) {
if (btnEWState == 0) {
Serial.println(F("EW Crosswalk request!"));
ewFlag = true;
}
// remember the current state of the button
lastEWBtnState = btnEWState;
// add a small debounce delay
delay(20);
}
}
void checkFlags(unsigned long currTime) {
// Handle pedestrian flags
// If nsFlag is set and NS traffic isn't already allowed
if (nsFlag && (currState != 2 && currState != 3)) {
currState = 1; // Set EW to caution and continue
lastMillis = currTime; // Reset delay time
}
nsFlag = false; // Always set false, either the mode changed or didn't need to
// If ewFlag is set and EW traffic isn't already allowed
if (ewFlag && (currState != 0 && currState != 1)) {
currState = 4; // Set NS to caution and continue
lastMillis = currTime; // Reset delay time
}
ewFlag = false; // Always set false, either the mode changed or didn't need to
}
void setLights() {
// Set all six lights according to the current state
digitalWrite(NS_GRN_PIN, LIGHT_ARR[currState][0]);
digitalWrite(NS_YEL_PIN, LIGHT_ARR[currState][1]);
digitalWrite(NS_RED_PIN, LIGHT_ARR[currState][2]);
digitalWrite(EW_GRN_PIN, LIGHT_ARR[currState][3]);
digitalWrite(EW_YEL_PIN, LIGHT_ARR[currState][4]);
digitalWrite(EW_RED_PIN, LIGHT_ARR[currState][5]);
}
void setState(unsigned long currTime) {
// Increment the state of the traffic light
// Using an array to avoid code block repetition
for (byte i = 0; i < NUM_STATES; i++) {
// Iterate through all the states
if (currState == i) {
if (currTime - lastMillis >= STATE_DELAY[i]) {
// Update lastMillis & state.
lastMillis = currTime;
currState++;
// Reset state to starting point if at the end
if (currState >= NUM_STATES) currState = 0;
Serial.print(F("State "));
Serial.println(currState + 1); // +1 so it prints 1 - 6
}
}
}
}
void setup() {
Serial.begin(115200);
// Set pinModes
pinMode(NS_BTN_PIN, INPUT_PULLUP); pinMode(EW_BTN_PIN, INPUT_PULLUP);
pinMode(NS_GRN_PIN, OUTPUT); pinMode(NS_YEL_PIN, OUTPUT); pinMode(NS_RED_PIN, OUTPUT);
pinMode(EW_GRN_PIN, OUTPUT); pinMode(EW_YEL_PIN, OUTPUT); pinMode(EW_RED_PIN, OUTPUT);
//pinMode(buzzer, OUTPUT);
// Startup message
Serial.println(F("Starting, drive carefully..."));
Serial.print(F("State "));
Serial.println(currState + 1); // Print state + 1 (for fun, instead of 0)
}
void loop() {
// Get current millis every time through loop
unsigned long curMillis = millis();
// These functions run continuously and quickly (about every 40mS)
checkButtons();
checkFlags(curMillis);
setLights();
setState(curMillis);
}