#define NUMELEMENTS(x) (sizeof(x) / sizeof(x[0]))
#define ISPRESSED LOW ///< Define the state of a pressed button as LOW
enum StateNames {
//stOff,
stBlink,
stRR,
stGR,
stX,
stOR,
stRR1,
stRG,
stRB,
stRR2,
};
struct Button {
const uint8_t pin; ///< The Arduino pin connected to the button
unsigned long lastDebounceTime; ///< The last time the button state changed
uint8_t lastButtonState; ///< The last known state of the button (before debouncing)
//
uint8_t currDebouncedState; ///< The current debounced state of the button
uint8_t prevDebouncedState; ///< The previous debounced state of the button
};
Button buttonList[] = {
{ 4, 0, !ISPRESSED, !ISPRESSED, !ISPRESSED },
{ 2, 0, !ISPRESSED, !ISPRESSED, !ISPRESSED },
};
uint32_t debounceDelay = 20;
byte potPin = A3;
int potValue;
bool setTimer_flash = false;
bool setTimer_loop = true;
int interval_loop = 5000;
int interval_flash = 1000;
int lastTimePressed ;
// verkeerslichten pins
uint8_t pinsTL[] = { 8, 7, 6 };
// voetgangers lichten pins
uint8_t pinsPL[] = { 12, 11 };
void clearCurrentState(bool lights = true);
void setup() {
// Serial monitor aanzetten
Serial.begin(115200);
setTimer_flash = true;
setTimer_loop = true;
// de mode zetten voor de verkeerslichten
for (uint8_t cnt = 0; cnt < NUMELEMENTS(pinsTL); cnt++) {
pinMode(pinsTL[cnt], OUTPUT);
}
// de mode zetten voor de voetgangerslichten
for (uint8_t cnt = 0; cnt < NUMELEMENTS(pinsPL); cnt++) {
pinMode(pinsPL[cnt], OUTPUT);
}
// de mode zetten voor de twee buttons
for (uint8_t cnt = 0; cnt < NUMELEMENTS(buttonList); cnt++) {
pinMode(buttonList[cnt].pin, INPUT_PULLUP);
}
}
void loop() {
static StateNames currentState = stBlink;
potValue = analogRead(potPin);
readButton();
switch (currentState) {
case stBlink:
/*
Verkeerslicht knippert oranje.
Voetgangerslicht uit (?).
Als het avond is blijven we hier.
Als het dag is blijven we hier voor 5 seconden en gaan naar stRR.
*/
if (potValue < 400) { // if it is night
interval_loop = 3000; // the interval is set to 3 seconds
if (timer_loop(interval_loop)) { // if the interval is over
Serial.print(millis());
Serial.println(F(" Switching to stRR"));
currentState = stRR; // set the new state on Red for all
allLightsOff(); // set all lights off
return;
}
}
if (timer_flash(interval_flash)) { // totdat the blink interval is over
int status = digitalRead(pinsTL[1]); // read if the orange led is on or off
Serial.print(millis());
Serial.print(F(" Blink "));
Serial.println(status);
digitalWrite(pinsTL[1], !status); // set the led on if it is off and off when its on
}
break;
case stRR:
/*
Verkeerslicht op rood.
Voetgangerslicht op rood.
Als het avond is geworden gaan we naar stBlink.
Anders als het tijd is gaan we naar stGR.
*/
Serial.print(millis());
Serial.println(F(" Red light on for cars. Red light for pediatrans"));
digitalWrite(pinsTL[0], HIGH); // Red Light for cars
digitalWrite(pinsPL[0], HIGH); // Red light for pediatrans.
currentState = nextState(stGR, currentState, 5000); // set the next state on Green for cars and red for pediatrans
break;
case stGR:
/*
Hier staat de auto verkeerslicht op groen zodat de auto's kunnen rijden en het
verkeerslicht voor de voetgangers op rood.
Zodra één van de knoppen van de voetgangerslichten is ingedrukt gaan we naar stX.
*/
Serial.print(millis());
Serial.println(F(" Green light on for cars. Red light for pediatrans"));
digitalWrite(pinsTL[2], HIGH); // Groen Light for cars
digitalWrite(pinsPL[0], HIGH); // Red light for pediatrans.
if (buttonList[0].currDebouncedState == ISPRESSED || buttonList[1].currDebouncedState == ISPRESSED) {
currentState = stX ;
clearCurrentState(false);
lastTimePressed = millis();
}
break;
case stX:
/*
Geen verandering in lichten.
Als een voetgangerscyclus niet recentelijk was gedaan (bv laatste 120 seconden) gaan we naar stOR.
Anders wachten we 120 seconden en gaan naar stOR; dit voorkoomt dat motorvoertuigen geen kans krijgen.
In deze stap moet je bijhouden wanneer deze de laatste keer was aangeroepen.
*/
interval_loop = 4000;
if (millis() - lastTimePressed > 4000) {
currentState = stOR;
clearCurrentState();
} else {
if (timer_loop(interval_loop)) {
currentState = stOR;
clearCurrentState();
}
}
break;
case stOR:
/*
Verkeerslicht op oranje.
Voetgangerslicht op rood.
Wacht 30 seconden en ga naar stRR1.
*/
Serial.print(millis());
Serial.println(F(" orange light on for cars. Red light for pediatrans"));
digitalWrite(pinsTL[1], HIGH); // orange Light for cars
digitalWrite(pinsPL[0], HIGH); // Red light for pediatrans.
currentState = nextState(stRR1, currentState, 3000); // set the next state on Green for cars and red for pediatrans
clearCurrentState();
break;
case stRR1:
/*
Verkeerslicht op rood.
Voetgangerslicht op rood.
Wacht 30 seconden en ga naar stRG.
*/
Serial.print(millis());
Serial.println(F(" red light on for cars. Red light for pediatrans"));
digitalWrite(pinsTL[0], HIGH); // red Light for cars
digitalWrite(pinsPL[0], HIGH); // Red light for pediatrans.
currentState = nextState(stRG, currentState, 3000);
clearCurrentState();
break;
case stRG:
/*
Hier staat het verkeerslicht voor de auto's op rood en de voetgangers op groen.
Zodra de tijd om is, ga naar stRB
*/
Serial.print(millis());
Serial.println(F(" red light on for cars. green light for pediatrans"));
digitalWrite(pinsTL[0], HIGH); // red Light for cars
digitalWrite(pinsPL[1], HIGH); // green light for pediatrans.
currentState = nextState(stRB, currentState, 3000);
clearCurrentState();
break;
case stRB:
/*
Hier gaat het groene verkeerslicht voor de voetgangers aan en uit per seconde om de voetgangers
te waarschuwen dat het licht bijna op rood springt.
Zodra de tijd om is, ga naar RR2
*/
interval_loop = 6000; // the interval is set to 3 seconds
if (timer_loop(interval_loop)) { // if the interval is over
Serial.print(millis());
Serial.println(F(" Switching to stRR2"));
currentState = stRR2; // set the new state on Red for all
allLightsOff(); // set all lights off
return;
}
if (timer_flash(interval_flash)) { // totdat the blink interval is over
int status = digitalRead(pinsPL[1]); // read if the orange led is on or off
Serial.print(millis());
Serial.print(F(" Blink "));
Serial.println(status);
digitalWrite(pinsPL[1], !status); // set the led on if it is off and off when its on
}
break;
case stRR2:
/*
Hier staan alle lichten op rood.
Als het avond is geworden gaan we naar stBlink.
Anders als het tijd is gaan we naar stGR.
*/
Serial.print(millis());
Serial.println(F(" red light on for cars. Red light for pediatrans"));
digitalWrite(pinsTL[0], HIGH); // red Light for cars
digitalWrite(pinsPL[0], HIGH); // red light for pediatrans.
currentState = nextState(stGR, currentState, 3000);
clearCurrentState();
break;
}
}
void clearCurrentState(bool lights)
{
setTimer_flash = true;
setTimer_loop = true;
if (lights == true)
{
allLightsOff();
}
}
StateNames nextState(StateNames nextState, StateNames currentState, int nextInterval)
{
if (potValue > 400)
{
Serial.print(millis());
Serial.println(F(" Switching to stBlink"));
currentState = stBlink;
setTimer_flash = true;
allLightsOff();
}
else
{
if (timer_loop(nextInterval))
{
currentState = nextState;
Serial.print(millis());
Serial.print(F(" Switching to next State "));
Serial.println(nextState);
setTimer_loop = true;
allLightsOff();
}
}
return currentState;
}
void allLightsOff() {
for (uint8_t cnt = 0; cnt < NUMELEMENTS(pinsTL); cnt++) {
digitalWrite(pinsTL[cnt], LOW);
}
for (uint8_t cnt = 0; cnt < NUMELEMENTS(pinsPL); cnt++) {
digitalWrite(pinsPL[cnt], LOW);
}
}
/*
Read all buttons with debounce
*/
void readButton() {
uint8_t buttonState;
for (uint8_t cnt = 0; cnt < NUMELEMENTS(buttonList); cnt++) {
buttonState = digitalRead(buttonList[cnt].pin);
if (buttonState != buttonList[cnt].lastButtonState) {
buttonList[cnt].lastDebounceTime = millis();
}
if ((millis() - buttonList[cnt].lastDebounceTime) > debounceDelay) {
buttonList[cnt].prevDebouncedState = buttonList[cnt].currDebouncedState;
buttonList[cnt].currDebouncedState = buttonState;
}
if (buttonState != buttonList[cnt].lastButtonState) {
buttonList[cnt].lastButtonState = buttonState;
};
}
}
bool timer_loop(uint32_t interval_loop) {
static uint32_t startTime; ///< Stores the start time in milliseconds
uint32_t currentMillis = millis(); ///< Get the current time in milliseconds
if (setTimer_loop) {
setTimer_loop = false;
startTime = millis();
}
if (currentMillis - startTime >= interval_loop) {
// indicate that we need to set the start time again
setTimer_loop = true;
// timer expired
return true;
}
return false; // Interval has not yet passed, return false
}
bool timer_flash(uint32_t interval_flash) {
static uint32_t startTime; ///< Stores the start time in milliseconds
uint32_t currentMillis = millis(); ///< Get the current time in milliseconds
if (setTimer_flash) {
setTimer_flash = false;
startTime = millis();
}
if (currentMillis - startTime >= interval_flash) {
// indicate that we need to set the start time again
setTimer_flash = true;
// timer expired
return true;
}
return false;
}