- BrainTools - https://www.braintools.ru -
Наверное каждый любитель электроники имеет в запасе модули приобретенные на всякий случай. Так несколько лет назад я не смог пройти мимо 1.5 дюймового E-Ink дисплея, лежащего на витрине радиомагазина. Через некоторое время нашлось для него применение. В статье ESP32 E-Paper Thermometer [1] описывается, как отображать окружающую температуру, измеренную с помощью датчика DS18B20. Проект выполнен в Arduino IDE. Но я решил пройти “Путь самурая” и портировать [2] код на ESP-IDF. Пришлось немного повозится с библиотеками для работы с дисплеем. На этом мой путь не окончился, как говорят: “У самурая нет цели, есть только путь”. И я решил, что было бы неплохо добавить еще несколько сенсоров, измеряющих влажность, давление, CO2, а потом отправлять эти данные по MQTT. В том же радиомагазине был приобретен фанерный домик-конструктор со светодиодным ночником. А в другом магазине – модуль с датчиками. Таким образом родилась идея сконструировать Micro-smart-home. На передней части домика расположен дисплей на пластиковых стойках. А с другой стороны расположен модуль с сенсорами.

Вид со стороны модуля с сенсорами

В проекте используется модуль ESP32, приобретенный несколько лет назад.
Эта картинка соответствует его реальной распиновке. По размером он как раз помещается в домик. На картинке со стороны сенсоров видны пару винтов – это ESP32 крепится ими к боковой стенке.
Процессор: Tensilica Xtensa LX6.
Память [3]:
SRAM: до 520 КБ.
Flash: 4 МБ.
Беспроводная связь:
Wi-Fi 802.11 b/g/n.
Bluetooth 4.2 (BR/EDR и BLE).
Интерфейсы:
UART, SPI, I2C, I2S, PWM, ADC, DAC, GPIO.
GPIO: 25. (те что на модуле без учета питания и EN)
Подробнее в документации [4]
Это модуль [5] с диагональю 1.54 дюйма и разрешением 200×200 пикселей. Оснащён встроенным контроллером и использует интерфейс SPI для связи. Поддерживает частичное обновление экрана.
Благодаря таким преимуществам, как сверхнизкое энергопотребление, широкий угол обзора и возможность сохранять изображение без подачи питания, этот дисплей идеально подходит для использования в электронных ценниках, промышленных приборах и других встраиваемых системах.
Wiki [6] страничка.
Отличие моего экземпляра в том, что у модуля имеется дополнительный набор выводов внизу. К этим выводам можно подключать стандартные перемычки.
Не требует подсветки, сохраняет последнее изображение даже при отключении питания
Сверхнизкое энергопотребление — питание требуется в основном только при обновлении
Интерфейс SPI, совместим с такими платами, как Raspberry Pi, Arduino, STM32, ESP32 и др.
Встроенный преобразователь уровней напряжения, подходит для микроконтроллеров с питанием 3.3В и 5В
Поставляется с примерами кода и документацией (поддержка Raspberry Pi, Jetson Nano, Arduino, STM32)
Рабочее напряжение: 3.3В / 5В
Интерфейс: 3-проводный SPI, 4-проводный SPI
Габаритные размеры: 48 мм × 33 мм
Размер области отображения: 27.6 мм × 27.6 мм
Шаг пикселя: 0.138 мм × 0.138 мм
Разрешение: 200 × 200 пикселей
Цвета отображения: черный, белый
Уровни серого: 2
Время частичного обновления: 0.3 с
Время полного обновления: 2 с
Потребляемая мощность при обновлении: ~26.4 мВт
Потребляемая мощность в режиме ожидания: <0.017 мВт
Угол обзора: >170°
|
Обозначение |
Назначение |
|---|---|
|
VCC |
Питание 3.3В / 5В |
|
GND |
Земля |
|
DIN |
SPI — линия MOSI |
|
CLK |
SPI — линия SCK |
|
CS |
Выбор чипа SPI, активный уровень — низкий |
|
DC |
Выбор данных/команды (высокий уровень — данные, низкий — команда) |
|
RST |
Аппаратный сброс, активный уровень — низкий |
|
BUSY |
Статус занятости, активный уровень — высокий |
DS18B20 — это цифровой датчик температуры, работающий по протоколу 1-Wire. Устройство поддерживает настраиваемое разрешение измерений от 9 до 12 бит и может сохранять полученные данные во встроенной энергонезависимой памяти (EEPROM). Благодаря поддержке 1-Wire-интерфейса, датчик может функционировать как в одиночном режиме, так и в составе сети, объединённой общей шиной, управляемой центральным микроконтроллером.
Диапазон измеряемых температур составляет от -55 до +125 °C. В пределах температур от -10 до +85 °C точность измерения достигает ±0.5 °C. В случае отсутствия внешнего источника питания датчик может использовать паразитное питание, получаемое непосредственно от линии передачи данных.
Каждый экземпляр DS18B20 имеет уникальный 64-битный идентификационный код. Этот код состоит из 8-битного кода семейства (28h), 48-битного серийного номера и контрольной суммы CRC (8 бит). Такая структура позволяет использовать множество датчиков на одной линии, обеспечивая их индивидуальную адресацию и управление с помощью одного микроконтроллера, даже если они распределены на значительном расстоянии друг от друга.
Основные параметры DS18B20:
интерфейс связи: 1-Wire;
диапазон рабочих температур: -55…+125 °C;
точность: ±0,5 °C в пределах от -10 до +85 °C;
формат хранения температуры: 9-битное значение;
максимальное время преобразования: 750 мс.
Внутренняя структура памяти DS18B20 включает как оперативную (RAM), так и энергонезависимую (EEPROM) части. В частности:
байты 0 и 1 содержат результат измерения температуры;
байты 2 и 3 — верхний (TH) и нижний (TL) температурные пороги;
байты 4 и 5 не используются;
байты 6 и 7 — счётчики, применяемые для повышения точности;
байт 8 содержит CRC-код для проверки целостности данных.
Дополнительные команды датчика, помимо стандартных для всех 1-Wire-устройств:
Alarm Search (ECh) — поиск датчиков с тревожным значением температуры (вышедшей за пределы TH или TL);
Convert T (44h) — запуск процесса измерения температуры и сохранения результата в памяти;
Write Scratchpad (4Eh) — запись TH, TL и байта конфигурации в RAM;
Read Scratchpad (BEh) — чтение 9 байтов RAM, включая данные температуры и CRC;
Copy Scratchpad (48h) — перенос значений TH и TL из RAM в EEPROM.
Процедура получения данных температуры:
Инициализация шины 1-Wire (reset и поиск устройств).
Отправка команды 0x44 для начала преобразования температуры.
Ожидание завершения измерения (не менее 750 мс).
Отправка команды 0xBE для чтения содержимого RAM (температурные данные находятся в первых двух байтах).
DS18B20 поддерживает два варианта питания: стандартное (трёхпроводное подключение) и паразитное (двухпроводное), что позволяет гибко интегрировать датчик в разнообразные схемы и устройства.
Данный модуль можно найти на Aliexpress [7].
Модуль объединяет три цифровых датчика — CCS811, HDC1080 и BMP280, обеспечивая измерение параметров качества воздуха, включая уровень летучих органических соединений (TVOC), влажность, температуру и атмосферное давление. Все датчики подключаются через стандартный интерфейс I2C, что упрощает интеграцию в различные проекты.
Основу контроля за загрязнением воздуха в помещении составляет газоанализатор CCS811, способный определять широкий спектр летучих органических соединений (TVOC) и рассчитывать эквивалентную концентрацию углекислого газа (eCO₂). Такие соединения зачастую присутствуют в воздухе из-за испарений от строительных материалов, бытовой электроники, офисного оборудования и даже дыхания [8] человека. Хотя CCS811 изначально проектировался для использования в компактной электронике вроде умных часов и смартфонов, его версия в модуле адаптирована для использования на макетных платах и в прототипах, благодаря удобным контактным площадкам.
CCS811 поддерживает несколько режимов работы, что позволяет эффективно управлять энергопотреблением. Это особенно важно при использовании в автономных и портативных устройствах. На плате предусмотрены дополнительные пины для подключения термистора NTC, который может применяться для температурной компенсации показаний. Для стабильной и точной работы рекомендуется выполнить “прогрев” датчика — первые 48 часов после начала эксплуатации, а также 20 минут после каждого включения питания.
HDC1080 — это цифровой сенсор температуры и влажности, разработанный компанией Texas Instruments. Он отличается компактностью, энергоэффективностью и точностью, что делает его отличным выбором для измерения микроклимата в помещениях.
Дополняет комплект BMP280 — прецизионный барометрический датчик от Bosch, который способен измерять атмосферное давление и температуру. Он поддерживает высокоскоростной обмен по шине I2C и требует минимального энергопотребления, что делает его подходящим для метеостанций, высотомеров и других IoT-приложений.
К недостаткам данного модуля я отнес бы то, что из-за нагревания сенсора CCS811, другие датчики показывают завышенную температуру где-то на 2 °C.
Диапазон измерения TVOC: 0–1187 ppb
Диапазон eCO₂: 400–8192 ppm
Режимы работы: 5 вариантов
Встроенный микроконтроллер для обработки данных
Интерфейс: I2C
Напряжение питания: 1.8–3.6 В
Температурная компенсация: с использованием внешнего датчика
Интерфейс: I2C
Напряжение питания: 2.7–5.5 В
Разрешение: 0.1
Влажность: 0–100% RH
Температура: от –40°C до +125°C
Точность: ±3% RH, ±0.2°C
Заводская калибровка, дополнительных компонентов не требует
Напряжение питания: 1.71–3.6 В
Скорость интерфейса I2C: до 3.4 МГц
Ток потребления: 2.7 μA при 1 Гц
Уровень шума: до 0.2 Па и 0.01°C
Диапазон давления: 300–1100 hPa (примерно от +9000 м до –500 м)
Интерфейс: I2C
Калиброван на заводе
Библиотека HDC1080 [10]
Библиотека CCS811 [12]
Библиотека BMP280 [14]
Схема подключения нарисована во Fridzing [15]. Библиотеки в основном скачивал готовые на просторах сети. Компонент для модуля CJMCU-8128 сделал по примеру на youtube [16]. Модуль ESP32, который используется в действительности немного отличается набором пинов от библиотечного, но в целом расположение выводов соответствует.

