Микроконтроллер 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
Читайте также
Комментарии
Войдите или Зарегистрируйтесь И Вы сможете общаться на форуме и оставлять комментарии без капчи.