Перейти к содержимому

Прошивка для ESP32 на основе ESP-IDF

Метки:

Добрый день, уважаемые читатели!

В этой статье перечислены все имеющиеся на момент написания статьи модули, классы и прочие библиотеки, которые входят в состав моей прошивки на основе ESP-IDF, их назначение и основные свойства. Эту статью, пожалуй, нужно было бы написать уже довольно давно, когда ещё я только начал публиковать описание термостата на esp32. Что ж, лучше поздно чем никогда. 

 


Что это за прошивка такая?

В этой статье описывается заготовка прошивки для ESP32 на основе фреймворка ESP-IDF (Espressif IOT Development Framework), то есть без использования Arduino. Назовем её условно “прошивка k12”, просто по названию данного сайта. Это не официальное название и не торговая марка. На основе этой прошивки созданы термостат, автоматическая теплица, устройство автоматического полива, которые описаны на данном сайте, а также несколько других устройств, которые уже несколько лет подряд успешно функционируют в моем доме с зачатками разума.

Зачем я принялся изобретать велосипед и не использовал что-то готовое? На это есть несколько причин.

  • Во-первых, когда-то использовал несколько вариантов готовых прошивок, но сталкивался с невозможностью реализации всех моих хотелок. Ну прямо как в том анекдоте – “весь город устраивает, а его нет“…
  • Во-вторых – свои ошибки я могу исправить сам и сравнительно быстро, если таковые обнаружены. А вот добиться исправления проблемы в open source проекте, которое поддерживается комьюнити – зачастую сложно и долго. Сталкивался с исправлением проблем в официальных фреймворках esp-idf и arduino-esp32.
  • Ну и самое главное – мне интересно разбираться в коде и писать код. Мне абсолютно не интересен путь “не важно как, лишь бы как-то и хоть иногда работало, и побыстрей”. Когда костыль на костыле и костылем подпёрто.

Данная прошивка идеальна и подходит абсолютно всем? Конечно же нет! В первую очередь я создавал её для себя и для своих задач. А ваши задачи могут существенно отличаться от моих. Например, я выбрал в качество основы основ протокол MQTT, и все построено вокруг него. Кому-то это не подходит. Но вы можете взять только нужные вам библиотеки для своих разработок. И эта статья как раз и создана для того, чтобы помочь вам в этом.

В написанных мной библиотеках совершенно точно есть проблемы и ошибки. Я в этом абсолютно уверен. Про некоторые я знаю, но пока не исправил; какие-то я просто ещё не нашел. Но они не мешают устройствам нормально функционировать по 120 дней подряд без паник, вылетов и перезагрузок по непонятным причинам. И я все ещё работаю над их исправлением. Некоторые модули переписаны уже по нескольку раз. Буду благодарен, если вы мне укажите на них, когда обнаружите.

Мне часто ставят в упрек, что “Arduino поддерживается миллионным комьюнити” и вылизан как котовьи фаберже, а мои поделки создаю только я сам. Совершенно верно подмечено, но увы, это не является гарантией полной защиты от проблем. Даже простой скетч вентиляции для погреба, написанный когда-то в Arduino, никогда не работал дольше месяца без сбоя и аварийной перезагрузки. Arduino очень хорош для начала, он прост и понятен каждому, и именно эта его ключевая особенность. Но вы же не пытаетесь принимать аспирин от всех болезней? Так почему же до сих пор Arduino IDE позиционируется как затычка для всего? 

В настоящий момент прошивка разделена на множество вроде бы отдельных частей – библиотек, которые вы можете найти и скачать с GitHub. На самом деле большинство из них все-таки не могут функционировать отдельно от других библиотек. Все-таки у меня получился не набор независимых модулей, а одна прошивка. Поэтому в настоящее время понемногу идет работа на следующей версией библиотек, где все они будут оптимизированы и собраны в единое целое. По аналогии с самой ESP-IDF и esp-idf-lib от UncleRus. Тем не менее, большинство составных частей останутся прежними, поэтому данная статья все равно останется актуальной.

 


