ESP8266, похоже, убивает цикл while

Когда я тестировал программу, я обнаружил странное поведение esp8266

Похоже, что цикл while выходит из цикла, даже если нет возможности выйти из кода

Я не знаю, связаны ли они, но вот код (программа представляет собой два разных визуальных шаблона светодиодов, переключаемых кнопкой)

#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);         //при изменении цикла while это должно удалить помехи
  digitalWrite(led4, LOW);
  previousTime = millis();
  
  while (!change){                                      //визуальный шаблон светодиодов по умолчанию
    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){         //после этого все светодиоды должны быть ВЫСОКИМ
      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){        //после этого все светодиоды должны быть НИЗКИМИ
      digitalWrite(led1, LOW);
      previousTime = millis();
    }
    
    if (!digitalRead(button) && millis()-pressedButton>200){       //проверяем, была ли нажата кнопка, чтобы прервать цикл while
      pressedButton = millis();
      break;
    }
  }

  
  while (change){                                         //альтернативный вариант визуального оформления светодиодов
    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){ //проверяем, была ли нажата кнопка, чтобы прервать цикл while
    // нажатая кнопка = millis();
    // перерыв;
    //}
  }
  
  change = !change;         //после перерыва в одном из циклов while программа перейдет к другому циклу while
 }

Что-то не так с кодом? Вот ссылка на видео поведения для более подробной информации. https://drive.google.com/file/d/1822MHNGQn- A2-HGHhRXz_8xydz-wM4Ha/view?usp=sharing

, 👍2

Обсуждение

Вы не можете поймать ESP в цикле while таким образом. Есть вещи, которые ему нужно вернуться в основной режим и выполнить между циклами. Вместо этого пусть функция цикла будет вашим циклом. Сделайте операторы while, если операторы и где у вас есть перерыв, вы меняете переменную изменения. Поместите код вверху в оператор if, который проверяет, изменились ли изменения., @Delta_G

@Delta_G Пожалуйста, ответьте, а не комментируйте., @Nick Gammon

Что касается вашей проблемы со светодиодом: даже если это произойдет с вашим текущим скетчом, задайте по этому поводу отдельный вопрос. Когда вы это сделаете, пожалуйста, добавьте схему вашей цепи., @the busybee

@NickGammon. Сделанный., @Delta_G

@the busybee, ладно, я не знал, что проблемы не связаны между собой. Как это? https://arduinoprosto.ru/q/93807/led-doesnt-completely-turn-off-with-digitalwriteled-low, @tatu101

Точно. И у вас уже есть ответ., @the busybee


1 ответ


Лучший ответ:

2

Вы не можете поймать ESP в цикле while таким образом. Есть вещи, которые ему нужно вернуться в основной режим и выполнить между циклами. Вместо этого пусть функция цикла будет вашим циклом. Сделайте операторы while, если операторы и где у вас есть перерыв, вы меняете переменную изменения. Поместите код вверху в оператор if, который проверяет, изменились ли изменения.

#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);  //при изменении цикла while это должно удалить помехи
    digitalWrite(led4, LOW);
    previousTime = millis();
    oldChange = change;
  }

  if (!change) {  //визуальный шаблон светодиодов по умолчанию
    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) {  //после этого все светодиоды должны быть ВЫСОКИМ
      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) {  //после этого все светодиоды должны быть НИЗКИМИ
      digitalWrite(led1, LOW);
      previousTime = millis();
    }

    if (!digitalRead(button) && millis() - pressedButton > 200) {  //проверяем, была ли нажата кнопка, чтобы прервать цикл while
      pressedButton = millis();
      change = true;
    }
  }


  if (change) {  //альтернатива визуального оформления светодиодов
    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  
}
,

Спасибо! Это устранило нежелательный разрыв второго паттерна. Но в чем причина того, что цикл while не работает внутри другого цикла?, @tatu101

Функция цикла неоднократно вызывается из main(). В main() есть и другие вещи, которые должны происходить между вызовами цикла. Вы не можете перехватить выполнение внутри цикла. Вам нужно время от времени прерывать цикл или вызывать метод yield или Delay(0). В вашем случае вам не нужен цикл while, поскольку цикл уже является циклом., @Delta_G