ESP8266 NodeMCU MQTT – публикация показаний температуры DS18B20 (Arduino IDE)

Узнайте, как публиковать показания температуры DS18B20 по MQTT с помощью ESP8266 (NodeMCU) на любую платформу, поддерживающую MQTT, или любой другой MQTT-клиент. В качестве примера мы будем публиковать показания датчика в Node-RED Dashboard, а ESP8266 будет запрограммирован с использованием Arduino IDE.

ESP8266 NodeMCU MQTT публикация показаний температуры DS18B20 Arduino IDE Node-RED

Рекомендуемое чтение: Что такое MQTT и как он работает

Обзор проекта

На следующей диаграмме показан общий обзор проекта, который мы создадим.

ESP8266 NodeMCU MQTT публикация показаний температуры DS18B20 обзор проекта
  • ESP8266 запрашивает показания температуры у датчика DS18B20. Показания публикуются в топике esp/ds18b20/temperature;

  • Node-RED подписан на топик esp/ds18b20/temperature. Таким образом, он получает показания температуры DS18B20 и отображает их в виде индикатора/графика;

  • Вы можете получать показания на любой другой платформе, поддерживающей MQTT, и обрабатывать данные по своему усмотрению.

Предварительные требования

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

Arduino IDE

Мы будем программировать ESP8266 с использованием Arduino IDE, поэтому убедитесь, что дополнение ESP8266 установлено.

Брокер MQTT

Установка MQTT брокера Mosquitto на Raspberry Pi

Для использования MQTT вам нужен брокер. Мы будем использовать брокер Mosquitto, установленный на Raspberry Pi. Прочитайте руководство Как установить брокер Mosquitto на Raspberry Pi.

Вы можете использовать любой другой MQTT-брокер, включая облачный MQTT-брокер. Мы покажем вам, как это сделать в коде позже.

Если вы не знакомы с MQTT, обязательно прочитайте наше вводное руководство: Что такое MQTT и как он работает.

Библиотеки MQTT

Для использования MQTT с ESP8266 мы будем использовать библиотеку Async MQTT Client.

Установка библиотеки Async MQTT Client

  1. Нажмите здесь, чтобы скачать библиотеку Async MQTT Client. В папке загрузок у вас должен появиться .zip файл

  2. Распакуйте .zip файл, и вы получите папку async-mqtt-client-master

  3. Переименуйте папку из async-mqtt-client-master в async_mqtt_client

  4. Переместите папку async_mqtt_client в папку библиотек вашей Arduino IDE

  5. Наконец, перезапустите Arduino IDE

В качестве альтернативы вы можете перейти в Sketch > Include Library > Add .ZIP library и выбрать только что загруженную библиотеку.

Установка библиотеки ESPAsync TCP

Для использования MQTT с ESP вам также нужна библиотека ESPAsync TCP.

  1. Нажмите здесь, чтобы скачать библиотеку ESPAsync TCP. В папке загрузок у вас должен появиться .zip файл

  2. Распакуйте .zip файл, и вы получите папку ESPAsyncTCP-master

  3. Переименуйте папку из ESPAsyncTCP-master в ESPAsyncTCP

  4. Переместите папку ESPAsyncTCP в папку библиотек вашей Arduino IDE

  5. Наконец, перезапустите Arduino IDE

В качестве альтернативы вы можете перейти в Sketch > Include Library > Add .ZIP library и выбрать только что загруженную библиотеку.

Библиотеки для датчика температуры DS18B20

Для работы с датчиком температуры DS18B20 вам необходимо установить библиотеку OneWire от Paul Stoffregen и библиотеку Dallas Temperature. Выполните следующие шаги для установки этих библиотек.

  1. Откройте Arduino IDE и перейдите в Sketch > Include Library > Manage Libraries. Должен открыться менеджер библиотек.

  2. Введите «onewire» в поле поиска и установите библиотеку OneWire от Paul Stoffregen.

Установка библиотеки OneWire от Paul Stoffregen в Arduino IDE
  1. Затем найдите «Dallas» и установите библиотеку DallasTemperature от Miles Burton.

Установка библиотеки DallasTemperature от Miles Burton в Arduino IDE

После установки библиотек перезапустите Arduino IDE.

