Как стать автором
Обновить

E-paper Arduino термометр на ESP-IDF

Уровень сложностиПростой
Время на прочтение12 мин
Количество просмотров3.4K

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

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

Модуль ESP32

В проекте используется модуль ESP32, приобретенный несколько лет назад.
Эта картинка соответствует его реальной распиновке. По размером он как раз помещается в домик. На картинке со стороны сенсоров видны пару винтов - это ESP32 крепится ими к боковой стенке.

ESP32 pinout
ESP32 pinout

Основные характеристики:

  • Процессор: Tensilica Xtensa LX6.

  • Память:

    • 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)

Подробнее в документации

E-Ink дисплей

Это модуль с диагональю 1.54 дюйма и разрешением 200×200 пикселей. Оснащён встроенным контроллером и использует интерфейс SPI для связи. Поддерживает частичное обновление экрана.
Благодаря таким преимуществам, как сверхнизкое энергопотребление, широкий угол обзора и возможность сохранять изображение без подачи питания, этот дисплей идеально подходит для использования в электронных ценниках, промышленных приборах и других встраиваемых системах.
Wiki страничка.
Отличие моего экземпляра в том, что у модуля имеется дополнительный набор выводов внизу. К этим выводам можно подключать стандартные перемычки.

E-Ink дисплей
E-Ink дисплей

Особенности

  • Не требует подсветки, сохраняет последнее изображение даже при отключении питания

  • Сверхнизкое энергопотребление — питание требуется в основном только при обновлении

  • Интерфейс 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

DS18B20 — это цифровой датчик температуры, работающий по протоколу 1-Wire. Устройство поддерживает настраиваемое разрешение измерений от 9 до 12 бит и может сохранять полученные данные во встроенной энергонезависимой памяти (EEPROM). Благодаря поддержке 1-Wire-интерфейса, датчик может функционировать как в одиночном режиме, так и в составе сети, объединённой общей шиной, управляемой центральным микроконтроллером.

DS18B20 pinout
DS18B20 pinout

Диапазон измеряемых температур составляет от -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. Инициализация шины 1-Wire (reset и поиск устройств).

  2. Отправка команды 0x44 для начала преобразования температуры.

  3. Ожидание завершения измерения (не менее 750 мс).

  4. Отправка команды 0xBE для чтения содержимого RAM (температурные данные находятся в первых двух байтах).

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

Модуль датчиков CJMCU-8128

Данный модуль можно найти на Aliexpress.

CJMCU-8128
CJMCU-8128

Модуль объединяет три цифровых датчика — CCS811, HDC1080 и BMP280, обеспечивая измерение параметров качества воздуха, включая уровень летучих органических соединений (TVOC), влажность, температуру и атмосферное давление. Все датчики подключаются через стандартный интерфейс I2C, что упрощает интеграцию в различные проекты.

Основу контроля за загрязнением воздуха в помещении составляет газоанализатор CCS811, способный определять широкий спектр летучих органических соединений (TVOC) и рассчитывать эквивалентную концентрацию углекислого газа (eCO₂). Такие соединения зачастую присутствуют в воздухе из-за испарений от строительных материалов, бытовой электроники, офисного оборудования и даже дыхания человека. Хотя CCS811 изначально проектировался для использования в компактной электронике вроде умных часов и смартфонов, его версия в модуле адаптирована для использования на макетных платах и в прототипах, благодаря удобным контактным площадкам.

CCS811 поддерживает несколько режимов работы, что позволяет эффективно управлять энергопотреблением. Это особенно важно при использовании в автономных и портативных устройствах. На плате предусмотрены дополнительные пины для подключения термистора NTC, который может применяться для температурной компенсации показаний. Для стабильной и точной работы рекомендуется выполнить "прогрев" датчика — первые 48 часов после начала эксплуатации, а также 20 минут после каждого включения питания.

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

Дополняет комплект BMP280 — прецизионный барометрический датчик от Bosch, который способен измерять атмосферное давление и температуру. Он поддерживает высокоскоростной обмен по шине I2C и требует минимального энергопотребления, что делает его подходящим для метеостанций, высотомеров и других IoT-приложений.

К недостаткам данного модуля я отнес бы то, что из-за нагревания сенсора CCS811, другие датчики показывают завышенную температуру где-то на 2 °C.

Основные характеристики компонентов:

CCS811:

  • Диапазон измерения TVOC: 0–1187 ppb

  • Диапазон eCO₂: 400–8192 ppm

  • Режимы работы: 5 вариантов

  • Встроенный микроконтроллер для обработки данных

  • Интерфейс: I2C

  • Напряжение питания: 1.8–3.6 В

  • Температурная компенсация: с использованием внешнего датчика