Основные функции и возможности

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

  • Прошивка не имеет собственного web-интерфейса. Поскольку web-интерфейс полезен только в локальной сети, то не вижу никакого смысла его программировать и тратить на него ресурсы микроконтроллера.
  • Основной протокол управления и контроля – MQTT. Поддерживаются любые типы серверов – с префиксами и без, с TLS и без оного. Имеется поддержка двух MQTT-брокеров – основного и резервного (например локального и облачного).
  • Подключение к нескольким WiFi-сетям (до пяти) с автоматическим выбором. Прошивка не имеет web-интерфейса для настройки подключения к wifi, всё необходимое настраивается только в конфигурационном файле. Несколько преднастроенных сетей позволяет переносить устройство из одной локации в другую без необходимости изменения прошивки.
  • Автоматическая синхронизация локального времени с серверами SNTP в сети интернет. Это позволяет в большинстве случаев отказаться от использования модуля часов. Но при необходимости можно легко интегрировать модули DS1307 или DS3231.
  • Постоянный мониторинг доступа в сеть интернет с помощью пинга с сохранением истории. Это позволяет приостанавливать сетевые процессы в случае проблем с доступом в сеть и предотвращать аварийные ситуации из-за этого (например из-за переполнения памяти).
  • Публикация данных с сенсоров вместе с временем измерения и со всеми экстремумами в одном топике в JSON-виде. Впрочем, можно перенастроить устройство на публикацию данных с сенсоров в открытом виде, если очень хочется.
  • Уведомления в Telegram. Можно привязать до 4 отдельных каналов или чатов: обычный, сервисный, охрана и изменение параметров. Уведомления – не обязательная часть, их можно отключить с помощью файла конфигурации проекта. Автоматические уведомления в Telegram об изменениях состояния устройства, в том числе с настраиваемой задержкой (это позволяет пропускать кратковременные сбои и отключения различных сервисов), об сбоях сенсоров и исполнительных устройств. Но полноценного бота (с обратной связью) на данный момент нет.
  • Возможность отправки данных на сторонние сервисы ThingSpeak, Народный мониторинг, Open Monitoring – по выбору, можно использовать даже несколько сервисов одновременно.
  • OTA (Over The Air) – обновление прошивки без необходимости физического подключения к устройству, через сеть интернет. Но необходим сервер с прямыми ссылками.
  • Расширенные возможности для удаленной отладки: отправка backtrace, списка задач с размером стека, фиксация уровня сигнала, пинга, количества свободной памяти.

Но самое главное – это не полностью готовая прошивка, а скорее гибкий шаблон вашей прошивки. То есть вы вольны изменять многое по своему желанию и потребностям. Какие-то  компоненты можно просто отключить с помощью “управляющих” макросов препроцессора – например telegram. Что-то вы можете дописать самостоятельно.

Само собой, поддерживаются все протоколы и возможности, которые заложены собственно в ESP-IDF, например одновременно две шины I2C, шина RS485 и протокол Modbus и т.д.

 


Что понадобится?

Для работы с этой прошивкой вам понадобится Visual Studio Code с установленным плагином PlatformIO. Инструкция по установке и первоначальной настройке. Конечно, можно использовать и оригинальный плагин от espressif, но тогда вам придется немного переделать сам проект. Кроме того, PlatformIO позволяет программировать и модули Arduino в более удобной IDE.

Структура каталогов

Шаблоны всех прошивок, опубликованных на сайте для ESP32, “рассчитаны” на определенную структуру каталогов на диске. 

У меня корневой каталог всех проектов – это C:\PlatformIO. Не в профиле пользователя и не в папке “Мои документы”, как предлагается по умолчанию! Не путайте каталог проектов и каталог установки самого platformio – это совершенно разные вещи!

Все общие библиотеки (то есть те, что используются сразу во всех проектах) лежат внутри корневого каталога проектов в подкаталоге libs. То есть полный путь к общим библиотекам будет C:\PlatformIO\libs

Каталоги (папки) проектов должны быть расположены внутри уже рассмотренного C:\PlatformIO по аналогии с библиотеками. Например: C:\PlatformIO\thermostat или как на картинке ниже:

Это не означает, что “можно так, и только так“! Cовсем нет, вы вполне можете использовать другие каталоги, как будет удобнее вам. Но тогда вам придется изменить настройки каталогов в нескольких файлах проекта самостоятельно. Не готовы этого сделать? – используете структуру как описано выше.

 


Структура прошивки

Назначение каталогов и файлов проекта:

  • Главный исполняемый файл проекта находится в каталоге .\src – как правило это файл main.cpp. Его подробнее я опишу ниже.
  • В папке .\include находится файл настроек проекта project_config.h. В нем описаны большая часть параметров, относящихся к проекту: используемые GPIO контроллера, имя и пароль wifi-сетей, параметры mqtt-брокеров, токены и пароли внешних сервисов и прочее, прочее, прочее.  В виде макросов препроцессора.
  • В папке .\lib расположены прикладные файлы проекта. Именно здесь реализована основная логика, для чего данное конкретное устройство и было собственно создано. Чаще всего здесь только один подкаталог, однако бывает и несколько. В заголовочных файлах этих библиотек вы найдете и большую часть “прикладных” параметров (сенсоры, параметры автоматического регулирования, настройки актуаторов, кранов, реле и т.д.), просто так удобнее.
  • В папке .\layouts могут располагаться схемы подключения и чертежи печатных плат устройства.
  • В файле partitions.csv находится разметка flash-памяти устройства. По умолчанию настроена схема с двумя OTA-разделами и большим NVS разделом
  • В файле platformio.ini находятся настройки проекта protformio. Про него я рассказывал здесь.

