ESP32 MQTT –使用Arduino IDE发布和订阅

ESP32 MQTT --使用Arduino IDE发布和订阅


功能介绍

该项目展示了如何将MQTT通信协议与ESP32一起使用来发布消息和订阅主题。 例如,我们将BME280传感器的读数发布到Node-RED仪表板,并控制ESP32输出。 我们将使用Arduino IDE对ESP32进行编程。


在此示例中,有一个Node-RED应用程序,该应用程序使用MQTT通信协议控制ESP32的输出并从ESP32接收传感器读数。 Node-RED应用程序在Raspberry Pi上运行。

我们将使用安装在同一Raspberry Pi上的Mosquitto代理。 代理负责接收所有消息,过滤消息,确定谁对它们感兴趣并将消息发布到所有订阅的客户端。

下图概述了本教程将要执行的操作。

Node-RED应用程序在主题esp32 / output中发布消息(" on"或" off")。 ESP32已订阅该主题。 因此,它接收到带有"开"或"关"的消息,以打开或关闭LED。

ESP32在esp32 /温度主题上发布温度,在esp32 /湿度主题上发布湿度。 Node-RED应用程序已订阅这些主题。 因此,它接收的温度和湿度读数可以显示在图表或仪表上。

一、介绍BME280传感器模块

BME280传感器模块读取温度,湿度和压力。 由于压力随海拔高度而变化,因此您也可以估算海拔高度。 但是,在本教程中,我们将仅读取温度和湿度。 该传感器模块有多种版本,但我们使用的是下图所示的版本。

传感器可以使用SPI或I2C通信协议进行通信(该传感器的某些模块仅与I2C进行通信,这些模块仅带有四个引脚)。

要使用SPI通信协议,请使用以下引脚:

SCK -- this is the SPI Clock pin

  • SDO -- MISO
  • SDI -- MOSI
  • CS -- Chip Select

To use I2C communication protocol, the sensor uses the following pins:

  • SCK -- SCL pin
  • SDI -- SDA pin

二、准备Arduino IDE

Arduino IDE有一个附加组件,可让您使用Arduino IDE及其编程语言对ESP32进行编程。 如果您尚未使用Arduino IDE,请按照以下教程之一进行准备,以使其能够与ESP32一起使用。

二、安装PubSubClient库

PubSubClient库提供了一个客户端,用于使用支持MQTT的服务器(基本上允许您的ESP32与Node-RED进行通信)来进行简单的发布/订阅消息传递。

单击此处下载PubSubClient库。 您的下载文件夹中应该有一个.zip文件夹

解压缩.zip文件夹,您应该获得pubsubclient-master文件夹

将文件夹从pubsubclient-master重命名为pubsubclient

将pubsubclient文件夹移至Arduino IDE安装库文件夹

然后,重新打开您的Arduino IDE

该库附带了许多示例草图。 请参阅Arduino IDE软件中的"文件">"示例">" PubSubClient"。

重要提示:PubSubClient与ESP32并不完全兼容,但本教程中提供的示例在我们的测试过程中工作非常可靠。

三、安装BME280库

要获取BME280传感器模块的读数,我们将使用Adafruit_BME280库。 请按照以下步骤在您的Arduino IDE中安装该库:

单击此处下载Adafruit-BME280库。 您的下载文件夹中应该有一个.zip文件夹

解压缩.zip文件夹,您应该会获得Adafruit-BME280-Library-master文件夹

将文件夹从Adafruit-BME280-Library-master重命名为Adafruit_BME280_Library

将Adafruit_BMPE280_Library文件夹移至Arduino IDE安装库文件夹

最后,重新打开您的Arduino IDE

四、安装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,密码和Raspberry Pi IP地址来编辑代码。

cpp 复制代码
/*********
  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);
  }
}

该代码通过MQTT协议发布有关esp32 /温度和esp32 /湿度主题的温度和湿度读数。

ESP32订阅了esp32 / output主题,以接收Node-RED应用程序在该主题上发布的消息。 然后,根据收到的消息,它打开或关闭LED。

订阅MQTT主题

在reconnect()函数中,您可以订阅MQTT主题。 在这种情况下,ESP32仅订阅esp32 / output:

client.subscribe(" esp32 / output");

在callback()函数中,ESP32接收已订阅主题的MQTT消息。 根据MQTT主题和消息,它打开或关闭LED:

发布MQTT消息

在loop()中,每5秒发布一次新的读数:

相关推荐
沐欣工作室_lvyiyi2 小时前
基于单片机的智能电表设计(论文+源码)
单片机·嵌入式硬件·电能表·数字电能表
waicsdn_haha2 小时前
Visual Studio Code 2025 安装与高效配置教程
c语言·ide·windows·vscode·微软·编辑器·win7
半导体老登2 小时前
新能源汽车核心元件揭秘:二极管、三极管结构与工作原理解析(2/2)
人工智能·单片机·嵌入式硬件·汽车
猿~~~4 小时前
STM32的HAL库开发---多通道ADC采集(DMA读取)实验
stm32·单片机·嵌入式硬件
Freak嵌入式5 小时前
开源一款I2C电机驱动扩展板-FreakStudio多米诺系列
嵌入式硬件·嵌入式·智能硬件·开源硬件·micropython·电机驱动·电子模块
LaoZhangGong1237 小时前
STM32的“Unique device ID“能否修改?
c语言·经验分享·stm32·单片机·嵌入式硬件
树欲静而风不止慢一点吧7 小时前
Visual Studio 2022配置网址参考
ide·visual studio
佚明zj7 小时前
libxls库的编译以及基于Visual studio的配置
ide·visual studio
AnalogElectronic8 小时前
问题记录,在使用android studio 构建项目时遇到的问题
android·ide·android studio
1101 11018 小时前
STM32-心知天气项目
stm32·单片机·嵌入式硬件