// https://arduino.stackexchange.com/questions/95476/fixing-a-pedestrian-traffic-light-sequence-pattern-in-a-cycle-using-millis-and-w
// for simulation, see https://wokwi.com/projects/389132610627050497
const int redLED = 2;
const int greenLED = 3;
unsigned int timeInterval [4] = { 5, 3, 4, 0}; // timers reload with these values
unsigned int timeCounter [4] = { 0, 0, 0, 0}; // these are the actual timers
//boolean reloadable [4] = {true, true, false, false}; // this determines if the timer will restart upon reaching end
// put value in <timeCounter> for oneshot event
// 3rd and 4th timers are not used in this example sketch
boolean tick [4] = {false, false, false, false}; // countdown timers flags
boolean mainTick = false;
boolean subTick = false;
boolean red = false;
boolean green = false;
boolean blink = false;
unsigned long previousMillis = 0;
void setup() {
Serial.begin(115200);
//memcpy(timeCounter, timeInterval, 4 * sizeof(long)); // preload timers
green = true; // start with green
timeCounter[0] = 1; // load the first counter
}
void loop() {
unsigned long currentMillis = millis();
// -------------------------------------------------------------------
if (currentMillis - previousMillis >= 500) { // 0.5 s tick
previousMillis = currentMillis;
subTick = !subTick; // alternate the value
if (subTick) {
mainTick = true; // 1 s tick
// Serial.println("tick"); // debugging code
for (int i = 0; i < 4; i++) { // keep track of 4 time intervals
timeCounter[i]-- ; // decrement counter
if (timeCounter[i] == 0) {
// if (reloadable[i]) timeCounter[i] = timeInterval[i]; // reached zero, reload counter if it is reloadable
tick[i] = true; // emit a "tick"
}
}
}
}
// -------------------------------------------------------------------
if (mainTick) { // 1 s tick
}
// -------------------------------------------------------------------
if (tick[0]) { //
tick[0] = false;
timeCounter[1] = timeInterval[1]; // setup the next tick
red = false; // setup flags
green = true;
blink = false;
}
// -------------------------------------------------------------------
if (tick[1]) { //
tick[1] = false; // clear flag so that code runs only once every tick
timeCounter[2] = timeInterval[2]; // setuop the next tick
red = true;
green = false;
blink = false;
}
// -------------------------------------------------------------------
if (tick[2]) { //
tick[2] = false; // clear flag so that code runs only once every tick
timeCounter[0] = timeInterval[0]; // setuop the next tick
red = false;
green = false;
blink = true;
}
// -------------------------------------------------------------------
if (mainTick) { // can have multiples of these
mainTick = false; // clear the flag in the last one
}
// -------------------------------------------------------------------
digitalWrite(redLED , red ? HIGH:LOW); // C++ ternary operator
digitalWrite(greenLED, green ? HIGH:LOW);
digitalWrite(redLED , blink && subTick? HIGH:LOW); // subTick changes every 500 ms
}
uno:A5.2
uno:A4.2
uno:AREF
uno:GND.1
uno:13
uno:12
uno:11
uno:10
uno:9
uno:8
uno:7
uno:6
uno:5
uno:4
uno:3
uno:2
uno:1
uno:0
uno:IOREF
uno:RESET
uno:3.3V
uno:5V
uno:GND.2
uno:GND.3
uno:VIN
uno:A0
uno:A1
uno:A2
uno:A3
uno:A4
uno:A5
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
led1:A
led1:C
led2:A
led2:C
gnd1:GND