1

I was emulating the pedestrian traffic light cyclic pattern (red, green, green flashing) in the next Arduino code. But when I run this code with my ESP8266 Wemos D1 mini controller, it appears the pattern (red, red and (green flashing) at the same time, green). I do not know why this strange pattern appeared and I was trying to fix it, but I did not get anything. How to fix this code to replicate the (red, green, green flashing) sequence pattern?

// Define pin assignments
const int redLED = D1;
const int greenLED = D2;
const int pedestrianButton = D3;
const int potentiometer = A0;
// Define variables
unsigned long lastStateChangeTime = 0;
unsigned long greenFlashingDuration = 3000; // 3 seconds
unsigned long redGreenDuration = 5000; // Initial duration
bool pedestrianRequest = false;
void setup() {
 // Initialize pins
 pinMode(greenLED, OUTPUT);
 pinMode(redLED, OUTPUT);
 pinMode(pedestrianButton, INPUT_PULLUP);
 attachInterrupt(digitalPinToInterrupt(pedestrianButton), pedestrianInterrupt, FALLING);
}
void loop() {
 updateTiming(); // Read potentiometer/LDR and update timings
 manageTrafficLights(); // Manage traffic light states
}
void manageTrafficLights() {
 unsigned long currentTime = millis();
 if (pedestrianRequest==true) {
 // Pedestrian request prioritized
 digitalWrite(greenLED, HIGH);
 digitalWrite(redLED, LOW);
 
 pedestrianRequest = false;
 }
 
 // Determine the state based on the timing
 
 if ( (currentTime-lastStateChangeTime) >= (2 * redGreenDuration) ) {
 lastStateChangeTime = currentTime; // Reset cycle
 }
 else {
 if ( (currentTime-lastStateChangeTime) < redGreenDuration ) {
 digitalWrite(greenLED, LOW);
 digitalWrite(redLED, HIGH); // Red state
 } else if ( (currentTime-lastStateChangeTime) < (2*redGreenDuration-greenFlashingDuration) ) {
 digitalWrite(redLED, LOW);
 digitalWrite(greenLED, HIGH); // Green state
 } else {
 digitalWrite(redLED, LOW);
 
 if ( ( (currentTime-lastStateChangeTime) >= (2*redGreenDuration-greenFlashingDuration) ) 
 && ( (currentTime-lastStateChangeTime) % (greenFlashingDuration/3) < (greenFlashingDuration/6) ) ){
 digitalWrite(greenLED, LOW);
 } else {
 digitalWrite(greenLED, HIGH);
 }
 
 }
 }
 
}
void updateTiming() {
 // Read potentiometer/LDR values and map to timings
 // Update redGreenDuration and greenFlashingDuration accordingly
 redGreenDuration = map(analogRead(potentiometer), 0, 1023, 5000, 10000);
}
void pedestrianInterrupt() {
 pedestrianRequest = true;
 // Quickly change to green if in red state
 if (digitalRead(redLED) == HIGH) {
 digitalWrite(greenLED, HIGH);
 digitalWrite(redLED, LOW);
 lastStateChangeTime = millis(); // Reset the cycle
 }
 
}
asked Feb 7, 2024 at 16:39

1 Answer 1

2

Here is some simplified example code that might be useful to you.

It keeps the logic and the LED control separated by the use of flags.

Simulation is at https://wokwi.com/projects/389132610627050497


// 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/389127817478781953
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]; // setup 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]; // setup 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
}
answered Feb 8, 2024 at 3:52
4
  • Your Wokwi link is broken. Commented Feb 8, 2024 at 9:00
  • @RussellMcMahon I tested the link on multiple devices, none of which were logged into Wokwi ... they all worked ... are you able to reach wokwi.com ? Commented Feb 8, 2024 at 17:08
  • It works for me now. I was able to access Wokwi. I tried accessing it only a few minutes after you posted the link. Mayhaps there was some setup time. || They need an NRF24L01 peripheral, or better still, a mesh of them :-). (That would be useful to me at present). Commented Feb 8, 2024 at 22:24
  • @RussellMcMahon they have a "custom chip" available ... it can be programmed with C++, Rust and Verilog ... perhaps it could be made to emulate an NRF24L01 Commented Feb 8, 2024 at 23:37

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.