ESP32教程46/55 - 使用HiveMQ MQTT进行远程温度监控 | SunFounder的ESP32套件
在本教程中,我们将使用ESP32和MQTT协议创建一个远程温度监控系统。该项目允许我们将温度数据发布到MQTT代理,并通过网页界面远程控制LED。通过按下按钮,我们可以将温度读数发送到云端,还可以接收命令来打开或关闭LED。
ESP32是一款功能强大的微控制器,内置Wi-Fi和蓝牙,非常适合物联网(IoT)应用。在此设置中,我们将使用NTC热敏电阻测量温度,使用按钮触发读数,并使用LED指示状态。数据将发送到HiveMQ(一个流行的MQTT代理),可在远程访问(视频中00:45处)。
硬件说明
对于此项目,我们将使用以下组件:
- ESP32微控制器:该板作为中央处理单元,处理Wi-Fi连接和MQTT通信。
- NTC热敏电阻:该温度传感器根据温度改变其电阻。它提供ESP32可读取的模拟信号,以确定当前温度。
- LED:该发光二极管将用于根据通过MQTT接收的命令指示状态。
- 按钮:该按钮将触发ESP32读取温度并将其发布到MQTT代理。
数据手册详情
| 制造商 | SunFounder |
|---|---|
| 零件编号 | ESP32 |
| 逻辑/IO电压 | 3.3 V |
| 电源电压 | 5 V(通过USB) |
| 输出电流(每通道) | 最大12 mA |
| PWM频率指导 | 最高40 kHz |
| 输入逻辑阈值 | 0.3 V(低),2.4 V(高) |
| 热限制 | -40至85 °C |
| 封装 | ESP32-WROOM-32 |
- 确保正确的电压电平以避免损坏。
- 为按钮使用上拉电阻以确保稳定的读数。
- 去耦电容有助于稳定电源。
- 注意热敏电阻的接线以避免错误读数。
- 验证您的MQTT代理详细信息以确保成功连接。
接线说明

要连接组件,首先连接NTC热敏电阻。将热敏电阻的一个引脚连接到ESP32上的3.3 V电源。另一个引脚连接到ESP32上的引脚36,并且还应连接一个10 kΩ电阻,该电阻再连接到地。这创建了一个分压器,使ESP32能够读取热敏电阻的电阻值。
接下来,连接LED。LED的较长引脚(阳极)通过220 Ω电阻连接到ESP32上的引脚4,而较短的引脚(阴极)连接到地。对于按钮,将一侧连接到3.3 V,另一侧连接到ESP32上的引脚14。此外,从按钮引脚连接一个10 kΩ电阻到地,以确保按钮未按下时保持稳定的低电平状态。
安装所需库
这里使用了PubSubClient库,您可以从库管理器中安装它。
代码示例与讲解
在设置中,我们初始化串行通信,设置Wi-Fi连接,并配置MQTT服务器。以下是设置代码的片段:
void setup() {
Serial.begin(115200);
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
}
这部分代码建立了与Wi-Fi网络的连接并设置了MQTT服务器。按钮和LED的引脚模式也在此处配置。
循环函数持续检查按钮状态,并在按下时发布温度数据。以下是循环中的重点摘录:
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
if (digitalRead(buttonPin)) {
long now = millis();
if (now - lastMsg > 5000) {
lastMsg = now;
char tempString[8];
dtostrf(thermistor(), 1, 2, tempString);
client.publish("SF/TEMP", tempString);
}
}
}
在此循环中,我们检查ESP32是否连接到MQTT代理。如果按下按钮,它会从热敏电阻读取温度并每5秒发布到主题"SF/TEMP"。
演示/预期效果
当项目设置并运行后,按下按钮会将当前温度发布到MQTT代理。您可以从任何MQTT客户端监控此数据。此外,您可以发送消息来控制LED;发送“on”将点亮它,而“off”将关闭它。请在视频15:30处观察预期行为,其中每次按下按钮后都会显示温度读数。
视频时间戳
- 00:00 开始
- 2:05 项目介绍
- 7:06 免费的HiveMQ服务
- 7:56 接线说明
- 11:11 Arduino代码说明
- 18:46 在Arduino IDE中选择ESP32开发板和COM端口
- 20:30 HiveMQ Free代理演示
/*
* :ref: https://randomnerdtutorials.com/esp32-mqtt-publish-subscribe-arduino-ide/
* https://docs.sunfounder.com/projects/kepler-kit/en/latest/iotproject/5.mqtt_pub.html
*/
#include <WiFi.h>
#include <PubSubClient.h>
// #include <Wire.h>
// 用您的SSID/密码组合替换下列变量。
const char* ssid = "SSID";
const char* password = "PASSWORD";
// 添加您的 MQTT 代理地址,例如:
const char* mqtt_server = "broker.hivemq.com";
const char* unique_identifier = "sunfounder-client-sdgvsda";
WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
int value = 0;
// LED引脚
const int ledPin = 4;
const int buttonPin = 14;
// 当你连接到WIFI时,只有36、39、34、35、32、33引脚可以用于模拟读取。
// 定义常量
const int thermistorPin = 36; // 连接到热敏电阻的引脚
const float referenceVoltage = 3.3;
const float referenceResistor = 10000; // 电阻值(10k)
const float beta = 3950; // 贝塔值(典型值)
const float nominalTemperature = 25; // 计算温度系数的名义温度
const float nominalResistance = 10000; // 在名义温度下的电阻值
void setup() {
Serial.begin(115200);
// 默认设置
setup_wifi();
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
}
void setup_wifi() {
delay(10);
// 我们首先连接到一个WiFi网络。
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();
// 如果在"SF/LED"主题上收到消息,你需要检查该消息是"开"还是"关"。
// 根据消息更改输出状态。
if (String(topic) == "SF/LED") {
Serial.print("Changing state to ");
if (messageTemp == "on") {
Serial.println("on");
digitalWrite(ledPin, HIGH);
} else if (messageTemp == "off") {
Serial.println("off");
digitalWrite(ledPin, LOW);
}
}
}
void reconnect() {
// 循环直到我们重新连接
while (!client.connected()) {
Serial.print("Attempting MQTT connection...");
// 尝试连接
if (client.connect(unique_identifier)) {
Serial.println("connected");
// 订阅
client.subscribe("SF/LED");
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// 请在重试之前等待5秒。
delay(5000);
}
}
}
float thermistor() {
int adcValue = analogRead(thermistorPin); // 读取ADC值
float voltage = (adcValue * referenceVoltage) / 4095.0; // 计算电压
float resistance = (voltage * referenceResistor) / (referenceVoltage - voltage); // 使用更新的配置计算热敏电阻电阻值
// 使用贝塔参数方程计算温度
float tempK = 1 / (((log(resistance / nominalResistance)) / beta) + (1 / (nominalTemperature + 273.15)));
float tempC = tempK - 273.15; // 获取摄氏温度
float tempF = 1.8 * tempC + 32.0; // 获取华氏温度
// 打印温度
Serial.print("Temp: ");
Serial.println(tempC);
delay(200); // 等待200毫秒
return tempC;
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
// 如果按钮被按下,发布温度到主题 "SF/TEMP"
if (digitalRead(buttonPin)) {
long now = millis();
if (now - lastMsg > 5000) {
lastMsg = now;
char tempString[8];
dtostrf(thermistor(), 1, 2, tempString);
client.publish("SF/TEMP", tempString);
}
}
}
Common Course Links
Common Course Files
资源与参考
-
文档ESP32 教程 46/55 - SunFounder 物联网通信的 MQTT 文档页面docs.sunfounder.com
文件📁
没有可用的文件。