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
}
}
1 Answer 1
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
}
-
Your Wokwi link is broken.Russell McMahon– Russell McMahon2024年02月08日 09:00:56 +00:00Commented Feb 8, 2024 at 9:00
-
-
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).Russell McMahon– Russell McMahon2024年02月08日 22:24:52 +00:00Commented 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 NRF24L01jsotola– jsotola2024年02月08日 23:37:56 +00:00Commented Feb 8, 2024 at 23:37