ESP8266 во время delay() обеспечивает работу wifi. В больших циклах рекомендуется вставлять delay(0) как раз для этого.
Блин, да с чего? Молоток иногда попадает по пальцу - значит он зло и гвозди забивать надо микроскопом, так что ли? delay - один из инструментов, который весьма полезен, если использовать его по назначению и правильно. А ЗЛО - это "Западное Либеральное Общество".
См. код delay в #60 и попробуйте объяснить, каким боком delay(0) может хоть на что-то повлиять, если там даже yield ни разу не вызовется?
Джентльмены верят на слово Речь про ESP8266. И поскольку я пасу этого коня на языке Lua, то про волшебную ардуино на оном камне читал очень давно. Про делай на ESP8266 осталось такое приятное воспоминание. Хотите оказаться правым - ковыряйте исходники сами. Сферические кони ждут.
Да это понятно, как и с delay(0) тоже заметил, но руки не дошли написать. Если понимать как работает, то можно легко пользоваться. Приведенный пример - тому доказательство. Но для начинающих, как мне кажется, вариант сложноватый, проще наверное с millis(), как обычно. Пост: это подтверждает. Я пытался найти для себя сценарии использования, честно говоря только искусственные варианты. Хотя с глобальными флагами, чтобы ветвиться после delay(), в зависимости от обработки в yield(), можно придумать. Но, как мне кажется, не хватает принудительно окончания delay(), по решению из yield().
Думаю можно в yield() возвращать 0/1 в зависимости от необходимости вывалиться сразу или после окончания интервала.
Подумал на досуге, мне кажется, что вариант с перегрузкой функции, delay(1000, &flag_variable); проще будет. Ну и my_yield(uint8_t *ptr) с передачей флага через указатель из основного кода через новый delay(1000, &flag_variable). А из yield() вызывается my_yield(NULL), для совместимости. Тогда с минимальными потерями можно управлять выходом из delay(xxxx,ptr) в любой момент, а через указатель на флаг передавать причину и необходимое действие. Еще можно добавить глобальный флаг состояния для анализа в my_yield(...), чтобы понимать откуда мы туда попали, и что нужно сделать... Пример кода: Код (C++): const int ledPin = LED_BUILTIN; // the number of the LED pin int ledState = LOW; // ledState used to set the LED uint32_t previousMillis = 0; // will store last time LED was updated const long interval = 1000; // interval at which to blink (milliseconds) void setup() { // set the digital pin as output: pinMode(ledPin, OUTPUT); Serial.begin(115200); } void loop() { uint8_t delay_break_flag = 0; // 76543210 // |||||||| // |||||||+--- 0: brake from delay // ||||||+---- 1: Flag 1 // |||||+----- 2: Flag 2 // ||||+------ 3: Flag 3 // |||+------- 4: Flag 4 // ||+-------- 5: Flag 5 // |+--------- 6: Flag 6 // +---------- 7: Internal flag "delay start" Serial.println("loop_begin------"); Serial.print("delay(30 000) start: "); Serial.println(millis()); delay(30000); Serial.print("delay(30 000) end: "); Serial.println(millis()); Serial.print("delay(60 000) start: "); Serial.println(millis()); delay(600000, &delay_break_flag); Serial.print("delay(60 000) end: "); Serial.println(millis()); if (delay_break_flag & 1) Serial.println("Delay break"); if (delay_break_flag & 2) Serial.println("Flag detected"); Serial.println("loop_end--------\n"); } void delay(uint32_t ms, uint8_t *ptr) { uint32_t start = micros(); if (ptr) // если только зашли в new delay() *ptr &= 0x80; // взведем флаг начала delay() while (ms > 0) { my_yield(ptr); if (ptr && *ptr & 1) // взведен флаг выхода из delay в my_yield() break; while ( ms > 0 && (micros() - start) >= 1000) { ms--; start += 1000; } } } void yield() { my_yield(NULL); // вызовем my_yield() с нулевым указателем } void my_yield(uint8_t *ptr) { unsigned long currentMillis = millis(); static int counter = 0; if (ptr && *ptr & 0x80) // это первый вход в my_yield() из delay(ххх,с указателем на флаг) ? { *ptr = 0; // сбросим флаг первого входа counter=0; // проинициализируем переменные } if (currentMillis - previousMillis >= interval) { previousMillis = currentMillis; // if the LED is off turn it on and vice-versa: if (ledState == LOW) { ledState = HIGH; Serial.print("Tic"); } else { ledState = LOW; Serial.println("-tac"); counter++; } digitalWrite(ledPin, ledState); } if (counter == 10) { counter=0; if (ptr) // тут для примера, переписываем в зависимости от условий и статуса... *ptr |= (uint8_t) 1; *ptr |= (uint8_t) 2; } } В симуляторе
Библиотеки для I2C/1wire тоже нужно проверить, там скорее всего есть бесконечные циклы ожидания событий и настраиваемые таймауты не предусмотрены, как и в библиотеках для периферии. Чтобы нормальный неблокирующий код получился придется почти все переписать в формате конечных автоматов.