Многозадачность на ESP32: Отказываемся от delay() в пользу millis().

.Многозадачность на ESP32: Отказываемся от delay() в пользу millis().

Микроконтроллер ESP32 завоевал огромную популярность в мире Интернета вещей (IoT) и встраиваемых систем благодаря своей мощности и наличию Wi-Fi/Bluetooth. Однако многие начинающие разработчики, осваивая классическую задачу мигания светодиодом ("Blink"), сталкиваются с ограничениями функции delay(). Хотя delay() проста в использовании, она полностью останавливает выполнение программы на указанное время, что неприемлемо для проектов, требующих одновременного выполнения нескольких операций.

Проблема delay(): Блокировка выполнения.

Функция delay(ms) приостанавливает работу микроконтроллера на ms миллисекунд. В это время ESP32 не может выполнять никакие другие задачи: опрашивать датчики, реагировать на нажатия кнопок, обмениваться данными по сети. В примере, рассмотренном в статье, при мигании светодиода с интервалом в 1 секунду (delay(1000)), нажатия кнопки, происходящие во время этой паузы, просто игнорируются программой. Это наглядно демонстрирует неэффективность delay() для создания отзывчивых и многофункциональных устройств.

Данный урок демонстрирует, как реализовать выполнение нескольких задач псевдопараллельно на ESP32

Решение millis(): Неблокирующий подход.

Альтернативой является функция millis(). Она не останавливает программу, а возвращает количество миллисекунд, прошедших с момента запуска ESP32. Используя этот счетчик, можно организовать выполнение задач по расписанию без блокировки основного цикла loop().

Принцип работы прост:

  1. Запоминается время последнего выполнения задачи (previousMillis).
  2. В каждой итерации цикла loop() получается текущее время (currentMillis = millis()).
  3. Проверяется, прошло ли достаточно времени с последнего выполнения (currentMillis - previousMillis >= interval).
  4. Если интервал истек, выполняется нужная операция (например, переключение состояния светодиода), и 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().

Прелесть подхода с millis() заключается в его масштабируемости. Можно легко добавить управление несколькими задачами, работающими с разными интервалами, просто создав для каждой задачи свой набор переменных для хранения времени последнего выполнения и интервала. В статье это демонстрируется на примере управления двумя светодиодами, мигающими с разной частотой (1000 мс и 500 мс), и одновременной проверкой состояния кнопки – все это работает псевдопараллельно без взаимных блокировок.

Почему это важно?

Освоение неблокирующего подхода с millis() – ключевой шаг для разработки более сложных и функциональных проектов на ESP32. Этот паттерн необходим при работе с сенсорами, требующими периодического опроса, реализации сетевых протоколов, создании пользовательских интерфейсов и во всех случаях, когда требуется отзывчивость системы и одновременное выполнение нескольких действий. Отказ от delay() в пользу millis() позволяет раскрыть реальный потенциал ESP32 для создания умных и эффективных устройств.

Полная версия статьи с подробными объяснениями, схемами подключения для одного и двух светодиодов, полными кодами примеров для delay() и millis(), а также пошаговыми инструкциями доступна на сайте Ардуино технологии (Arduino-tex.ru).


Понравилась новость Многозадачность на ESP32: Отказываемся от delay() в пользу millis()? Не забудь поделиться с друзьями в соц. сетях.

А также подписаться на наш канал на YouTube, вступать в группу Вконтакте.

Понравилась статья? Поделитесь ею с друзьями:

Вернуться в раздел: Новости Дата публикации 26 марта , 2025

Комментарии

Войдите или Зарегистрируйтесь И Вы сможете общаться на форуме и оставлять комментарии без капчи.


Cлучайные товары

Посмотреть товар в Магазине »

Мы в соц сетях

Подпишись на канал Telegram

Portal-PK (Портал ПК) © 2015 - 2025
Разработка проектов
AT Block
DWIN Box