ESP32 MQTT – Публикация и подписка с Arduino IDE
В этом проекте показано, как использовать протокол связи MQTT с ESP32 для публикации сообщений и подписки на топики. В качестве примера мы будем публиковать показания датчика BME280 на панель Node-RED Dashboard и управлять выходом ESP32. ESP32 будет программироваться с помощью Arduino IDE.
Обзор проекта
В этом примере есть приложение Node-RED, которое управляет выходами ESP32 и получает показания датчиков от ESP32, используя протокол связи MQTT. Приложение Node-RED работает на Raspberry Pi.
Мы будем использовать брокер Mosquitto, установленный на том же Raspberry Pi. Брокер отвечает за получение всех сообщений, фильтрацию сообщений, определение того, кто в них заинтересован, и публикацию сообщений всем подписанным клиентам.
На следующем рисунке показан обзор того, что мы будем делать в этом руководстве.
Приложение Node-RED публикует сообщения (»on» или «off») в топик esp32/output. ESP32 подписан на этот топик. Таким образом, он получает сообщение с «on» или «off» для включения или выключения светодиода.
ESP32 публикует температуру в топик esp32/temperature и влажность в топик esp32/humidity. Приложение Node-RED подписано на эти топики. Таким образом, оно получает показания температуры и влажности, которые можно отобразить на графике или шкале, например.
Примечание: существует также аналогичное руководство по использованию ESP8266 и Node-RED с MQTT.
Предварительные требования
Вы должны быть знакомы с Raspberry Pi – читайте Начало работы с Raspberry Pi.
У вас должна быть установлена операционная система Raspbian на вашем Raspberry Pi – читайте Установка Raspbian Lite, включение и подключение по SSH.
Вам нужен Node-RED, установленный на вашем Pi и Node-RED Dashboard.
Узнайте, что такое MQTT и как он работает.
Если вам нравится домашняя автоматизация и вы хотите узнать больше о Node-RED, Raspberry Pi, ESP8266 и Arduino, мы рекомендуем попробовать наш курс: Создание системы домашней автоматизации с Node-RED, ESP8266 и Arduino. У нас также есть курс, посвященный ESP32: Запишитесь на курс Learn ESP32 with Arduino IDE.
Необходимые компоненты
Это компоненты, необходимые для сборки схемы (нажмите на ссылки ниже, чтобы найти лучшую цену на Maker Advisor):
Raspberry Pi – читайте Лучшие стартовые наборы Raspberry Pi 3
ESP32 DOIT DEVKIT V1 Board – читайте Обзор и сравнение плат разработки ESP32
Вы можете использовать ссылки выше или перейти непосредственно на MakerAdvisor.com/tools, чтобы найти все компоненты для ваших проектов по лучшей цене!
Знакомство с модулем датчика BME280
Модуль датчика BME280 измеряет температуру, влажность и давление. Поскольку давление изменяется с высотой, вы также можете оценить высоту над уровнем моря. Однако в этом руководстве мы будем считывать только температуру и влажность. Существует несколько версий этого модуля датчика, но мы используем ту, что показана на рисунке ниже.
Датчик может взаимодействовать по протоколу SPI или I2C (существуют модули этого датчика, которые поддерживают только I2C, они имеют всего четыре вывода).
Для использования протокола связи SPI используйте следующие выводы:
SCK – это вывод тактового сигнала SPI
SDO – MISO
SDI – MOSI
CS – Chip Select (выбор микросхемы)
Для использования протокола связи I2C датчик использует следующие выводы:
SCK – вывод SCL
SDI – вывод SDA
Схема подключения
Мы будем использовать связь I2C с модулем датчика BME280. Для этого подключите датчик к выводам SDA и SCL ESP32, как показано на следующей принципиальной схеме.
Мы также будем управлять выходом ESP32 – светодиодом, подключенным к GPIO 4.
Вот как должна выглядеть ваша схема:
Подготовка Arduino IDE
Существует дополнение для Arduino IDE, которое позволяет программировать ESP32 с помощью Arduino IDE и его языка программирования. Следуйте одному из следующих руководств, чтобы подготовить вашу Arduino IDE для работы с ESP32, если вы ещё этого не сделали.
После того как вы убедились, что дополнение ESP32 установлено, вы можете продолжить работу с этим руководством.
Установка библиотеки PubSubClient
Библиотека PubSubClient предоставляет клиент для простого обмена сообщениями публикация/подписка с сервером, поддерживающим MQTT (по сути, позволяет вашему ESP32 общаться с Node-RED).
Нажмите здесь, чтобы скачать библиотеку PubSubClient. У вас должен появиться файл .zip в папке загрузок
Разархивируйте файл .zip, и у вас должна появиться папка pubsubclient-master
Переименуйте папку из pubsubclient-master в pubsubclient
Переместите папку pubsubclient в папку библиотек вашей установки Arduino IDE
Затем перезапустите вашу Arduino IDE
Библиотека поставляется с несколькими примерами скетчей. Смотрите File > Examples > PubSubClient в программе Arduino IDE.
Важно: PubSubClient не полностью совместима с ESP32, но пример, представленный в этом руководстве, очень надёжно работал во время наших тестов.
Установка библиотеки BME280
Для считывания показаний с модуля датчика BME280 мы будем использовать библиотеку Adafruit_BME280. Выполните следующие шаги для установки библиотеки в вашу Arduino IDE:
Нажмите здесь, чтобы скачать библиотеку Adafruit-BME280. У вас должен появиться файл .zip в папке загрузок
Разархивируйте файл .zip, и у вас должна появиться папка Adafruit-BME280-Library-master
Переименуйте папку из Adafruit-BME280-Library-master в Adafruit_BME280_Library
Переместите папку Adafruit_BME280_Library в папку библиотек вашей установки Arduino IDE
Наконец, перезапустите вашу Arduino IDE
В качестве альтернативы вы можете перейти в Sketch > Include Library > Manage Libraries и ввести «adafruit bme280» для поиска библиотеки. Затем нажмите install.
Установка библиотеки Adafruit_Sensor
Для использования библиотеки BME280 вам также необходимо установить библиотеку Adafruit_Sensor. Выполните следующие шаги для установки библиотеки:
Нажмите здесь, чтобы скачать библиотеку Adafruit_Sensor. У вас должен появиться файл .zip в папке загрузок
Разархивируйте файл .zip, и у вас должна появиться папка Adafruit_Sensor-master
Переименуйте папку из Adafruit_Sensor-master в Adafruit_Sensor
Переместите папку Adafruit_Sensor в папку библиотек вашей установки Arduino IDE
Наконец, перезапустите вашу Arduino IDE
Загрузка кода
Теперь вы можете загрузить следующий код на ваш ESP32. Код прокомментирован в тех местах, где вам нужно внести изменения. Вам нужно отредактировать код, указав ваш собственный SSID, пароль и IP-адрес Raspberry Pi.
/*********
Rui Santos
Complete project details at https://randomnerdtutorials.com
*********/
#include <WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <Adafruit_BME280.h>
#include <Adafruit_Sensor.h>
// Replace the next variables with your SSID/Password combination
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Add your MQTT Broker IP address, example:
//const char* mqtt_server = "192.168.1.144";
const char* mqtt_server = "YOUR_MQTT_BROKER_IP_ADDRESS";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
//uncomment the following lines if you're using SPI
/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/
Adafruit_BME280 bme; // I2C
//Adafruit_BME280 bme(BME_CS); // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI
float temperature = 0;
float humidity = 0;
// LED Pin
const int ledPin = 4;
void setup() {
Serial.begin(115200);
// default settings
// (you can also pass in a Wire library object like &Wire2)
//status = bme.begin();
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
pinMode(ledPin, OUTPUT);
}
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* message, unsigned int length) {
Serial.print("Message arrived on topic: ");
Serial.print(topic);
Serial.print(". Message: ");
String messageTemp;
for (int i = 0; i < length; i++) {
Serial.print((char)message[i]);
messageTemp += (char)message[i];
}
Serial.println();
// Feel free to add more if statements to control more GPIOs with MQTT
// If a message is received on the topic esp32/output, you check if the message is either "on" or "off".
// Changes the output state according to the message
if (String(topic) == "esp32/output") {
Serial.print("Changing output to ");
if(messageTemp == "on"){
Serial.println("on");
digitalWrite(ledPin, HIGH);
}
else if(messageTemp == "off"){
Serial.println("off");
digitalWrite(ledPin, LOW);
}
}
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// Attempt to connect
if (client.connect("ESP8266Client")) {
Serial.println("connected");
// Subscribe
client.subscribe("esp32/output");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
long now = millis();
if (now - lastMsg > 5000) {
lastMsg = now;
// Temperature in Celsius
temperature = bme.readTemperature();
// Uncomment the next line to set temperature in Fahrenheit
// (and comment the previous temperature line)
//temperature = 1.8 * bme.readTemperature() + 32; // Temperature in Fahrenheit
// Convert the value to a char array
char tempString[8];
dtostrf(temperature, 1, 2, tempString);
Serial.print("Temperature: ");
Serial.println(tempString);
client.publish("esp32/temperature", tempString);
humidity = bme.readHumidity();
// Convert the value to a char array
char humString[8];
dtostrf(humidity, 1, 2, humString);
Serial.print("Humidity: ");
Serial.println(humString);
client.publish("esp32/humidity", humString);
}
}
Этот код публикует показания температуры и влажности в топиках esp32/temperature и esp32/humidity через протокол MQTT.
ESP32 подписан на топик esp32/output для получения сообщений, публикуемых в этом топике приложением Node-RED. Затем, в соответствии с полученным сообщением, он включает или выключает светодиод.
Подписка на топики MQTT
В функции reconnect() вы можете подписаться на топики MQTT. В данном случае ESP32 подписан только на esp32/output:
client.subscribe("esp32/output");
В функции callback() ESP32 получает MQTT-сообщения из подписанных топиков. В зависимости от топика и сообщения MQTT, он включает или выключает светодиод:
// If a message is received on the topic esp32/output, you check if the message is either "on" or "off".
// Changes the output state according to the message
if (String(topic) == "esp32/output") {
Serial.print("Changing output to ");
if (messageTemp == "on") {
Serial.println("on");
digitalWrite(ledPin, HIGH);
}
else if (messageTemp == "off") {
Serial.println("off");
digitalWrite(ledPin, LOW);
}
}
Публикация сообщений MQTT
В функции loop() новые показания публикуются каждые 5 секунд:
if (now - lastMsg > 5000) { ... }
По умолчанию ESP32 отправляет температуру в градусах Цельсия, но вы можете раскомментировать последнюю строку, чтобы отправлять температуру в градусах Фаренгейта:
// Temperature in Celsius
temperature = bme.readTemperature();
// Uncomment the next line to set temperature in Fahrenheit
// (and comment the previous temperature line)
//temperature = 1.8 * bme.readTemperature() + 32; // Temperature in Fahrenheit
Вам нужно преобразовать переменную temperature типа float в массив char, чтобы вы могли опубликовать показание температуры в топике esp32/temperature:
// Convert the value to a char array
char tempString[8];
dtostrf(temperature, 1, 2, tempString);
Serial.print("Temperature: ");
Serial.println(tempString);
client.publish("esp32/temperature", tempString);
Тот же процесс повторяется для публикации показания влажности в топике esp32/humidity:
humidity = bme.readHumidity();
// Convert the value to a char array
char humString[8];
dtostrf(humidity, 1, 2, humString);
Serial.print("Humidity: ");
Serial.println(humString);
client.publish("esp32/humidity", humString);
Создание потока Node-RED
Перед созданием потока вам необходимо установить на вашем Raspberry Pi:
После этого импортируйте предоставленный поток Node-RED. Перейдите в репозиторий GitHub или нажмите на изображение ниже, чтобы увидеть исходный файл, и скопируйте предоставленный код.
Далее, в окне Node-RED, в правом верхнем углу, выберите меню и перейдите в Import > Clipboard.
Затем вставьте предоставленный код и нажмите Import.
Должны загрузиться следующие узлы:
После внесения любых изменений нажмите кнопку Deploy, чтобы сохранить все изменения.
Интерфейс Node-RED
Теперь ваше приложение Node-RED готово. Чтобы получить доступ к интерфейсу Node-RED и увидеть, как выглядит ваше приложение, откройте любой браузер в вашей локальной сети и введите:
http://Your_RPi_IP_address:1880/ui
Ваше приложение должно выглядеть так, как показано на следующем рисунке. Вы можете управлять светодиодом (включать и выключать) с помощью переключателя, или вы можете просматривать показания температуры на графике и значения влажности на шкале.
Демонстрация
Посмотрите следующее видео для живой демонстрации:
Откройте монитор последовательного порта Arduino IDE, чтобы посмотреть на MQTT-сообщения, которые принимаются и публикуются.
Заключение
Подводя итог, мы показали вам основные концепции, которые позволяют включать свет и мониторить датчики с помощью вашего ESP32, используя Node-RED и протокол связи MQTT. Вы можете использовать этот пример для интеграции в вашу собственную систему домашней автоматизации, управления большим количеством выходов или мониторинга других датчиков.
Вам также может быть интересно почитать:
Надеемся, что это руководство было для вас полезным.
Спасибо за чтение.
Источник: ESP32 MQTT – Publish and Subscribe with Arduino IDE