ESP32. Управление кнопками в FreeRTOS

ESP-32 v57Год назад я писал статью про управление кнопками в Arduino. С тех пор родилась библиотека SButton с кучей наворотов, которая активно используется мной в различных проектах. В последнее время я использую в проектах контроллер ESP32  компании Espressif Systems и много времени уделяю программирование под FreeRTOS, хорошо раскрывающей возможности этого двухъядерного контроллера.

Итак, задача реализовать работу кнопки параллельно выполнению других задач. Данные примеры публикую как памятку себе )

Итак, приступим…

Пример работающий на всех Arduino

Этот пример взят из предыдущей статьи и будет работать на любом микроконтроллере, который поддерживает Arduino IDE. Нужно только установить требуемый GPIO, к которому подключена кнопка.

 

Здесь отлавливаются события как на нажатие, так и на отпускание кнопки. Если померить время между этими событиями, то можно организовать обработку короткого нажатия кнопки и ее длинного удержания.

К недостаткам данного метода следует отнести то, что если в цикле loop() будут выполнятся еще какие то действия, занимающие, то мы вполне можем пропустить нажатие кнопки.

Пример 1. Цикл с кнопкой в параллельной задаче

В Arduino IDE Core ESP32 по умолчанию загружается FreeRTOS, где параллельными задачами запускается работа с WiFi на первом ядре и главный пользовательский цикл loop() и другие пользовательские задачи. При использовании WiFi лучше не трогать первое ядро, чтобы не получить «глючный ESP8266», когда всегда можно нарваться на «злобный WDT», если твоя задача будет что-то делать «не вовремя» или «слишком долго».

Чтобы кнопка работала постоянно, запускаю обработчик параллельной задачей с нужным приоритетом.

При работе с параллельными процессами FreeRTOS следует обратить на следующие особенности:

  1. Приоритет задачи обработки кнопки должен быть выше задач, во время которых может быть востребовано нажатие кнопки. В моем примере главный цикл loop() выполняется в задаче loopTask с приоритетом 1, а задача обработки кнопки имеет приоритет 5.
  2. Если в обработке кнопки будет какой то сложный алгоритм, то нужно следить за размером стека, выделяемым при старте задачи. Ошибка переполнения стека будет выглядеть следующим образом
  3. При таком алгоритме цикл обработки кнопки постоянно крутится с задержкой 100 мсек, оставляя ровно столько времени другим задачам с более низким приоритетом. Непростительное расточение ресурсов микроконтроллера, поэтому следующий пример делаю на прерывании

 

Пример 2. Использование внешнего прерывания

Полностью запихать работу с кнопкой в обработчик прерывания мне не удалось. Дребезг, вызываемый при опускании кнопки, стабильно давал ложное срабатывания. Кроме того, внутри обработчика прерывания действует ряд ограничений, например, не работает delay() и не увеличивается значение millis(). Поэтому обработчик прерываний я использовал только для управления семафором, который «держит» задачу работы с кнопкой в ожидании.

 

В данном примере задача обработки кнопки ожидает освобождения семафора и не занимает ресурсов контроллера большую часть времени. При получении внешнего прерывания по кнопке задача выполняет какое-то действие. Для устранения ложного срабатывания статус кнопки должен дважды смениться на противоположный с соответствующей задержкой. Если отпускание кнопки не успевает сработать, то возврат в состояние готовности следующего нажатие производится по таймауту.

Хороший, надежный алгоритм с программным подавлением дребезга контактов не занимающий ресурсов микроконтроллера во время ожидания на нажатие кнопки. К его недостатком можно отнести ненадежное определение отпускания кнопки, что не позволяет рассчитать время нажатия (для обработки длинных и коротких нажатий)

Пример 3. Комбинирование внешнего прерывания и цикла обработки нажатия кнопки

При получении прерывания по кнопке цикл задачи снимается с ожидания светофора и работает по таймауту, как в первом примере, до тех пор пока не будет зафиксирована отпущенная кнопка с учетом дребезга контактов.

В этом примере надежно фиксируется как нажатие, так и отпускание кнопки, что позволяет рассчитывать время ее нажатия. Данная задача «кушает ресурсы» только после нажатия кнопки до ее отпускания.

Пример 4. Обработка нескольких кнопок

При работе с несколькими кнопками вовсе не обязательно запускать несколько задач и обработчиков прерывания. Достаточно по прерыванию от любой кнопки переходить на цикл роботы по таймауту, а при фиксировании отпускания всех

Пример 5. Обработка емкостного сенсорного входа по прерыванию

Touch интерфейс — чисто ESP-шная фича, позволяющая реализовать до 10 сенсорных кнопок. Далее привожу пример работы с сенсорной кнопкой на GPIO4 (TOUCH0) с прерыванием по порогу срабатывания. В остальном код ничем не отличается от Примера 3.

Полезные ссылки

Хороший цикл статей про FreeRTOS на русском языке

 

Файлы примеров к статье
7.1 KiB
155 Downloads
Детали
Вы можете оставить отзыв или трекбек со своего сайта.

2 комментария на «ESP32. Управление кнопками в FreeRTOS»

  1. Дамир:

    А Вы проверяли, действительно ли отключаются прерывания в примере 5 ?

    У меня не получается отключить прерывания.

    int threshold = 20;
    bool touch1detected = false;

    void gotTouch1() {
    touch1detected = true;
    }

    void setup() {
    Serial.begin(115200);
    delay(1000);
    Serial.println(«ESP32 Touch Interrupt Test»);

    touchAttachInterrupt(T0, gotTouch1, threshold);
    delay(1000);
    detachInterrupt(T0);
    delay(1000);

    }
    void loop() {
    if (touch1detected) {
    detachInterrupt(T0);
    touch1detected = false;
    Serial.println(«Touch 1 detected»);
    Serial.println(touchRead(T0));
    }
    }

    С уважением.

  2. Дамир:

    Результат

    06:47:12.228 -> Touch 1 detected
    06:47:12.228 -> 15
    06:47:12.275 -> Touch 1 detected
    06:47:12.275 -> 0
    06:47:12.275 -> Touch 1 detected
    06:47:12.275 -> 9
    06:47:12.322 -> Touch 1 detected
    06:47:12.322 -> 8
    06:47:12.322 -> Touch 1 detected
    06:47:12.322 -> 6
    06:47:12.368 -> Touch 1 detected
    06:47:12.368 -> 5
    06:47:12.368 -> Touch 1 detected
    06:47:12.368 -> 6
    06:47:12.415 -> Touch 1 detected
    06:47:12.415 -> 5

Ваш отзыв

Вы должны войти, чтобы оставлять комментарии.