А так выглядит картинка Fritzing на Breadboard вкладке

проект файла e-home.fzz [17]
В исходном примере ESP32 E-Paper Thermometer проект выполнен в Arduino IDE. Библиотеки для работы с e-paper дисплеем и сенсорами модуля CJMCU-8128 также реализованы для Arduino. В первом варианте проекта я изрядно убил времени, чтобы собрать нужные исходные файлы и отредактировать существующие, а затем заставить работать дисплей на ESP-IDF. В обновленной версии проекта поступил намного проще. Первым делом создал новый проект в ESP-IDF 5.4.1 – последняя стабильная версия на момент написания. В ESP-IDF версии 5.x можно установить Arduino как зависимость [18].
idf.py add-dependency "espressif/arduino-esp32^3.0.2"
Далее собираем необходимые компоненты для работы дисплея. Клонируем следующие проекты в components каталог:
Adafruit-GFX-Library [19] – основная графическая библиотека для Adafruit дисплеев, предоставляющая общий набор графических примитивов.
Adafruit_BusIO [20] – вспомогательная библиотека для работы дисплея с I2C, SPI
GxEPD [21] – библиотека отображения на e-paper дисплее с общим базовым классом и отдельным классом ввода-вывода для Arduino.
BitmapGraphics.h [22] – необходим для отрисовки на дисплее пиктограммы термометра, символа °C и надписи Temperature.
Есть уже готовая реализация Adafruit-GFX-Library-ESP-IDF [23]. Я не пробовал работать с этой библиотекой, возможно с ней все проще. Также существует библиотека GxEPD2 [24], возможно попробую использовать её.
Библиотека GxEPD реализует абстрактные методы Adafruit-GFX-Library. Из GxEPD нам нужно только GxGDEH0154D67-исходники для данного типа дисплея. GxEPD используется в ESP32 E-Paper Thermometer проекте, поэтому остановился на ней. Компилятор ESP-IDF 5.4.1 ругается на то, что методы класса GxIO не переопределены. В ранних версиях IDF такой ошибки [25] не было. Проще всего можно добавить пустую реализацию методов или обозначить их как чисто виртуальные методы, добавив = 0 для виртуальных методов без реализации в заголовок GxIO.h.
virtual void writeDataTransaction(uint8_t d) = 0;
virtual void writeData16Transaction(uint16_t d, uint32_t num = 1) = 0;
virtual void writeCommand(uint8_t c) = 0;
virtual void writeData(uint8_t d) = 0;
virtual void writeData(uint8_t* d, uint32_t num) = 0;
virtual void writeData16(uint16_t d, uint32_t num = 1) = 0;
virtual void writeAddrMSBfirst(uint16_t d) = 0;
virtual void startTransaction() = 0;
virtual void endTransaction() = 0;
virtual void selectRegister(bool rs_low) = 0;
virtual void setBackLight(bool lit) = 0;
Для модуля датчиков CJMCU-8128 используются библиотеки Adafruit, CCS811 и ds18b20.
Adafruit_Sensor [26] – унифицированный модуль абстракции для сенсоров от Adafruit.
Adafruit_BMP280_Library [14] – библиотека для датчика измерения барометрического давления и температуры BMP-280.
Adafruit_Si7021 [27] – библиотека для датчика влажности/температуры Adafruit Si7021.
CCS811 [28] – библиотека Arduino для цифрового датчика газа CCS811 контроля качества воздуха в помещении.
ds18b20 [29] – простая библиотека для одного DS18B20 на ESP32.
Эти библиотеки можно подключить как компоненты IDF, или просто просто как файлы проекта в основном модуле. Для IDF 5.x существует DS18B20 Device Driver [30] с возможностью работы с многими DS18b20 сенсорами.
EventGroup — это механизм синхронизации задач в FreeRTOS. Он позволяет задачам или обработчикам событий общаться между собой с помощью набора битов (флагов), где каждый бит обозначает какое-то событие или состояние.
Создаётся группа событий wifi_event_group, внутри которой будет использоваться, например, бит BIT0 (часто это 1 << 0, то есть 0x01), чтобы отслеживать успешное подключение к Wi-Fi.
Подключение к Wi-Fi:
После запуска Wi-Fi и выполнения esp_wifi_connect() ESP32 пытается подключиться к точке доступа.
Успешное подключение и получение IP:
В обработчике IP-событий:
case IP_EVENT_STA_GOT_IP:
xEventGroupSetBits(wifi_event_group, BIT0);
Устанавливается бит BIT0 — это сигнал, что подключение завершено успешно (ESP32 получила IP от DHCP).
Ожидание в главной задаче:
В wifi_start():
xEventGroupWaitBits(wifi_event_group, BIT0, false, true, portMAX_DELAY);
Эта строка блокирует выполнение функции до тех пор, пока не будет установлен BIT0, т.е. пока устройство не подключится к Wi-Fi.
Это нужно для того, чтобы не продолжать запуск MQTT-клиента, пока не будет Wi-Fi подключения.
Создание группы событий (wifi_event_group) – используется для синхронизации статуса подключения.
Инициализация сетевого стека:
esp_netif_init() — инициализация TCP/IP стека.
esp_event_loop_create_default() — создание цикла обработки событий.
esp_netif_create_default_wifi_sta() — создание интерфейса Wi-Fi в режиме станции (STA).
Инициализация Wi-Fi:
esp_wifi_init() — инициализация драйвера Wi-Fi.
Регистрация обработчиков событий Wi-Fi и IP (esp_event_handler_instance_register).
Настройка подключения:
Задание SSID и пароля в структуре wifi_config_t.
Установка режима станции: esp_wifi_set_mode(WIFI_MODE_STA).
Применение конфигурации: esp_wifi_set_config().
Запуск Wi-Fi:
esp_wifi_start() — запуск Wi-Fi.
В WIFI_EVENT_STA_START вызывается esp_wifi_connect().
Обработка событий:
При отключении (WIFI_EVENT_STA_DISCONNECTED) — попытка повторного подключения.
При получении IP (IP_EVENT_STA_GOT_IP) — установка бита события (BIT0) в группе событий.
Ожидание подключения:
xEventGroupWaitBits(..., BIT0, ...) — блокирующее ожидание успешного подключения к Wi-Fi.
Исходный файл wifi.c [31].
Создание группы событий (mqtt_event_group) — для синхронизации при необходимости (в данном коде не используется явно).
Настройка MQTT клиента:
URI брокера: mqtt://192.168.1.107:1883.
Интервал Keepalive = 10 секунд.
Last Will сообщение при отключении: "0" в топик esp-home/status/activ (с флагом retain).
Инициализация и запуск:
esp_mqtt_client_init() — инициализация клиента.
esp_mqtt_client_register_event() — регистрация обработчика событий.
esp_mqtt_client_start() — запуск клиента.
Обработка событий MQTT:
MQTT_EVENT_CONNECTED — подписка на esp-home/cmnd/#.
MQTT_EVENT_SUBSCRIBED — публикация "1" в esp-home/status/activ.
MQTT_EVENT_DATA — вывод полученных сообщений (топик + данные).
Также логируются события отключения, ошибки, публикации и отписки.
Исходный файл mqtt.c [32].
Запуск системы:
Инициализация NVS (nvs_flash_init()).
Подключение к Wi-Fi (wifi_start()).
Запуск MQTT-клиента (mqtt_app_start()).
Создание задачи display_task:
Задача отвечает за работу с сенсорами, отображение данных и отправку по MQTT.
DS18B20 — температурный датчик на GPIO 25 (ds18b20_init()).
I2C-шина (SDA=33, SCL=32) — для остальных сенсоров.
Сенсоры:
CCS811 — датчик CO₂ и TVOC.
BMP280 — температура и давление.
Si7021 — температура и влажность.
E-ink дисплей — инициализация с пиктограммой.
Считывание значений с сенсоров:
DS18B20 – температура на улице.
BMP280 — температура и давление в помещении.
Si7021 — температура и влажность в помещении.
CCS811:
Установка климатических данных (темп./влажн.) для компенсации.
Получение CO₂ и TVOC.
Обновление e-link дисплея:
Показывается температура с DS18B20 (частичное обновление).
Формирование JSON-строки (sprintf) с измерениями:
Все значения сенсоров включаются в строку buffer в формате PAYLOAD.
Публикация данных через MQTT:
Тема: "esp-home/send".
Данные: buffer.
Задержка перед следующим измерением:
vTaskDelay(3000 / portTICK_PERIOD_MS); (3 секунды).
Исходный файл main.cc [33]
home-sensors/
├── components/
│ ├── Adafruit_BusIO/ # Adafruit I2C/SPI bus abstraction library
│ ├── Adafruit-GFX-Library/ # Adafruit graphics primitives for displays
│ ├── Adafruit-sensors/ # Adafruit sensors
│ ├── ds18b20/ # 1-Wire DS18B20 temperature sensor driver
│ ├── GxEPD/ # E-paper display driver library
│ └── ccs811/ # CCS811 air quality sensor driver
├── main/
│ ├── BitmapGraphics.h # Header for bitmap/e-paper graphics utilities
│ ├── wifi.h # Wi-Fi connection management header
│ ├── mqtt.h # MQTT client interface header
│ ├── main.cc # Main application entry point
│ ├── wifi.c # Wi-Fi connection management implementation
│ └── mqtt.c # MQTT client implementation
├── CMakeLists.txt # Project build configuration
└── README.md # Project overview and instructions
Исходный код проекта находится в этом репозитории [34].
Проект выполнен на ESP-IDF версии 5.4.1. Arduino-фреймворк подключен как зависимость espressif/arduino-esp32. Такой подход позволяет достаточно легко адаптировать различные готовые решения Arduino-платформы на ESP-IDF. Но иногда требуется доработка библиотек и CMakeLists.txt – файлов. Необходимо обращать внимание [35] на конфигурацию в исходниках библиотек, такую как инициализация портов ввода-вывода, шин I2C и прочего.
На ESP-IDF реализована логика [36] считывания данных из сенсоров: DS18B20, CCS811, BMP280, Si7021, CCS811 с помощью библиотек для среды Arduino.
Портирован исходный код из проекта ESP32 E-Paper Thermometer [1] для отображения температуры от датчика DS18B20 на E-Ink дисплее.
E-Ink дисплей подключен по SPI согласно дефолтной конфигурации в библиотеке.
Данные передаются по MQTT в домашнюю систему.
Автор: vladipirogov
Источник [37]
Сайт-источник BrainTools: https://www.braintools.ru
Путь до страницы источника: https://www.braintools.ru/article/15521
URLs in this post:
[1] ESP32 E-Paper Thermometer: https://www.instructables.com/ESP32-E-Paper-Thermometer
[2] портировать: https://github.com/vladipirogov/epaper-idf
[3] Память: http://www.braintools.ru/article/4140
[4] документации: https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf
[5] модуль: https://www.waveshare.com/1.54inch-e-paper-module.htm
[6] Wiki: https://www.waveshare.com/wiki/1.54inch_e-Paper_Module_Manual#ESP32.2F8266
[7] Aliexpress: https://www.aliexpress.com/item/32879540726.html
[8] дыхания: http://www.braintools.ru/article/4500
[9] Документация HDC1080 (даташит): https://www.ti.com/lit/gpn/hdc1080
[10] Библиотека HDC1080: https://github.com/jshnaidman/HDC1080/tree/master
[11] Документация CCS811 (даташит): https://cdn-learn.adafruit.com/assets/assets/000/044/636/original/CCS811_DS000459_2-00-1098798.pdf?1501602769
[12] Библиотека CCS811: https://github.com/sparkfun/SparkFun_CCS811_Arduino_Library/archive/master.zip
[13] Документация BMP280 (даташит): https://cdn-shop.adafruit.com/datasheets/BST-BMP280-DS001-11.pdf
[14] Библиотека BMP280: https://github.com/adafruit/Adafruit_BMP280_Library
[15] Fridzing: https://fritzing.org/
[16] youtube: https://www.youtube.com/watch?v=dfxx8wF3Uhs&t=1s
[17] e-home.fzz: https://github.com/vladipirogov/home-sensors/blob/main/e-home.fzz
[18] зависимость: https://docs.espressif.com/projects/arduino-esp32/en/latest/esp-idf_component.html
[19] Adafruit-GFX-Library: https://github.com/adafruit/Adafruit-GFX-Library
[20] Adafruit_BusIO: https://github.com/adafruit/Adafruit_BusIO
[21] GxEPD: https://github.com/ZinggJM/GxEPD
[22] BitmapGraphics.h: https://content.instructables.com/F5C/IQBC/KGKU4CZJ/F5CIQBCKGKU4CZJ.h
[23] Adafruit-GFX-Library-ESP-IDF: https://github.com/martinberlin/Adafruit-GFX-Library-ESP-IDF
[24] GxEPD2: https://github.com/ZinggJM/GxEPD2
[25] ошибки: http://www.braintools.ru/article/4192
[26] Adafruit_Sensor: https://github.com/adafruit/Adafruit_Sensor
[27] Adafruit_Si7021: https://github.com/adafruit/Adafruit_Si7021
[28] CCS811: https://github.com/maarten-pennings/CCS811
[29] ds18b20: https://github.com/feelfreelinux/ds18b20
[30] DS18B20 Device Driver: https://components.espressif.com/components/espressif/ds18b20/
[31] wifi.c: https://github.com/vladipirogov/home-sensors/blob/main/main/wifi.c
[32] mqtt.c: https://github.com/vladipirogov/home-sensors/blob/main/main/mqtt.c
[33] main.cc: http://main.cc
[34] репозитории: https://github.com/vladipirogov/home-sensors/tree/main
[35] внимание: http://www.braintools.ru/article/7595
[36] логика: http://www.braintools.ru/article/7640
[37] Источник: https://habr.com/ru/articles/912324/?utm_source=habrahabr&utm_medium=rss&utm_campaign=912324
Нажмите здесь для печати.