Чтобы узнать больше о датчике температуры DS18B20, прочитайте наше руководство: ESP8266 DS18B20 Temperature Sensor with Arduino IDE (Single, Multiple, Web Server)

Необходимые компоненты

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

Вы можете использовать указанные выше ссылки или перейти непосредственно на MakerAdvisor.com/tools, чтобы найти все компоненты для ваших проектов по лучшей цене!

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

Подключите DS18B20 к ESP8266, как показано на следующей схеме, с выводом данных DS18B20, подключённым к GPIO 4 (D2).

ESP8266 NodeMCU DS18B20 датчик температуры подключение GPIO 4 схема

Код

Скопируйте следующий код в вашу Arduino IDE. Чтобы он работал, вам нужно вставить свои сетевые учётные данные, а также данные MQTT-брокера.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp8266-nodemcu-mqtt-publish-ds18b20-arduino/

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.

  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266WiFi.h>
#include <Ticker.h>
#include <AsyncMqttClient.h>

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

// Raspberri Pi Mosquitto MQTT Broker
#define MQTT_HOST IPAddress(192, 168, 1, XXX)
// For a cloud MQTT broker, type the domain name
//#define MQTT_HOST "example.com"
#define MQTT_PORT 1883

// Temperature MQTT Topics
#define MQTT_PUB_TEMP "esp/ds18b20/temperature"

// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);
// Temperature value
float temp;

AsyncMqttClient mqttClient;
Ticker mqttReconnectTimer;

WiFiEventHandler wifiConnectHandler;
WiFiEventHandler wifiDisconnectHandler;
Ticker wifiReconnectTimer;

unsigned long previousMillis = 0;   // Stores last time temperature was published
const long interval = 10000;        // Interval at which to publish sensor readings

void connectToWifi() {
  Serial.println("Connecting to Wi-Fi...");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

void onWifiConnect(const WiFiEventStationModeGotIP& event) {
  Serial.println("Connected to Wi-Fi.");
  connectToMqtt();
}

void onWifiDisconnect(const WiFiEventStationModeDisconnected& event) {
  Serial.println("Disconnected from Wi-Fi.");
  mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
  wifiReconnectTimer.once(2, connectToWifi);
}

void connectToMqtt() {
  Serial.println("Connecting to MQTT...");
  mqttClient.connect();
}

void onMqttConnect(bool sessionPresent) {
  Serial.println("Connected to MQTT.");
  Serial.print("Session present: ");
  Serial.println(sessionPresent);
}

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  Serial.println("Disconnected from MQTT.");

  if (WiFi.isConnected()) {
    mqttReconnectTimer.once(2, connectToMqtt);
  }
}

/*void onMqttSubscribe(uint16_t packetId, uint8_t qos) {
  Serial.println("Subscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
  Serial.print("  qos: ");
  Serial.println(qos);
}

void onMqttUnsubscribe(uint16_t packetId) {
  Serial.println("Unsubscribe acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}*/

