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

Термостат на ESP32 с удаленным управлением. Часть 3. Телеметрия

Добрый день, уважаемый читатель! В этой части я расскажу, как создать готовую прошивку на основе моего шаблона. Для начала это будет только метеостанция с удаленным управлением:

  • Измерение температуры и влажности в трех точках с заданным интервалом времени
  • Отправка измеренных данных на MQTT брокер в JSON-виде
  • Контроль температуры в заданных пределах с уведомлениями на смартфон

Что потребуется для начала работы

Я не зря написал “кучу ненужных и бесполезных” статей на своем канале – да кому они нужны? Вот сейчас все они нам и понадобятся – в них описаны некоторые подготовительные шаги. Если вам всё это известно и не интересно, можете их пропустить; если нет – ссылки ниже. Далее все подготовительные работы по пунктам.

  1. Установить Visual Studio Code и PlatformIO. В Arduino IDE собрать проект не получится
  2. Потребуется собрать устройство или хотя-бы его прототип на макетной плате, чтобы можно было подключить датчики

Данный проект настроен для следующих сенсоров:

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

  1. Выбрать любой публичный MQTT брокер и создать на нём учетную запись. Если есть желание и роутер keenetic – можно дополнительно создать свой личный MQTT брокер, но это строго опционально.
  2. Зарегистрировать Telegram – бота – он понадобится для уведомлений

Так же советую ознакомиться со статьями по настройке проекта. Создавать проект вручную и настраивать ESP-IDF пока не потребуется – на GitHub имеется уже готовый настроенный проект, вся работа будет вестись только в файле project_config.h

 


Создаем проект из готового прототипа

Открываем ссылку проекта на GitHub: https://github.com/kotyara12/telemeter_dzen

Под строкой меню, над списком файлов, в левом углу вы найдете выпадающий список “ветвей” (branchs) проекта. Ветви будут содержать отдельные этапы проекта, соответствующие статьям. В ветке master содержится последняя, самая актуальная версия проекта с самым полным функционалом на текущий момент. Но для данной статьи нам будет нужна ветвь 01_telemeter (хотя это и не обязательно, можно скачать и сразу master).

1. Создайте на диске C каталог PlatformIO, то есть C:\PlatformIO\.

Вы можете использовать любой другой диск и каталог, но в этом случае вам придется изменять настройки в нескольких файлах конфигурации. Если вы не готовы к этому, то оставьте “как есть”, то есть C:\PlatformIO\.

2. На сайте GitHub скачайте репозиторий в виде ZIP-архива

3. Переместите архив в папку C:\PlatformIO\ и распакуйте его. У вас должно получиться примерно следующее:

4. Переименуйте папку в telemeter_dzen, “обрезав хвост”. Архив тоже можно удалить, за ненадобностью.

5. Внутри папки найдете файл “libs_local_xxxxx.zip”, переместите его в C:\PlatformIO\ и распакуйте. У вас должно получиться так:

6. Запустите VS Code и откройте папку проекта C:\PlatformIO\telemeter_dzen через меню “Файл” – “Открыть папку”.

7. Подождите, пока пропадет надпись “Loading tasks…” и попробуйте скомпилировать проект, нажав кнопку “PlatformIO : Build” ✔ на нижней панели. Если вы всё сделали правильно, через несколько минут вы должны получить в терминале такое сообщение:

 


Настройка проекта

Теперь нужно настроить проект под ваши данные.

Откройте файл include\project_config.h и начинайте внимательно его просматривать:

Что здесь нужно изменить? Там очень много различных параметров, но не все нужно сразу же изменять, в этой статье я обращу внимание на самые основные. Можете ориентироваться по номерам строк в файле.

1. Находим раздел “WiFi сети” и настраиваем параметры подключения к WiFi. Я рекомендую использовать режим нескольких сетей:

Укажите здесь все доступные вашему устройству WiFi сети и пароли к ним. Лишние снизу обязательно закомментируйте.

Устройство запоминает последнюю сеть, к которой удалось успешно подключиться, и при следующем запуске попытается подключиться именно к ней. Если к ней не удалось подключиться в течении какого-то времени, то выполняются попытки подключиться к другим сетям. То есть все настроенные сети равноценны, устройство сможет работать с любой из них.

