• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь несколько условий в while цикле

enjoynering

Well-known member
добрый день.

не первый раз сталкиваюсь с такой проблемой. Arduino для esp8266 упорно игнорирует больше одного условия в цикле while

например вот такой код вызывает срабатывание wdt:
Код:
  int16_t counter = 2000;

  while ((digitalRead(_dreq) == LOW) || (counter > 0))
  {
    counter--;
    delayMicroseconds(1);
  }
а такой нет:
Код:
  int16_t counter = 2000;

  while (digitalRead(_dreq) == LOW)
  {
    counter--;
    if (counter < 0)  break;
    delayMicroseconds(1);
  }
почему????
 

tretyakov_sa

Moderator
Команда форума
добрый день.
не первый раз сталкиваюсь с такой проблемой. Arduino для esp8266 упорно игнорирует больше одного условия в цикле while почему????
Потому, что есть фоновый процесс обслуживания WI-FI кода и к нему нужно вернутся не реже определенного времени. Ваш цикл выполняется слишком долго. Возврат к обслуживанию wi-fi ядра происходит в Loop при использовании delay() или yield().
 

CodeNameHawk

Moderator
Команда форума
В первом примере выход из while только, когда оба условия будут false.
После того, как count станет < 0 выхода из цикла не будет , будет крутиться в цикле пока (digitalRead(_dreq) == LOW) не станет false, если это займет "много" времени, сработает WatchDog.

Во втором любое из условий выведет из цикла.(ну или не войдет в цикл если (digitalRead(_dreq) == LOW) false)

Tак что, Arduino ничего не игнорирует.
Попробуйте :
Код:
while ((digitalRead(_dreq) == LOW) && (counter > 0))
 
Последнее редактирование:

enjoynering

Well-known member
я думаю вы не правы насчет

Код:
while ((digitalRead(_dreq) == LOW) && (counter > 0))
&& означает что пока ОБА условия не будут TRUE цикл не прекратится.

я нашел ошибку. виной всему моя не внимательность - в конце строчки c while поставил ; и компилятор это проглотил

Код:
  int16_t counter = 2000;
  while ((digitalRead(_dreq) == LOW) || (counter > 0));
  {
    counter--;
    delayMicroseconds(1);
  }
 

CodeNameHawk

Moderator
Команда форума
&& означает что пока ОБА условия не будут TRUE цикл не прекратится.
Неправильно понимаете, выход из цикла, когда общий результат становиться false. Arduino Reference
Значит любое из условий, ставшие false, выведет из цикла. Думаю таблицу состояний для логического И видели.
А вот, что бы зашло в цикл, оба условия должны быть true.
 
Последнее редактирование:

Алексей.

Active member
я нашел ошибку. виной всему моя не внимательность - в конце строчки c while поставил ; и компилятор это проглотил
Вполне нормальное поведение компилятора, то что просили то и собрал, он не виноват что в операторе '>' вы не выполняете delayMicroseconds
Можно было и в счетчике для оператора сравнения коду добавить :)
Код:
class Counter {
public:
   Counter(int16_t value = 0) {
       this->value = value;
   }
   int16_t operator = (int16_t value) {
       this->value = value;
       return this->value;
   }
   bool operator > (int16_t value) {
       this->value--;
       delayMicroseconds(1);
       return this->value > value;
   }
private:
   int value;
};

Counter counter = 2000;
while ((digitalRead(_dreq) == LOW) || counter > 0) ;
 

enjoynering

Well-known member
Можно было и в счетчике для оператора сравнения коду добавить
Красиво, но не кажется вам это очень громоздким? Пока это все провернется у меня буфер успеет три раза опустошится, нет? Я не критикую, просто хочу понять для себя как писать быстрый код.

Вполне нормальное поведение компилятора
мне смутило что после опечатки ";", в конце while, идет код в скобках
Код:
  {
    counter--;
    delayMicroseconds(1);
  }
на который компилятор никак не ругнулся, а ведь по идее должен был.
 
Последнее редактирование:

enjoynering

Well-known member
Неправильно понимаете, выход из цикла, когда общий результат становиться false.
Да опечатался - && означает что пока ОБА условия TRUE цикл while крутится.

Мне же нужно пока ОДНО из условий TRUE крутим цикл while. Те пока пин в низком состоянии или пока счетчик не обнулится. Как только, что то одно из этого случилось - вываливаемся и цикла.
 

Алексей.

