Микроконтроллер ESP32 завоевал огромную популярность в мире Интернета вещей (IoT) и встраиваемых систем благодаря своей мощности и наличию Wi-Fi/Bluetooth. Однако многие начинающие разработчики, осваивая классическую задачу мигания светодиодом ("Blink"), сталкиваются с ограничениями функции delay()
. Хотя delay()
проста в использовании, она полностью останавливает выполнение программы на указанное время, что неприемлемо для проектов, требующих одновременного выполнения нескольких операций.
Функция delay(ms)
приостанавливает работу микроконтроллера на ms
миллисекунд. В это время ESP32 не может выполнять никакие другие задачи: опрашивать датчики, реагировать на нажатия кнопок, обмениваться данными по сети. В примере, рассмотренном в статье, при мигании светодиода с интервалом в 1 секунду (delay(1000)
), нажатия кнопки, происходящие во время этой паузы, просто игнорируются программой. Это наглядно демонстрирует неэффективность delay()
для создания отзывчивых и многофункциональных устройств.
Альтернативой является функция millis()
. Она не останавливает программу, а возвращает количество миллисекунд, прошедших с момента запуска ESP32. Используя этот счетчик, можно организовать выполнение задач по расписанию без блокировки основного цикла loop()
.
Принцип работы прост:
previousMillis
).loop()
получается текущее время (currentMillis = millis()
).currentMillis - previousMillis >= interval
).previousMillis
обновляется текущим временем./* * Сравнение: delay() против millis() в ESP32. * https://arduino-tex.ru/news/209/sravnenie-delay-protiv-millis-v-esp32.html */ #define LED_PIN 21 // Пин GPIO21 ESP32, подключенный к светодиоду #define BUTTON_PIN 18 // Пин GPIO18 ESP32, подключенный к кнопке #define BLINK_INTERVAL 1000 // Интервал мигания светодиода (миллисекунды) // Переменные: int ledState = LOW; // Текущее состояние светодиода int previousButtonState = HIGH; // Предыдущее состояние кнопки unsigned long previousMillis = 0; // Время последнего изменения светодиода void setup() { Serial.begin(115200); pinMode(LED_PIN, OUTPUT); pinMode(BUTTON_PIN, INPUT_PULLUP); previousButtonState = digitalRead(BUTTON_PIN); // Начальное состояние } void loop() { unsigned long currentMillis = millis(); // Текущее время // Проверяем, прошло ли достаточно времени: if (currentMillis - previousMillis >= BLINK_INTERVAL) { // Инвертируем состояние: ledState = (ledState == LOW) ? HIGH : LOW; digitalWrite(LED_PIN, ledState); previousMillis = currentMillis; // Сохраняем время } // --- Проверка состояния кнопки --- (выполняется в КАЖДОЙ итерации) int currentButtonState = digitalRead(BUTTON_PIN); if (currentButtonState != previousButtonState) { Serial.println(currentButtonState); previousButtonState = currentButtonState; } // --- ЗДЕСЬ МОЖНО ДОБАВИТЬ ДРУГИЕ НЕБЛОКИРУЮЩИЕ ЗАДАЧИ --- }
Поскольку цикл loop()
выполняется очень быстро и без пауз, проверка времени и другие задачи (например, чтение состояния кнопки) происходят практически непрерывно. В статье приводится пример кода, где светодиод мигает с интервалом в 1 секунду, но при этом все нажатия кнопки успешно регистрируются и выводятся в монитор порта, так как проверка кнопки происходит в каждой итерации loop()
, независимо от состояния светодиода.
Прелесть подхода с millis()
заключается в его масштабируемости. Можно легко добавить управление несколькими задачами, работающими с разными интервалами, просто создав для каждой задачи свой набор переменных для хранения времени последнего выполнения и интервала. В статье это демонстрируется на примере управления двумя светодиодами, мигающими с разной частотой (1000 мс и 500 мс), и одновременной проверкой состояния кнопки – все это работает псевдопараллельно без взаимных блокировок.
Почему это важно?
Освоение неблокирующего подхода с millis()
– ключевой шаг для разработки более сложных и функциональных проектов на ESP32. Этот паттерн необходим при работе с сенсорами, требующими периодического опроса, реализации сетевых протоколов, создании пользовательских интерфейсов и во всех случаях, когда требуется отзывчивость системы и одновременное выполнение нескольких действий. Отказ от delay()
в пользу millis()
позволяет раскрыть реальный потенциал ESP32 для создания умных и эффективных устройств.
Полная версия статьи с подробными объяснениями, схемами подключения для одного и двух светодиодов, полными кодами примеров для delay()
и millis()
, а также пошаговыми инструкциями доступна на сайте Ардуино технологии (Arduino-tex.ru).
Понравилась новость Многозадачность на ESP32: Отказываемся от delay() в пользу millis()? Не забудь поделиться с друзьями в соц. сетях.
А также подписаться на наш канал на YouTube, вступать в группу Вконтакте.
Понравилась статья? Поделитесь ею с друзьями:
Вернуться в раздел: Новости Дата публикации 26 марта , 2025
Читайте также
Комментарии
Войдите или Зарегистрируйтесь И Вы сможете общаться на форуме и оставлять комментарии без капчи.