Главный исполняемый файл проекта main.cpp практически не изменяется от проекта к проекту, я изменяю только указания на то, какие прикладные задачи необходимо запустить в конце всех настроек и инициализаций. После этого он завершается и больше не используется. Выглядит он так:

  1. Вначале инициализируется система отладочных сообщений – логов.
  2. Затем подключаются обработчики перезапуска espRegisterSystemShutdownHandler(); – дабы успеть сохранить на flash-памяти все данные перед тем как устройство будет перезагружено. Но это не всегда удается, например в случае паники никакие пользовательские обработчики не работают.
  3. Затем инициализируем саму систему хранения параметров в NVS – paramsInit();
  4. Запускаем задачу системного светодиода – ledSysInit(...); При необходимости, сюда же следует добавить и другие светодиоды.
  5. Запускаем главный цикл событий – eventLoopCreate(); Это прикладной цикл, отличный от системного, хотя можно использовать и один общий. Но возможны “накладки”
  6. Далее запускаем библиотеку, которая будет отслеживать состояние внутренних служб и датчиков – statesInit(true);
  7. Запускаем одну или обе шины I2C (по необходимости) – initI2C(). При этом scanI2C(); позволяет вывести в лог все устройства на шине, что иногда облегчает диагностику на начальном этапе.
  8. Запускаем “минутный” таймер и службу расписаний – schedulerEventHandlerRegister();. В большинстве случаев для суточных и недельных прикладных расписаний секунды не важны, но желательно отмечать начало каждой минуты, чем она и занимается.
  9. Подключаем обработчик PING-ера, который служит для периодической проверки доступа в сеть интернет – pingerEventHandlerRegister(); На самом деле пигнер в этот момент не стартует, а будет запущен только после того, как в цикле событий будет сигнал об успешном подключении к WiFi.
  10. Запуск и регистрация службы синхронизации времени – sntpTaskCreate(true); Здесь же могут быть подключены микросхемы часов реального времени.
  11. Запуск MQTT клиента – mqttTaskStart(true); Опять же, собственно запуска не происходит, просто выполняется инициализация библиотеки и клиент переходит в режим ожидания подключения к WiFi сети.
  12. Регистрируем обработчики событий для системы хранения параметров – paramsEventHandlerRegister();
  13. Если включены telegram-уведомления – запускаем задачу отправки уведомлений – tgTaskCreate();
  14. Запускаем еще одну задачу, которая будет отправлять данные на ThingSpeak, OpenMonitoring или NarodMon одновременно – dsTaskCreate(false);
  15. Наконец, запускаем прикладные задачи, которые лежат в папке lib – например sensorsTaskStart(); Здесь можно запустить несколько прикладных задач, в зависимости от назначения устройства. 
  16. Последним этапом запускаем службу WiFi – wifiStart(). С этого момента все приходит в окончательное движение через систему событий и main.cpp завершает свою работу.

 


Перечень модулей и библиотек

