Особенности программирования ESP32 из Arduino IDE

Эта небольшая статья ориентирована в первую очередь на тех, кто только начинает осваивать микроконтроллер ESP32 в среде Arduino IDE. Я далеко не гуру в микроконтроллерах и в свое время я потратил много времени, пытаясь понять, чем же отличается программирование для ESP32 от уже привычных Adruino и ESP8266; и почему почти все примеры для ESP32 написаны как задачи для FreeRTOS. Меня долго занимал вопрос – что же это за FreeRTOS такая, и так ли уж необходимо ее осваивать, когда начинаешь работать с новым микроконтроллером. Забегая вперед скажу, что таки да, без FreeRTOS на ESP32 никуда, по крайней мере если Вы используете классическую Arduino IDE. Ну то есть если очень хочется, то можно обойтись без задач и FreeRTOS, но это будет как “микроскопом гвозди забивать”. Повторю еще раз – все нижесказанное относится к Arduino IDE, про другие IDE пока ничего сказать не могу, ибо сам не пробовал, хотя и установил. Итак, обо всем по порядку… 

 

ESP32 имеет по сравнению с ESP8266 множество преимуществ – более шустрый двухядерный процессор, гораздо больше портов ввода-вывода, в том числе и аналоговых, возможность подключения внешней WiFi-антенны (на некоторых моделях) и много чего еще. В рамках данной статьи я не буду рассматривать все аппаратные отличия ESP32 от своего предшественника, информации об этом много. Скажу лишь, что лично для меня ключевым фактором перехода на повсеместное использование ESP32 стало существенно большее количество портов ввода-вывода для подключения внешних устройств и датчиков, особенно аналоговых. ESP8266 обладает в этом плане ну очень скромными возможностями, да еще единственный АЦП обладает довольно низким разрешением. Конечно, цена ESP32 несколько выше, но с этим вполне можно смириться. 

ESP32-DevKitC

ESP32-DevKitC – варианты с печатной антенной и внешней

Перед началом программирования ESP32 в Arduino IDE необходимо установить пакет esp32 by Espressiv Systems через Менеджер плат:

esp32 by Espressiv Systems

Установленный пакет esp32 в менеджере плат

Если в списке плат нет этого пакета, добавьте строчку “https://dl.espressif.com/dl/package_esp32_index.json” в Настройках Adruino IDE:

Настройки Adruino IDE

Подключение esp32 к менеджеру плат

После этого повторно установите пакет через Менеджер плат.

Нужна ли FreeRTOS для ESP32?

Первое, на что натыкаешься, когда смотришь примеры скетчей для ESP32 – в них очень часто используются функции xTaskCreate или xTaskCreatePinnedToCore. То есть различные операции выполняются в режиме многопоточности. Возникает вопрос: а разве нельзя сделать “по старому, по простому”, без использования всех этих задач? Так ли уж необходимо осваивать новую область – программирование для FreeRTOS?

Кроме того, лично у меня сразу же возник еще один вопрос – если на борту ESP32 теперь два процессора, то как они будут использоваться скетчем? В свое время я задавал на форме esp8266.ru, но потом сам же на него и ответил :). 

Ответы на свои вопросы я получил после того, как наткнулся на “обертку” скетча Arduino \packages\esp32\hardware\esp32\1.0.4\cores\esp32\main.cpp. Эта обертка используется для всех скетчей, которые Вы создаете в классической Arduino IDE.

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_task_wdt.h"
#include "Arduino.h"

TaskHandle_t loopTaskHandle = NULL;

#if CONFIG_AUTOSTART_ARDUINO

bool loopTaskWDTEnabled;

void loopTask(void *pvParameters)
{
setup();
    for(;;) {
        if(loopTaskWDTEnabled){
            esp_task_wdt_reset();
        }
        loop();
    }
}

extern "C" void app_main()
{
    loopTaskWDTEnabled = false;
    initArduino();
    xTaskCreateUniversal(loopTask, "loopTask", 8192, NULL, 1, &loopTaskHandle, CONFIG_ARDUINO_RUNNING_CORE);
}

#endif

Какую информацию отсюда можно почерпнуть? Видно, что FreeRTOS всегда подключается к Вашему скетчу (#include “freertos/FreeRTOS.h”), а любой классический скетч Arduino IDE (то есть написанный без использования задач) – это всего лишь задача FreeRTOS, которая выполняется на втором ядре процессора #1, и которой выделено всего 8192 байт стека! Сама FreeRTOS при этом выполняется на ядре процессора #0. Это и хорошо, и плохо. Хорошо, что на ESP32 под Arduino обслуживание самого контроллера, WiFi и прочие служебные надобности теперь никак не пересекаются с Вашим скетчем. Теперь даже если скетч зависнет или уйдет в Sleep на столетие, то это никак не повлияет на работу служебных подпрограмм. А плохо тем, что Ваш скетч получит только доступ только к ограниченному объему стека, остальная доступная память просто не будет использоваться. 8192 – это далеко не весь стек, что доступен задачам FreeRTOS, на одном из моих контроллеров работает еще с десяток параллельных задач (каждый со своим выделенным стеком) и память еще не закончилась.

Вывод: если Вы хотите использовать все доступные на ESP32 возможности, Вам придется изучать и использовать функции FreeRTOS, хотите Вы этого или нет. В этом нет ничего страшного, осваивается FreeRTOS довольно легко. Но увы, когда Вы начнете использовать многопоточность и задачи на ESP, то Вам придется забыть про некоторые уже ставшие привычными библиотеки Arduino, так как они просто не способны работать в многозадачной среде. Например лично я столкнулся с сложностями при использовании библиотеки time, которую я использовал для синхронизации с NTP-серверами. Когда несколько потоков – задач одновременно пытаются получить текущее время, контроллер иногда может аварийно перезагружаться. Проблема решаемая, но требуется внимательность и перепрограммирование некоторых участков кода под новые условия.

Ссылки для изучения FreeRTOS:

В процессе поисков по интернету для себя я отобрал следующие ресурсы, которыми пользуюсь постоянно:

  1. Андрей Курниц “FreeRTOS — операционная система для микроконтроллеров”
  2. FreeRTOS — практическое применение
  3. Справочник по Free RTOS API

Добавить комментарий