HDC1080:

  • Интерфейс: I2C

  • Напряжение питания: 2.7–5.5 В

  • Разрешение: 0.1

  • Влажность: 0–100% RH

  • Температура: от –40°C до +125°C

  • Точность: ±3% RH, ±0.2°C

  • Заводская калибровка, дополнительных компонентов не требует

BMP280:

  • Напряжение питания: 1.71–3.6 В

  • Скорость интерфейса I2C: до 3.4 МГц

  • Ток потребления: 2.7 μA при 1 Гц

  • Уровень шума: до 0.2 Па и 0.01°C

  • Диапазон давления: 300–1100 hPa (примерно от +9000 м до –500 м)

  • Интерфейс: I2C

  • Калиброван на заводе

Полезные ресурсы:

Схема подключения.

Схема подключения нарисована во Fridzing. Библиотеки в основном скачивал готовые на просторах сети. Компонент для модуля CJMCU-8128 сделал по примеру на youtube. Модуль ESP32, который используется в действительности немного отличается набором пинов от библиотечного, но в целом расположение выводов соответствует.

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

проект файла e-home.fzz

Реализация программной части

В исходном примере ESP32 E-Paper Thermometer проект выполнен в Arduino IDE. Библиотеки для работы с e-paper дисплеем и сенсорами модуля CJMCU-8128 также реализованы для Arduino. В первом варианте проекта я изрядно убил времени, чтобы собрать нужные исходные файлы и отредактировать существующие, а затем заставить работать дисплей на ESP-IDF. В обновленной версии проекта поступил намного проще. Первым делом создал новый проект в ESP-IDF 5.4.1 - последняя стабильная версия на момент написания. В ESP-IDF версии 5.x можно установить Arduino как зависимость.

idf.py add-dependency "espressif/arduino-esp32^3.0.2"

Библиотеки для дисплея

Далее собираем необходимые компоненты для работы дисплея. Клонируем следующие проекты в components каталог:

  • Adafruit-GFX-Library - основная графическая библиотека для Adafruit дисплеев, предоставляющая общий набор графических примитивов.

  • Adafruit_BusIO - вспомогательная библиотека для работы дисплея с I2C, SPI

  • GxEPD - библиотека отображения на e-paper дисплее с общим базовым классом и отдельным классом ввода-вывода для Arduino.

BitmapGraphics.h - необходим для отрисовки на дисплее пиктограммы термометра, символа °C и надписи Temperature.

Есть уже готовая реализация Adafruit-GFX-Library-ESP-IDF. Я не пробовал работать с этой библиотекой, возможно с ней все проще. Также существует библиотека GxEPD2, возможно попробую использовать её.
Библиотека GxEPD реализует абстрактные методы Adafruit-GFX-Library. Из GxEPD нам нужно только GxGDEH0154D67-исходники для данного типа дисплея. GxEPD используется в ESP32 E-Paper Thermometer проекте, поэтому остановился на ней. Компилятор ESP-IDF 5.4.1 ругается на то, что методы класса GxIO не переопределены. В ранних версиях IDF такой ошибки не было. Проще всего можно добавить пустую реализацию методов или обозначить их как чисто виртуальные методы, добавив = 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 - унифицированный модуль абстракции для сенсоров от Adafruit.

  • Adafruit_BMP280_Library - библиотека для датчика измерения барометрического давления и температуры BMP-280.

  • Adafruit_Si7021 - библиотека для датчика влажности/температуры Adafruit Si7021.

  • CCS811 - библиотека Arduino для цифрового датчика газа CCS811 контроля качества воздуха в помещении.

  • ds18b20 - простая библиотека для одного DS18B20 на ESP32.

Эти библиотеки можно подключить как компоненты IDF, или просто просто как файлы проекта в основном модуле. Для IDF 5.x существует DS18B20 Device Driver с возможностью работы с многими DS18b20 сенсорами.

Подключение к Wi-Fi (режим STA):