void onMqttPublish(uint16_t packetId) {
  Serial.print("Publish acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}

void setup() {
  sensors.begin();
  Serial.begin(115200);
  Serial.println();

  wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
  wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);

  mqttClient.onConnect(onMqttConnect);
  mqttClient.onDisconnect(onMqttDisconnect);
  //mqttClient.onSubscribe(onMqttSubscribe);
  //mqttClient.onUnsubscribe(onMqttUnsubscribe);
  mqttClient.onPublish(onMqttPublish);
  mqttClient.setServer(MQTT_HOST, MQTT_PORT);
  // If your broker requires authentication (username and password), set them below
  //mqttClient.setCredentials("REPlACE_WITH_YOUR_USER", "REPLACE_WITH_YOUR_PASSWORD");

  connectToWifi();
}

void loop() {
  unsigned long currentMillis = millis();
  // Every X number of seconds (interval = 10 seconds)
  // it publishes a new MQTT message
  if (currentMillis - previousMillis >= interval) {
    // Save the last time a new reading was published
    previousMillis = currentMillis;
    // New temperature readings
    sensors.requestTemperatures();
    // Temperature in Celsius degrees
    temp = sensors.getTempCByIndex(0);
    // Temperature in Fahrenheit degrees
    //temp = sensors.getTempFByIndex(0);

    // Publish an MQTT message on topic esp/ds18b20/temperature
    uint16_t packetIdPub1 = mqttClient.publish(MQTT_PUB_TEMP, 1, true, String(temp).c_str());
    Serial.printf("Publishing on topic %s at QoS 1, packetId: %i ", MQTT_PUB_TEMP, packetIdPub1);
    Serial.printf("Message: %.2f \n", temp);
  }
}

Просмотреть исходный код

Как работает код

В следующем разделе импортируются все необходимые библиотеки.

#include <OneWire.h>
#include <DallasTemperature.h>
#include <ESP8266WiFi.h>
#include <Ticker.h>
#include <AsyncMqttClient.h>

Вставьте свои сетевые учётные данные в следующие строки.

#define WIFI_SSID "REPLACE_WITH_YOUR_SSID"
#define WIFI_PASSWORD "REPLACE_WITH_YOUR_PASSWORD"

Вставьте IP-адрес Raspberry Pi, чтобы ESP8266 подключился к вашему брокеру.

#define MQTT_HOST IPAddress(192, 168, 1, 106)

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

#define MQTT_HOST "example.com"

Определите порт MQTT.

#define MQTT_PORT 1883

Мы будем публиковать температуру в топике esp/ds18b20/temperature. Если вы хотите изменить топик, измените его в следующей строке.

#define MQTT_PUB_TEMP "esp/ds18b20/temperature"

Вы можете создать больше топиков, если хотите.

Настройте DS18B20 в следующих строках. В нашем случае он подключён к GPIO 4. Вы можете подключить его к любому другому GPIO.

// GPIO where the DS18B20 is connected to
const int oneWireBus = 4;
// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(oneWireBus);
// Pass our oneWire reference to Dallas Temperature sensor
DallasTemperature sensors(&oneWire);

Переменная temp будет хранить значение температуры от датчика температуры DS18B20.

float temp;

Создайте объект AsyncMqttClient с именем mqttClient для управления MQTT-клиентом и таймеры для переподключения к MQTT-брокеру и маршрутизатору при потере соединения.

AsyncMqttClient mqttClient;
Ticker mqttReconnectTimer;

WiFiEventHandler wifiConnectHandler;
WiFiEventHandler wifiDisconnectHandler;
Ticker wifiReconnectTimer;

Затем создайте вспомогательные переменные таймера для публикации показаний каждые 10 секунд. Вы можете изменить время задержки в переменной interval.

unsigned long previousMillis = 0;  // Stores last time temperature was published
const long interval = 10000;       // Interval at which to publish sensor readings

Функции MQTT: подключение к Wi-Fi, подключение к MQTT и события Wi-Fi

Мы не добавляли комментарии к функциям, определённым в следующем разделе кода. Эти функции поставляются с библиотекой Async Mqtt Client. Названия функций говорят сами за себя.

Например, функция connectToWifi() подключает ESP8266 к вашему маршрутизатору:

void connectToWifi() {
  Serial.println("Connecting to Wi-Fi...");
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
}

Функция connectToMqtt() подключает ESP8266 к вашему MQTT-брокеру:

void connectToMqtt() {
  Serial.println("Connecting to MQTT...");
  mqttClient.connect();
}

Функция onMqttConnect() выполняется после начала сессии с брокером.

void onMqttConnect(bool sessionPresent) {
  Serial.println("Connected to MQTT.");
  Serial.print("Session present: ");
  Serial.println(sessionPresent);
}

Функции MQTT: отключение и публикация

Если ESP8266 теряет соединение с MQTT-брокером, вызывается функция onMqttDisconnect, которая выводит сообщение в серийный монитор.

void onMqttDisconnect(AsyncMqttClientDisconnectReason reason) {
  Serial.println("Disconnected from MQTT.");

  if (WiFi.isConnected()) {
    mqttReconnectTimer.once(2, connectToMqtt);
  }
}

Когда вы публикуете сообщение в MQTT-топик, вызывается функция onMqttPublish(). Она выводит идентификатор пакета в серийный монитор.

void onMqttPublish(uint16_t packetId) {
  Serial.print("Publish acknowledged.");
  Serial.print("  packetId: ");
  Serial.println(packetId);
}

По сути, все эти функции, которые мы только что упомянули, являются функциями обратного вызова (callback). Они выполняются асинхронно.

setup()

Теперь перейдём к setup(). Инициализируйте датчик DS18B20 и запустите серийную связь.

sensors.begin();
Serial.begin(115200);

Следующие две строки создают обработчики, которые позволят переподключиться как к MQTT-брокеру, так и к Wi-Fi в случае потери соединения.

wifiConnectHandler = WiFi.onStationModeGotIP(onWifiConnect);
wifiDisconnectHandler = WiFi.onStationModeDisconnected(onWifiDisconnect);

Наконец, назначьте все функции обратного вызова. Это означает, что эти функции будут выполняться автоматически, когда это необходимо. Например, когда ESP8266 подключается к брокеру, автоматически вызывается функция onMqttConnect() и так далее.

mqttClient.onConnect(onMqttConnect);
mqttClient.onDisconnect(onMqttDisconnect);
//mqttClient.onSubscribe(onMqttSubscribe);
//mqttClient.onUnsubscribe(onMqttUnsubscribe);
mqttClient.onPublish(onMqttPublish);
mqttClient.setServer(MQTT_HOST, MQTT_PORT);

Аутентификация брокера

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

mqttClient.setCredentials("REPlACE_WITH_YOUR_USER", "REPLACE_WITH_YOUR_PASSWORD");

Наконец, подключитесь к Wi-Fi.

connectToWifi();

loop()

В loop() вы создаёте таймер, который позволит публиковать новые показания температуры в топике esp/ds18b20/temperature каждые 10 секунд.

unsigned long currentMillis = millis();
// Every X number of seconds (interval = 10 seconds)
// it publishes a new MQTT message
if (currentMillis - previousMillis >= interval) {
  // Save the last time a new reading was published
  previousMillis = currentMillis;
  // New temperature readings
  sensors.requestTemperatures();
  // Temperature in Celsius degrees
  temp = sensors.getTempCByIndex(0);

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

//temp = sensors.getTempFByIndex(0);

Узнайте больше о датчике температуры DS18B20: ESP8266 DS18B20 Temperature Sensor with Arduino IDE (Single, Multiple, Web Server).

Публикация в топики

Чтобы опубликовать сообщение в MQTT-топик, используйте следующую строку:

uint16_t packetIdPub1 = mqttClient.publish(MQTT_PUB_TEMP, 1, true, String(temp).c_str());

Если вы хотите публиковать больше показаний в различные топики, вы можете продублировать эту предыдущую строку в loop().

По сути, используйте метод publish() объекта mqttClient для публикации данных в топик. Метод publish() принимает следующие аргументы по порядку:

  • MQTT-топик (const char*)

  • QoS (uint8_t): качество обслуживания – может быть 0, 1 или 2

  • Флаг сохранения (bool): флаг retain

  • Полезная нагрузка (const char*)

QoS (quality of service, качество обслуживания) – это способ гарантировать доставку сообщения. Оно может быть одного из следующих уровней:

  • 0: сообщение будет доставлено один раз или не доставлено вовсе. Сообщение не подтверждается. Нет возможности дублирования сообщений;

  • 1: сообщение будет доставлено как минимум один раз, но может быть доставлено более одного раза;

  • 2: сообщение всегда доставляется ровно один раз;

  • Узнайте больше о MQTT QoS.

Загрузка кода

При включённом Raspberry Pi с запущенным MQTT-брокером Mosquitto загрузите код в ESP8266.

Откройте серийный монитор на скорости 115200 бод, и вы увидите, что ESP8266 начинает публиковать сообщения.

ESP8266 NodeMCU Arduino IDE серийный монитор MQTT публикация показаний датчика отладка

Подготовка Node-RED Dashboard

ESP8266 публикует показания температуры каждые 10 секунд в топике esp/ds18b20/temperature. Теперь вы можете использовать любую панель мониторинга, поддерживающую MQTT, или любое другое устройство с поддержкой MQTT, чтобы подписаться на этот топик и получать показания.

В качестве примера мы создадим простой поток (flow) с использованием Node-RED для подписки на этот топик и отображения показаний на индикаторе или графике.

Если у вас не установлен Node-RED, следуйте этим руководствам:

Когда Node-RED запущен на вашем Raspberry Pi, перейдите по IP-адресу вашего Raspberry Pi, за которым следует :1880.

http://raspberry-pi-ip-address:1880

Должен открыться интерфейс Node-RED. Перетащите узел MQTT in, узел chart и узел gauge в поток.

Node-RED перетаскивание узлов MQTT In Chart Gauge

Нажмите на узел MQTT и отредактируйте его свойства следующим образом:

MQTT In узел ESP8266 публикация температуры Node-RED Flow

Поле Server относится к MQTT-брокеру. В нашем случае MQTT-брокер – это Raspberry Pi, поэтому установлено значение localhost:1883. Если вы используете облачный MQTT-брокер, вам следует изменить это поле. Вставьте топик, на который хотите подписаться, и QoS.

Установите следующие свойства для узла gauge.

Узел Gauge ESP32 публикация температуры Node-RED Flow

Отредактируйте узел chart следующим образом:

Узел Chart ESP32 публикация температуры Node-RED Flow

Соедините ваши узлы, как показано ниже:

ESP8266 NodeMCU MQTT публикация температуры Node-RED Flow

Наконец, разверните ваш поток (нажмите кнопку в правом верхнем углу).

Кнопка Deploy Node-RED

В качестве альтернативы вы можете перейти в Menu > Import и скопировать следующий код в ваш Clipboard, чтобы создать поток Node-RED.

[{"id":"3eb4b485.bb948c","type":"mqtt in","z":"b01416d3.f69f38","name":"","topic":"esp/ds18b20/temperature","qos":"1","datatype":"auto","broker":"8db3fac0.99dd48","x":930,"y":120,"wires":[["706fecd4.6f91a4","47ed6377.491d6c"]]},{"id":"706fecd4.6f91a4","type":"ui_gauge","z":"b01416d3.f69f38","name":"","group":"37de8fe8.46846","order":2,"width":0,"height":0,"gtype":"gage","title":"Temperature","label":"ºC","format":"{{value}}","min":0,"max":"40","colors":["#00b500","#f7df09","#ca3838"],"seg1":"","seg2":"","x":1190,"y":100,"wires":[]},{"id":"47ed6377.491d6c","type":"ui_chart","z":"b01416d3.f69f38","name":"","group":"2b7ac01b.fc984","order":4,"width":0,"height":0,"label":"Temperature","chartType":"line","legend":"false","xformat":"HH:mm:ss","interpolate":"linear","nodata":"","dot":false,"ymin":"","ymax":"","removeOlder":1,"removeOlderPoints":"","removeOlderUnit":"3600","cutout":0,"useOneColor":false,"colors":["#1f77b4","#aec7e8","#ff7f0e","#2ca02c","#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5"],"useOldStyle":false,"outputs":1,"x":1190,"y":160,"wires":[[]]},{"id":"8db3fac0.99dd48","type":"mqtt-broker","z":"","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"37de8fe8.46846","type":"ui_group","z":"","name":"DS18B20","tab":"53b8c8f9.cfbe48","order":1,"disp":true,"width":"6","collapse":false},{"id":"2b7ac01b.fc984","type":"ui_group","z":"","name":"SENSORS","tab":"99ab8dc5.f435c","disp":true,"width":"6","collapse":false},{"id":"53b8c8f9.cfbe48","type":"ui_tab","z":"","name":"Home","icon":"dashboard","order":2,"disabled":false,"hidden":false},{"id":"99ab8dc5.f435c","type":"ui_tab","z":"","name":"HTTP","icon":"dashboard","order":1,"disabled":false,"hidden":false}]

Просмотреть исходный код

Демонстрация

Перейдите по IP-адресу вашего Raspberry Pi, за которым следует :1880/ui.

http://raspberry-pi-ip-address:1880/ui

Вы должны получить доступ к текущим показаниям датчика на панели мониторинга (индикатор и график).

ESP32 MQTT публикация температуры Node-RED Dashboard индикатор график

Вот и всё! Ваша плата ESP8266 публикует показания датчика в Node-RED через MQTT.

Заключение

MQTT – это отличный протокол связи для обмена небольшими объёмами данных между устройствами. В этом руководстве вы научились публиковать показания температуры DS18B20 с ESP8266 в MQTT-топик. Затем вы можете использовать любое устройство или платформу домашней автоматизации для подписки на этот топик и получения показаний.

Вместо DS18B20 вы можете использовать другой датчик:

Мы надеемся, что это руководство оказалось полезным для вас. Если вы хотите узнать больше об ESP8266, ознакомьтесь с нашими ресурсами:

Спасибо за чтение.