Я настоятельно рекомендую добавить в этот список “запасную” WiFi сеть, которую вы можете “раздать” с вашего мобильного устройства. Зачем? Представьте себе ситуацию: вы создали устройство, отладили и установили внутри какого-то ящика глубоко-далеко. Например внутри кухонной вытяжки или в гараже. Достать конечно можно, но очень долго и очень неохота… И надо же такому случиться – вышел из строя ваш любимый роутер, и вам пришлось заменить его чем-то другим. Как перепрошить устройство на новую сеть? Вот тут и придет на помощь ваша “запасная” сеть – вы раздаете wifi со смартфона, через какое-то время устройство подключается к ней и вы спокойно обновляете прошивку через ОТА. Готово, “и зверей убивать не надо” (с) Простоквашино

 

2. Настраиваем MQTT клиент. В прошивке вы можете использовать два сервера – основной и резервный (например локальный и облачный). Цель точно та же самая, что и в случае с “запасной” WiFi сетью – не потерять управление над устройствами в случае выхода из строя основного сервера. Но для простоты в примере прошивки указан только один сервер.

  • CONFIG_MQTT1_HOST – здесь указываем имя или адрес сервера (без префиксов “ssl://” и ‘tcp://’)
  • CONFIG_MQTT1_PORT_TCP – здесь указываем порт сервера по протоколу TCP без использования шифрования (стандартное значение 1888)
  • CONFIG_MQTT1_PORT_TLS – здесь указываем порт сервера по протоколу TLS c использованиtv шифрования (стандартное значение 8888)
  • CONFIG_MQTT1_USERNAME – укажите логин подключения к брокеру
  • CONFIG_MQTT1_PASSWORD – укажите пароль подключения к брокеру
  • CONFIG_MQTT1_TLS_ENABLED – поставьте 1, если нужно использовать безопасное подключение или 0 – передавать всё в открытом виде. Параметры сертификата сервера пока не трогаем, для большинства облачных брокеров подходят настройки “по умолчанию”. Проверка TLS серnификатов в ESP-IDF довольно заумная тема, она требует отдельной большой статьи
  • CONFIG_MQTT1_PUB_LOCATION – локация для публичных топиков. Локация определяет, где установлено устройство, например “office” или “village”
  • CONFIG_MQTT1_LOC_LOCATION – локация локальных топиков. Локальные топики используются только для взаимного обмена данными между устройствами и не должны быть использованы внешним пользователем
  • CONFIG_MQTT1_PUB_DEVICE и CONFIG_MQTT1_LOC_DEVICE – название устройства для публичных и локальных топиков. Если Вам нужна более сложная структура, чем “location/device/…”, вы можете прописать здесь что-то вроде “home/toilet” или “home/kitchen”
  • CONFIG_MQTT1_PUB_PREFIX и CONFIG_MQTT1_LOC_PREFIX – постоянный префикс всех топиков для данного брокера. Некоторые публичные брокеры требуют, чтобы топик начинался с определенной строки, например “/” или “user1233445/” – вот эти данные и следует здесь указать, если необходимо. Если такой необходимости нет – закомментируйте эти строки.

В отличие от WiFi резервный сервер – только временная замена основному. Если устройство переключилось на резервный сервер, то через 5-15 минут (в зависимости от настроек), оно попытается переключиться на основной сервер.

 

3. Настраиваем уведомления в Telegram. Надеюсь, вы создали бота в telegram? Если нет, самое время это сделать. Находим раздел “Уведомления в Telegram”:

Здесь нужно указать следующие параметры:

  • CONFIG_TELEGRAM_TOKEN – здесь вы указываете токен бота, который вы получили при его создании
  • CONFIG_TELEGRAM_CHAT_ID_xxx – укажите идентификаторы чатов или каналов (или можно даже пользователей), куда будут отправляться уведомления соответствующей категории. И таки да, это не я ошибся, это именно так – в кавычках (строка)!

На этом начальную настройку файла конфигурации можно считать законченной. Остальные параметры пока не трогаем. Не забудьте сохранить изменения в файле.

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

 


Первый запуск

Подключаем ESP32 к компьютеру с помощью кабеля. Лучше всего на время прошивки вынуть ESP32 из панельки на плате, иначе иногда PlatformIO не может подключиться к контроллеру.

Загружаем прошивку. После загрузки откройте монитор порта, если вы все сделали правильно, то в терминале вы должны увидеть примерно следующее:

У меня куча ошибок – “ругается” на сенсоры, которые пока никто и не думал подключать…

Если вы зарегистрировал telegram-бота, через несколько секунд должны появиться первые сообщения, в основном чате:

Не обращайте внимание на надпись “Гараж” – я просто использовал токен от неиспользуемого в данный момент устройства.

Если датчики вы еще не подключали, как и я, то в сервисном чате вы увидите уведомления от их неисправности:

Теперь давайте попробуем подключиться к MQTT-брокеру, например с помощью MQTT Explorer. Здесь вы должны увидеть примерно такую картину:

 


Поздравляю Вас! Вы успешно запустили первую прошивку. 👍

Можно подключить сенсоры, и проверить как они работают, если вы ещё этого не сделали.

На этом пока всё, рассказывать про структуру топиков я буду в следующей статье, так как информации достаточно много.


 

Все статьи цикла “Термостат и ОПС”:

Прошивка K12 для ESP32 и ESP-IDF:

Дополнительные статьи, которые применимы к любым устройствам, запрограммированным с помощью тех же самых библиотек.


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

15 комментариев для “Термостат на ESP32 с удаленным управлением. Часть 3. Телеметрия”

  1. Доброго времени, Александр.
    С упоением читаю ваши статьи. решил вот попробовать запустить проект.
    Все вроде по инструкции делаю. Но как обычно и бывает, сразу не взлетает. 🙂
    Пишет следующее:
    libs/clouds/reTgSend/src/reTgSend.cpp:62:12: fatal error: esp_crt_bundle.h: No such file or directory

    ************************************************************************
    * Looking for esp_crt_bundle.h dependency? Check our library registry!
    *
    * CLI > platformio lib search “header:esp_crt_bundle.h”
    * Web > https://registry.platformio.org/search?q=header:esp_crt_bundle.h
    *
    ************************************************************************

    #include “esp_crt_bundle.h”
    ^~~~~~~~~~~~~~~~~~
    compilation terminated.
    Compiling .pio\build\esp32dev\libf3f\reNotifier\reNotifier.o
    *** [.pio\build\esp32dev\libf6d\reTgSend\reTgSend.o] Error 1
    ========================================================================== [FAILED] Took 67.67 seconds

    1. Доброго времени.

      После обновления ESP-IDF до версии 4.4.3 при сборке проекта PIO начинает выдавать ошибку:

      C:/PlatformIO/libs/clouds/reTgSend/src/reTgSend.cpp:63:12: fatal error: esp_crt_bundle.h: No such file or directory

      Looking for esp_crt_bundle.h dependency? Check our library registry!

      CLI > platformio lib search “header:esp_crt_bundle.h”

      Web > https://registry.platformio.org/search?q=header:esp_crt_bundle.h

      #include “esp_crt_bundle.h”

      ^~~~~~~~~~~~~~~~~~

      compilation terminated.

      *** [.pio\build\esp32dev\libdc6\reTgSend\reTgSend.o] Error 1

      Для решения проблемы замените вызов

      #include “esp_crt_bundle.h”

      на

      #include “mbedtls/ssl.h”

  2. Добрый день, Александр!
    При компиляции проекта работа завершается с ошибками:

    Compiling .pio\build\esp32dev\app_update\esp_ota_app_desc.o
    Archiving .pio\build\esp32dev\esp-idf\app_trace\libapp_trace.a
    In file included from C:/PlatformIO/libs/system/reStates/include/reStates.h:23,
    from src/main.cpp:16:
    C:/PlatformIO/libs/system/reEvents/include/reEvents.h:155:5: error: ‘ip_addr_t’ does not name a type; did you mean ‘in_addr_t’?
    155 | ip_addr_t host_addr;
    | ^~~~~~~~~
    | in_addr_t
    In file included from C:/PlatformIO/libs/clouds/reMqtt/include/reMqtt.h:26,
    from C:/PlatformIO/libs/system/reParams/include/reParams.h:27,
    from C:/PlatformIO/libs/system/reStates/include/reStates.h:24,
    from src/main.cpp:16:
    C:/PlatformIO/libs/wifi/reWiFi/include/reWifi.h:46:1: error: ‘wifi_mode_t’ does not name a type
    46 | wifi_mode_t wifiMode();
    | ^~~~~~~~~~~
    C:/PlatformIO/libs/wifi/reWiFi/include/reWifi.h:47:1: error: ‘wifi_ap_record_t’ does not name a type
    47 | wifi_ap_record_t wifiInfo();
    | ^~~~~~~~~~~~~~~~
    C:/PlatformIO/libs/wifi/reWiFi/include/reWifi.h:51:1: error: ‘esp_netif_ip_info_t’ does not name a type
    51 | esp_netif_ip_info_t wifiLocalIP();
    | ^~~~~~~~~~~~~~~~~~~
    Compiling .pio\build\esp32dev\bootloader_support\src\bootloader_common.o
    Compiling .pio\build\esp32dev\bootloader_support\src\bootloader_common_loader.o
    *** [.pio\build\esp32dev\src\main.o] Error 1
    ================================== [FAILED] Took 86.86 seconds ===========================
    Что-то не так установилось в PlatformIO?

    1. Добрый день!

      Попробуйте добавить #include “lwip/ip_addr.h”

      Странно, но у меня компилируется и так, хотя, по идее, и у меня должно было бы “ругаться”

  3. Спасибо за подсказу, Александр!
    После добавления в файл C:\PlatformIO\libs\system\reEvents\include\reEvents.h
    #include “lwip/ip_addr.h”
    Первая ошибка компиляции исчезла. Две другие ошибки удалось убрать добавлением в C:\PlatformIO\libs\wifi\reWiFi\include\ reWifi.h
    #include “esp_wifi_types.h”
    #include “esp_netif_types.h”
    После устранения этих трёх ошибок компиляция продолжалась довольно долго, но опять остановилась с ошибкой:
    C:/PlatformIO/libs/system/rLog/src/rLog.cpp:37:8: error: ‘xSemaphoreHandle’ does not name a type; did you mean ‘SemaphoreHandle_t’?
    37 | static xSemaphoreHandle _rlog_mutex;
    | ^~~~~~~~~~~~~~~~
    | SemaphoreHandle_t

    Нашёл, что xSemaphoreHandle определяется в файле FreeRTOS.h, которй включатся в строке 34 файла rLog.cpp
    /* FreeRTOS enabled */

    #include “freertos/FreeRTOS.h”
    #include “freertos/semphr.h”

    static xSemaphoreHandle _rlog_mutex;

    void _rlog_lock()

    Но, если открыть файл FreeRTOS.h, то определение xSemaphoreHandle влючается по условию, а configENABLE_BACKWARD_COMPATIBILITY = 0 во время компиляции:

    #if configENABLE_BACKWARD_COMPATIBILITY == 1
    #define eTaskStateGet eTaskGetState
    #define portTickType TickType_t
    #define xTaskHandle TaskHandle_t
    #define xQueueHandle QueueHandle_t
    #define xSemaphoreHandle SemaphoreHandle_t

    Подскажите, что и где надо поправить?

    1. Добрый день!
      По поводу последней ошибки (rLog), то оно конечно, нужно заменить на SemaphoreHandle_t. Эту библиотеку я уже довольно давно написал, вполне возможно, там уже что-то могло и изменится.
      С остальными включениями вы тоже, наверное, все правильно сделали.

      🤔 У меня только один вопрос – почему же у меня на трех контуперах проект продолжает собираться без проблем и ошибок. Совершенно непонятно. Особенно с логами – должно же было как-то проявится. Но нет.

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

  4. Фурман А.

    Огромное спасибо за Ваш труд! Сделал все по инструкции. ESP шка шлет данные как положено.

  5. Александр

    Здравствуйте, при компиляции выскакиевает такая ошибка:
    — git rev-parse returned ”
    — Configuring incomplete, errors occurred!
    See also “C:/PlatformIO/telemeter_dzen/.pio/build/esp32dev/CMakeFiles/CMakeOutput.log”.

    CMake Warning at C:/Users/Mark/.platformio/packages/framework-espidf/tools/cmake/git_submodules.cmake:1 (find_package):
    By not providing “FindGit.cmake” in CMAKE_MODULE_PATH this project has
    asked CMake to find a package configuration file provided by “Git”, but
    CMake did not find on.

    подскажите как исправить??

  6. Александр

    Спасибо, установил заново все пошло. Теперь при компиляции проекта выскакивают другие ошибки, что то с библиотекой или я опять что то не то установил?? Не понимаю что делать, помогите)

    src/main.cpp: In function ‘void app_main()’:
    src/main.cpp:77:11: error: invalid conversion from ‘int’ to ‘i2c_port_t’ [-fpermissive]
    77 | initI2C(0, CONFIG_I2C_PORT0_SDA, CONFIG_I2C_PORT0_SCL, CONFIG_I2C_PORT0_PULLUP, CONFIG_I2C_PORT0_FREQ_HZ);
    | ^
    | |
    | int
    In file included from src/main.cpp:25:
    C:/PlatformIO/libs/system/reI2C/include/reI2C.h:42:31: note: initializing argument 1 of ‘bool initI2C(i2c_port_t, int, int, bool, uint32_t)’
    42 | bool initI2C(const i2c_port_t i2c_num, const int sda_io_num, const int scl_io_num, const bool pullup_enable, const uint32_t clk_speed);
    | ~~~~~~~~~~~~~~~~~^~~~~~~
    src/main.cpp:78:11: error: invalid conversion from ‘int’ to ‘i2c_port_t’ [-fpermissive]
    78 | scanI2C(0);
    | ^
    | |
    | int
    C:/PlatformIO/libs/system/reI2C/include/reI2C.h:82:25: note: initializing argument 1 of ‘void scanI2C(i2c_port_t)’
    82 | void scanI2C(i2c_port_t i2c_num);
    | ~~~~~~~~~~~^~~~~~~
    src/main.cpp:79:11: error: invalid conversion from ‘int’ to ‘i2c_port_t’ [-fpermissive]
    79 | initI2C(1, CONFIG_I2C_PORT1_SDA, CONFIG_I2C_PORT1_SCL, CONFIG_I2C_PORT1_PULLUP, CONFIG_I2C_PORT1_FREQ_HZ);
    | ^
    | |
    | int
    C:/PlatformIO/libs/system/reI2C/include/reI2C.h:42:31: note: initializing argument 1 of ‘bool initI2C(i2c_port_t, int, int, bool, uint32_t)’
    42 | bool initI2C(const i2c_port_t i2c_num, const int sda_io_num, const int scl_io_num, const bool pullup_enable, const uint32_t clk_speed);
    | ~~~~~~~~~~~~~~~~~^~~~~~~
    src/main.cpp:80:11: error: invalid conversion from ‘int’ to ‘i2c_port_t’ [-fpermissive]
    80 | scanI2C(1);
    | ^
    | |
    | int
    C:/PlatformIO/libs/system/reI2C/include/reI2C.h:82:25: note: initializing argument 1 of ‘void scanI2C(i2c_port_t)’
    82 | void scanI2C(i2c_port_t i2c_num);

    1. Это новая версия ESP-IDF. Прошивка была создана ещё под 5.0, а у вас уже 5.1.
      Это неизбежно, фреймворки изменяются и дорабатываются регулярно. В том числе и Arduino32.

      Просто посмотрите какие аргументы системных функций изменились.
      В данном конкретном случае замените 0 на I2C_NUM_0, а 1 на I2C_NUM_1, и всё заработает

  7. Тоже возникли проблемы с компиляцией.

    re_mqtt_event_data_t::host определен как char[32] в reEvents.h
    а далее в reStates.cpp проверяется существование “if (data->host)” на что ругается компилятор.
    не знаю насколько корректна замена на “if (data->host[0] != 0)”, но как минимум ошибку сняло

Добавить комментарий для Kirill Отменить ответ

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