EventGroup — это механизм синхронизации задач в FreeRTOS. Он позволяет задачам или обработчикам событий общаться между собой с помощью набора битов (флагов), где каждый бит обозначает какое-то событие или состояние.
Создаётся группа событий wifi_event_group, внутри которой будет использоваться, например, бит BIT0 (часто это 1 &lt;&lt; 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 подключения.

  1. Создание группы событий (wifi_event_group) - используется для синхронизации статуса подключения.

  2. Инициализация сетевого стека:

    • esp_netif_init() — инициализация TCP/IP стека.

    • esp_event_loop_create_default() — создание цикла обработки событий.

    • esp_netif_create_default_wifi_sta() — создание интерфейса Wi-Fi в режиме станции (STA).

  3. Инициализация Wi-Fi:

    • esp_wifi_init() — инициализация драйвера Wi-Fi.

    • Регистрация обработчиков событий Wi-Fi и IP (esp_event_handler_instance_register).

  4. Настройка подключения:

    • Задание SSID и пароля в структуре wifi_config_t.

    • Установка режима станции: esp_wifi_set_mode(WIFI_MODE_STA).

    • Применение конфигурации: esp_wifi_set_config().

  5. Запуск Wi-Fi:

    • esp_wifi_start() — запуск Wi-Fi.

    • В WIFI_EVENT_STA_START вызывается esp_wifi_connect().

  6. Обработка событий:

    • При отключении (WIFI_EVENT_STA_DISCONNECTED) — попытка повторного подключения.

    • При получении IP (IP_EVENT_STA_GOT_IP) — установка бита события (BIT0) в группе событий.

  7. Ожидание подключения:

    • xEventGroupWaitBits(..., BIT0, ...) — блокирующее ожидание успешного подключения к Wi-Fi.

Исходный файл wifi.c.

Работа с MQTT:

  1. Создание группы событий (mqtt_event_group) — для синхронизации при необходимости (в данном коде не используется явно).

  2. Настройка MQTT клиента:

    • URI брокера: mqtt://192.168.1.107:1883.

    • Интервал Keepalive = 10 секунд.

    • Last Will сообщение при отключении: "0" в топик esp-home/status/activ (с флагом retain).

  3. Инициализация и запуск:

    • esp_mqtt_client_init() — инициализация клиента.

    • esp_mqtt_client_register_event() — регистрация обработчика событий.

    • esp_mqtt_client_start() — запуск клиента.

  4. Обработка событий MQTT:

    • MQTT_EVENT_CONNECTED — подписка на esp-home/cmnd/#.

    • MQTT_EVENT_SUBSCRIBED — публикация "1" в esp-home/status/activ.

    • MQTT_EVENT_DATA — вывод полученных сообщений (топик + данные).

    • Также логируются события отключения, ошибки, публикации и отписки.

Исходный файл mqtt.c.

Логика основного модуля

Инициализация:

  1. Запуск системы:

    • Инициализация NVS (nvs_flash_init()).

    • Подключение к Wi-Fi (wifi_start()).

    • Запуск MQTT-клиента (mqtt_app_start()).

  2. Создание задачи display_task:

    • Задача отвечает за работу с сенсорами, отображение данных и отправку по MQTT.

display_task функция

1. Инициализация сенсоров и дисплея:

  • DS18B20 — температурный датчик на GPIO 25 (ds18b20_init()).

  • I2C-шина (SDA=33, SCL=32) — для остальных сенсоров.

  • Сенсоры:

    • CCS811 — датчик CO₂ и TVOC.

    • BMP280 — температура и давление.

    • Si7021 — температура и влажность.

  • E-ink дисплей — инициализация с пиктограммой.

2. Основной цикл задачи

  1. Считывание значений с сенсоров:

    • DS18B20 - температура на улице.

    • BMP280 — температура и давление в помещении.

    • Si7021 — температура и влажность в помещении.

    • CCS811:

      • Установка климатических данных (темп./влажн.) для компенсации.

      • Получение CO₂ и TVOC.

  2. Обновление e-link дисплея:

    • Показывается температура с DS18B20 (частичное обновление).

  3. Формирование JSON-строки (sprintf) с измерениями:

    • Все значения сенсоров включаются в строку buffer в формате PAYLOAD.

  4. Публикация данных через MQTT:

    • Тема: "esp-home/send".

    • Данные: buffer.

  5. Задержка перед следующим измерением:

    • vTaskDelay(3000 / portTICK_PERIOD_MS); (3 секунды).

Исходный файл main.cc

Структура проекта

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

Исходный код проекта находится в этом репозитории.

Заключение

Проект выполнен на ESP-IDF версии 5.4.1. Arduino-фреймворк подключен как зависимость espressif/arduino-esp32. Такой подход позволяет достаточно легко адаптировать различные готовые решения Arduino-платформы на ESP-IDF. Но иногда требуется доработка библиотек и CMakeLists.txt - файлов. Необходимо обращать внимание на конфигурацию в исходниках библиотек, такую как инициализация портов ввода-вывода, шин I2C и прочего.
На ESP-IDF реализована логика считывания данных из сенсоров: DS18B20, CCS811, BMP280, Si7021, CCS811 с помощью библиотек для среды Arduino.
Портирован исходный код из проекта ESP32 E-Paper Thermometer для отображения температуры от датчика DS18B20 на E-Ink дисплее.
E-Ink дисплей подключен по SPI согласно дефолтной конфигурации в библиотеке.
Данные передаются по MQTT в домашнюю систему.

Теги:
Хабы:
+12
Комментарии11

Публикации

Ближайшие события