Ну и наконец, перечислю состав модулей в папке и их назначение C:\PlatformIO\libs

  • certs – здесь просто расположены файлы сертификатов ЦС, используемые для TLS-соединений
  • consts – в этом каталоге собраны параметры и настройки, по аналогии с project_config.h, но используемые сразу во всех проектах. Как то: форматы дат и времени, форматы чисел, названия общих топиков и т.д.
  • clouds – в этом каталоге собраны библиотеки для работы с внешними сервисами:
    • reMqtt – клиент MQTT с возможностью переключения между локальным и облачным серверами “на лету”. По сути, это “обертка” вокруг штатного клиента ESP-IDF.
    • reDataSend – служба отправки данных на ThingSpeak, OpenMonitoring или NarodMon. Можно отключить с помощью макросов CONFIG_OPENMON_ENABLE, CONFIG_THINGSPEAK_ENABLE и CONFIG_NARODMON_ENABLE. Можно легко адаптировать для отправки данных на другие cloud-сервисы посредством REST API.
    • reTgSend – служба отправки уведомлений в Telegram. Можно отключить с помощью макросов CONFIG_TELEGRAM_ENABLE. Имеется встроенная очередь отправки, поэтому сообщения не будут потеряны даже в offline (при наличии свободной оперативной памяти, разумеется).
  • peripherals – библиотеки для работы с периферийным оборудованием, кроме датчиков и сенсоров:
    • reADCIntf – библиотека-обёртка для интерфейса ADC в ESP-IDF версии от 5.0.0 и выше. Просто для удобства использования
    • reAlarm – библиотека для создания охранно-пожарной сигнализации. Поддерживаются как проводные, так и беспроводные датчики. Несколько зон и типов реакции, например можно сделать защиту от протечек.  Можно использовать совместно с другим функционалом, например датчики движения использовать для управления освещением.
    • reBeep – простейшая библиотечка для пассивного зуммера (бипера) для подачи звуковых сигналов
    • reBinStat – отслеживание состояния цифрового входа и публикация этого состояния и времени переключения на MQTT в виде JSON
    • reDS1307 – драйвер часов реального времени на чипе DS1307
    • reDS3231 – драйвер часов реального времени на чипе DS3231
    • reElTariffs – контроль тарифов электроэнергии, если у вас установлен многотарифный счетчик. Пока находится в зачаточном состоянии
    • reGpio – контроль состояния входов с использованием прерываний и системы событий
    • reLCD – драйвер LCD1602 и LCD2004 через шину I2C с русификацией
    • reLedдрайвер мигающе-моргающего светодиода
    • reLoadCtrl – управление нагрузкой (реле или ключом) со счетчиками и белкджеком. Умеет сохранять счетчики в NVS и публиковать здоровенный JSON с подробными сведениями.
    • reMCP23017 – драйвер расширителя входов MCP23017 с прерываниями
    • rePCF8574 – драйвер расширителя входов PCF8574
    • reRangeMonitor – контроль за диапазонами температуры, влажности, напряжения и иных параметров с поддержкой уведомлений и JSON
    • reRTC – обобщающий модуль для часов реального времени
    • reRx433 – приемник сигналов по радиоканалу на частоте 433MHz. Для PIR-датчиков и пультов управления
    • reShutter – многошаговый драйвер для управления форточками, кранами и подобными устройствами с помощью мостовых схем
    • reTriStat – контроль состояния двух входов, и соответственно, трех состояний. В остальном похож на reBinStat.
  • sensors – здесь расположены драйверы для популярных датчиков и сенсоров:
    • reSensor – базовый класс для всех остальных драйверов сенсоров. Он предоставляет такие “услуги” как: фильтры по среднему и медианный; фиксацию и хранение экстремумов (минимумов и максимумов); генерацию JSON и т.д.
    • reADC – драйвер встроенных ADC входов ESP32. Можно использовать, например, для измерения напряжения аккумулятора
    • reAHT1x – драйвер для датчиков температуры и влажности ASAIR AHT10/AHT15/AHT20
    • reAM232x -драйвер для датчиков температуры и влажности ASAIR AM2320, AM2321
    • reBH1750 – драйвер для датчика освещенности BH1750
    • reBME280 – драйвер для датчика давления, температуры и влажности BME280
    • reBME68x – драйвер для датчика давления, температуры, влажности и качества воздуха BME680 без использования BSEC
    • reBMP280 – драйвер для датчика давления и температуры BMP280
    • reBSEC68x – драйвер для датчика давления, температуры, влажности и качества воздуха BME680 c использованием библиотеки BSEC
    • reCCS811 – драйвер для датчика качества воздуха CCS811
    • reCWTSoilS – драйвер для датчиков влажности почвы CWT-Soil-THCPH-S (подключение через RS485 Modbus RTU)
    • reDHTxx – драйвер для датчиков температуры и влажности ASAIR DHT11 / DHT12 / DHT21 / DHT22
    • reDS18x20 – драйвер для датчиков температуры семейства Dallas DS18x20
    • reFXJT – драйвер для флюгера RS-FXJT-N01 на шине RX485
    • reHTU2x – драйвер для датчиков температуры и влажности серий HTU2xD / SHT2x / Si7021
    • reMD02 -драйвер для датчика XY-MD02 (SHT20 over RS485)
    • reMoisture – драйвер для емкостных датчиков влажности Capacitive Soil Moisture Sensor v1.2 или аналогичных
    • reQDY30A – драйвер для датчика уровня жидкости QDY30A (подключение через RS485 Modbus RTU)
    • reSHT3x -драйвер для датчиков температуры и влажности SHT30D/SHT31D/SHT35D с нагревателем и порогами
    • reTH485 – универсальный драйвер для датчиков температуры и влажности и шины RS485 Modbus RTU
  • system – набор общих библиотек
    • reCerts – поддержка централизованного хранилища TLS-сертификатов
    • reEsp32 – здесь собраны все общие системные функции, функции отладки и макросы перехвата ошибок
    • reEvents – прикладной цикл событий и объявление типов событий
    • reI2C – обертка стандартной библиотеки i2c.h для удобства использования
    • reNotifier – класс для генерации уведомлений о сбоях с возможностью “отложить” уведомления на заданное время
    • reNvs – обертка стандартной библиотеки NVS для большего удобства. 
    • reOTA – готовый модуль для OTA обновлений
    • reParams – библиотека для управления системными и прикладными параметрами прошивки. Умеет хранить переменные в NVS, подписываться на топики конфигурации на MQTT сервере, отправлять уведомления об изменении и многое другое. Вам нужно только зарегистрировать вашу переменную в списке параметров, остальной библиотека берет на себя
    • reScheduler – как следует из названия, это служба расписаний. Контролируется начало каждой новой минуты (00 секунд) и рассылается соответствующее событие через прикладной цикл событий
    • reStates – модуль для контроля состояния системы: подключения к wifi и брокеру, состояния датчиков и т.д. Сбои и ошибки индицируются разным режимом вспышек на системном светодиоде, а также отправляются пользователю в виде уведомлений.
    • reSysInfo – служит для периодической публикации на MQTT-брокере системной информации. Можно отключить
    • rLog – библиотека для вывода отладочных сообщений вроде ESP_LOG.
    • rStrings – библиотека для работы с динамическими строками в памяти. Здесь же пока расположены функции генерации топиков по неким “стандартным” правилам, но позже они переедут в другой моудль.
    • rTypes – объявления базовых типов данных и некоторые функции для работы с ними
  • wifi – всё, что связано с подключением к сети и интернету
    • rePing – библиотека для пинга произвольных серверов в сети с ожиданием завершения
    • rePinger – тоже пингер, но только для контроля доступа в сети интернет. Пингуется обычно yandex.ru и google.com, но их можно изменить
    • reSNTP – обертка вокруг esp_sntp.h для запуска службы синхронизации времени
    • reWiFi – модуль для подключения и поддержания соединения к сети wifi с возможностью указания до 5 сетей. 

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

 


