2

When i was testing out a program I found a strange behavior of esp8266

It seems to get out of a while loop even when there's no option of getting out on code

I don't know if these are related but here's the code (the program is just two different visual patterns of leds toggled by a button)

#define led1 D0
#define led2 D1
#define led3 D2
#define led4 D3
#define button D7

unsigned long pressedButton;
bool change = 0;
unsigned long previousTime;
unsigned int difference;


void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(button, INPUT_PULLUP);
}

void loop(){
  digitalWrite(led1, LOW);
  digitalWrite(led2, LOW);
  digitalWrite(led3, LOW);         //when the while loop change, this should delete interference
  digitalWrite(led4, LOW);
  previousTime = millis();
  
  while (!change){                                      //default visual pattern of leds
    difference = millis()-previousTime;
    
    if (!digitalRead(led1) && difference>=200){
      digitalWrite(led1, HIGH);
    }
    if (!digitalRead(led2) && difference>=400){
      digitalWrite(led2, HIGH);
    }
    if (!digitalRead(led3) && difference>=600){
      digitalWrite(led3, HIGH);
    }
    if (!digitalRead(led4) && difference>=800){         //after here, all the leds should be HIGH
      digitalWrite(led4, HIGH);
    }
    if (digitalRead(led4) && difference>=1000){
      digitalWrite(led4, LOW);
    }
    if (digitalRead(led3) && difference>=1200){
      digitalWrite(led3, LOW);
    }
    if (digitalRead(led2) && difference>=1400){
      digitalWrite(led2, LOW);
    }
    if (digitalRead(led1) && difference>=1600){        //after here, all the leds should be LOW
      digitalWrite(led1, LOW);
      previousTime = millis();
    }
    
    if (!digitalRead(button) && millis()-pressedButton>200){       //check if button was pressed to break while loop
      pressedButton = millis();
      break;
    }
  }

  
  while (change){                                         //alternative of visual pattern of leds
    difference = millis()-previousTime;
    
    if (!digitalRead(led1) && difference>=200){
      digitalWrite(led1, HIGH);
      digitalWrite(led4, HIGH);
      digitalWrite(led2, LOW);
      digitalWrite(led3, LOW);
    }
    if (digitalRead(led1) && difference>=400){
      digitalWrite(led1, LOW);
      digitalWrite(led4, LOW);
      digitalWrite(led2, HIGH);
      digitalWrite(led3, HIGH);
      previousTime = millis();
    }

    //if (!digitalRead(button) && millis()-pressedButton>=200){     //check if button was pressed to break while loop
    //  pressedButton = millis();
    //  break;
    //}
  }
  
  change = !change;         //after a break in one of the while loops, this will make the program go to the other while loop
 }

Is there something wrong with the code? Here is a link of a video of the behavior for more details https://drive.google.com/file/d/1822MHNGQn-A2-HGHhRXz_8xydz-wM4Ha/view?usp=sharing

6
  • You can't trap an ESP in a while loop like that. There are things it needs to get back to main and do between loops. Instead, let the loop function be your loop. Make the while statements if statements and where you have break, that's where you change the change variable. Put the code at the top in an if statement that checks to see if change has changed.
    – Delta_G
    Commented Jul 11, 2023 at 21:59
  • @Delta_G Please make an answer and not a comment.
    – Nick Gammon
    Commented Jul 12, 2023 at 5:04
  • Concerning your LED issue: Even if it happens with your current sketch, please post a separate question for it. When you do, please add a schematic of your circuit. Commented Jul 12, 2023 at 7:13
  • 1
    @NickGammon. Done.
    – Delta_G
    Commented Jul 12, 2023 at 16:54
  • @the busybee all right I didn't know the problems were not related. Like that? arduino.stackexchange.com/questions/93807/…
    – tatu101
    Commented Jul 13, 2023 at 23:13

1 Answer 1

2

You can't trap an ESP in a while loop like that. There are things it needs to get back to main and do between loops. Instead, let the loop function be your loop. Make the while statements if statements and where you have break, that's where you change the change variable. Put the code at the top in an if statement that checks to see if change has changed.

#define led1 D0
#define led2 D1
#define led3 D2
#define led4 D3
#define button D7

unsigned long pressedButton;
bool change = 0;
bool oldChange = 1;
unsigned long previousTime;
unsigned int difference;


void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(button, INPUT_PULLUP);
}

void loop() {
  if (change != oldChange) {
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);  //when the while loop change, this should delete interference
    digitalWrite(led4, LOW);
    previousTime = millis();
    oldChange = change;
  }

  if (!change) {  //default visual pattern of leds
    difference = millis() - previousTime;

    if (!digitalRead(led1) && difference >= 200) {
      digitalWrite(led1, HIGH);
    }
    if (!digitalRead(led2) && difference >= 400) {
      digitalWrite(led2, HIGH);
    }
    if (!digitalRead(led3) && difference >= 600) {
      digitalWrite(led3, HIGH);
    }
    if (!digitalRead(led4) && difference >= 800) {  //after here, all the leds should be HIGH
      digitalWrite(led4, HIGH);
    }
    if (digitalRead(led4) && difference >= 1000) {
      digitalWrite(led4, LOW);
    }
    if (digitalRead(led3) && difference >= 1200) {
      digitalWrite(led3, LOW);
    }
    if (digitalRead(led2) && difference >= 1400) {
      digitalWrite(led2, LOW);
    }
    if (digitalRead(led1) && difference >= 1600) {  //after here, all the leds should be LOW
      digitalWrite(led1, LOW);
      previousTime = millis();
    }

    if (!digitalRead(button) && millis() - pressedButton > 200) {  //check if button was pressed to break while loop
      pressedButton = millis();
      change = true;
    }
  }


  if (change) {  //alternative of visual pattern of leds
    difference = millis() - previousTime;

    if (!digitalRead(led1) && difference >= 200) {
      digitalWrite(led1, HIGH);
      digitalWrite(led4, HIGH);
      digitalWrite(led2, LOW);
      digitalWrite(led3, LOW);
    }
    if (digitalRead(led1) && difference >= 400) {
      digitalWrite(led1, LOW);
      digitalWrite(led4, LOW);
      digitalWrite(led2, HIGH);
      digitalWrite(led3, HIGH);
      previousTime = millis();
    }
  }

  change = false  
}
2
  • Thank you! That resolved the unwanted break on the second pattern. But what is the reason for the while loop not working inside another loop?
    – tatu101
    Commented Jul 13, 2023 at 18:47
  • The loop function is called repeatedly from main(). There are other things in main() that have to happen in between calls to loop. You can't trap execution inside loop. You have to let loop exit once in a while or call yield or delay(0). In your case, you didn't need a while loop since loop is already a loop.
    – Delta_G
    Commented Jul 14, 2023 at 3:28

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.