Active member
Пока это все провернется у меня буфер успеет три раза опустошится.
Counter counter = 2000;
1. в стеке выделяется место размером sizеof(Counter), равным sizеof(int16_t), виртуальных функций нет, поэтому таблицы виртуальных функций не выделяется, время выполнения может превышать int16_t counter; только если компилятор этот counter расположит в регистре.
2. вызов конструктора в котором выполняется только операция присваивания внутренней переменной параметра по умолчанию, время увеличивается на вызов и возврат.
3. вызов оператора '=' в котором опять только операция присваивания, время увеличивается на вызов и возврат.
Можите пункт 3 исключить, заменив Counter counter = 2000 на Counter counter(2000)
Накладные расходы незначительные :)

Вызов ( counter > 0 ) повторяет Ваш код
{
counter--;
delayMicroseconds(1);
}
Чему там проворачиваться??

мне смутило что после опечатки ";", в конце while, идет код в скобках
код в скобках - создание области видимости, где тут опечатка? для разделения переменных можете создавать области видимости сколько угодно
Код:
{
char tmp[100] = "some text";
...
}
{
int32_t tmp = 100;
...
}
две переменные tmp в двух разных областях видимости изолированы и не мешают друг другу на смотря на одно имя
 
Последнее редактирование:

CodeNameHawk

Moderator
Команда форума
Ваше условие
Код:
while ((digitalRead(_dreq) == LOW) || (counter > 0))
подходит для этого,
Мне же нужно пока ОДНО из условий TRUE крутим цикл while.
но не подходит для этого
Как только, что то одно из этого случилось - вываливаемся и цикла.
 

CodeNameHawk

Moderator
Команда форума
код в скобках - создание области видимости, где тут опечатка? для разделения переменных можете создавать области видимости сколько угодно
Код:
while ((digitalRead(_dreq) == LOW) || (counter > 0));
Из за ; код дальше не пойдет, будет все время висеть тут, так как counter не будет уменьшаться.
 

Алексей.

Active member
CodeNameHawk, Я же сказал что ТС забыл перегрузить оператор '>' , если он перегружен и в операторе счётчик уменьшаем то while таки закончится, я проверял :)
 

CodeNameHawk

Moderator
Команда форума
Ваша перегрузка не меняет логику работы программы, ТС хочет
пока пин в низком состоянии или пока счетчик не обнулится. Как только, что то одно из этого случилось - вываливаемся и цикла.
если он перегружен и в операторе счётчик уменьшаем то while таки закончится, я проверял :)
Вы не обращаете внимания, что если пин == LOW , то обнуление счетчика не выведет из цикла.
 
Последнее редактирование:

Алексей.

Active member
В перегруженном операторе '>' выполняется уменьшение счетчика, вызов delayMicroseconds(1) чтоб не сработал вотчдог и возврат результата return this->value > value;
Таким образом цикл while ((digitalRead(_dreq) == LOW) || counter > 0) ; в котором значение пина остается в высоком состоянии, завершится когда счетчик будет списан до нуля.
Если оператор не перегружаем, то цикл должен выполняться пока значение пина остается в высоком состоянии, а про вотчдог мы уже забыли и он вызывает перезагрузку.
Если эта перегрузка оператора не меняет логику, тогда у меня аргументы закончились.
 

CodeNameHawk

Moderator
Команда форума
Как работа вашего кода отличается от работы этого?
Код:
  int16_t counter = 2000;
  while ((digitalRead(_dreq) == LOW) || (counter > 0))
  {
    counter--;
    delayMicroseconds(1);
  }
в котором значение пина остается в высоком состоянии, завершится когда счетчик будет списан до нуля.
Так вся суть в том, чтобы вне зависимости от состояния пина, чтобы цикл завершился при обнулении счетчика, должна же программа и дальше работать, даже если кнопку не нажали(или не отпустили ).
 
Последнее редактирование:

Алексей.

Active member
CodeNameHawk, В оригинале было while ((digitalRead(_dreq) == LOW) || (counter > 0)) ;
Если Вы ещё не заметили строка с while заканчивалась на ;
Вы предложили другой код, найдите отличия.

Как работа вашего кода отличается от работы этого?
Я показал как выполнять списания счетчика и вызов delayMicroseconds(1) просто перегрузив оператор '>' не меняя оригинальный while заканчивающийся на ; и только
 

CodeNameHawk

Moderator
Команда форума
Если Вы ещё не заметили строка с while заканчивалась на ;
Хорошая помощь, вместо того, чтобы убрать один символ, написать кучу ненужного кода. Такой же примерно код, как ваш, написав вместо counter функцию, которая возвращает результат, но нафига?
 

Алексей.

Active member
Конечно с++ не нужен, а stl вообще пора предать анафеме, ansi c - гламур, давайте вернемся к Карнигану. Вперёд! только без меня.
 

kab

New member
Как там типа: Keep it simple, s...? Короче, KISS! А если честно, у себя не всегда получается...
 
Сверху Снизу