На этом пока всё, до встречи на сайте и на telegram-канале! 

💠 Полный архив статей вы найдете здесь


Пожалуйста, оцените статью:
[ 5 из 5, всего 3 оценок ]

8 комментариев для “Прошивка для ESP32 на основе ESP-IDF”

  1. Здравствуйте! С удовольствием читаю Ваши статьи. Хочу задать немного отвлечённый вопрос. Есть интересный проект, SIP-звонок для домофона, реализованный на ESP-IDF под ESP32. Хочу его повторить, но никак не получается его скомпилировать. Выдаёт ошибку: “undefined reference to `app_main'”. Вы, как человек, разбирающийся в ESP-IDF, могли бы посмотреть, почему проект не компилируется, конечно, если это Вам интересно? Я задал вопрос на ru.stackoverflow.com, но пока глухо как в танке. И все мои попытки разобраться, почему же так происходить пока не дали результатов.

    Проект sip-call: https://github.com/sikorapatryk/sip-call
    Вопрос на stackoverflow: https://ru.stackoverflow.com/questions/1572478/%d0%9d%d0%b5-%d0%bc%d0%be%d0%b3%d1%83-%d1%81%d0%ba%d0%be%d0%bc%d0%bf%d0%b8%d0%bb%d0%b8%d1%80%d0%be%d0%b2%d0%b0%d1%82%d1%8c-%d0%bf%d1%80%d0%be%d0%b5%d0%ba%d1%82-%d0%b4%d0%bb%d1%8f-esp-idf

    С уважением, Олег

    1. Здравствуйте. А в чем вы его пытались компилировать? Проект в исходном виде создан для Espressif IDE. Если нужно для PlatformIO к примеру – его нужно чутка переделывать. В Arduino IDE вообще не получится.

          1. Я вроде бы понял, в чём причина, правда, решения пока не нашёл – папка “main”, как и каждый компонент в папке “components”, должны содержать файл “CMakeList.txt”, в которых описываются зависимости проекта, а этих файлов в проекте нет. Видимо автор проекта забыл их запушить в репозиторий. Осталось теперь понять, какое содержимое должно быть в этих файлах

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

    Ваш адрес email не будет опубликован. Обязательные поля помечены *