ESP32 ESP32 温湿度监控系统:DHT22 + MQTT + Node-RED 仪表盘完整项目教程
项目概述
温湿度监控是物联网领域最经典、最基础的项目之一。无论是智能家居、农业大棚、仓储管理还是实验室环境监控,温湿度数据都是最基本的监测指标。
本教程将带你从零搭建一个完整的 ESP32 温湿度监控系统,涵盖:
- 硬件层:ESP32 开发板 + DHT22 温湿度传感器
- 通信层:MQTT 协议数据上报
- 服务层:Mosquitto MQTT Broker
- 可视化层:Node-RED 仪表盘
你也可以将 MQTT Broker 替换为任何公共 MQTT 云平台(如阿里云 IoT、华为云 IoT、EMQX Cloud),代码只需修改 Broker 地址。
硬件清单
| 组件 | 型号 | 数量 | 预估价格 |
|---|---|---|---|
| 开发板 | ESP32-DevKitC 或 NodeMCU-32S | 1 | ¥25-40 |
| 温湿度传感器 | DHT22 (AM2302) | 1 | ¥15-25 |
| 面包板 | 830 孔 | 1 | ¥8-12 |
| 杜邦线 | 公对母/公对公 | 10 根 | ¥3-5 |
| 电阻 | 4.7kΩ 上拉电阻 | 1 | ¥0.1 |
| MicroUSB 线 | 数据线 | 1 | ¥5-10 |
总计约 ¥60-90,你大部分组件可能已有现成的。
硬件接线
DHT22 引脚定义
DHT22 有 4 个引脚(从左到右,面对传感器正面):
| 引脚 | 名称 | 说明 |
|---|---|---|
| 1 | VDD | 电源正极 3.3V-5V |
| 2 | DATA | 数据引脚 |
| 3 | NC | 空脚(不连接) |
| 4 | GND | 电源负极/地 |
接线图
ESP32 DHT22
------ -----
3.3V ────────────── VDD (引脚1)
GPIO4 ────────────── DATA (引脚2)
NC (引脚3) — 不接
GND ────────────── GND (引脚4)
关键注意事项:
- DATA 引脚到 3.3V 之间需接一个 4.7kΩ 上拉电阻(DHT22 使用单总线协议,需要上拉电阻保证信号稳定)
- 如果使用 DHT22 模块版(带 PCB 的),通常已集成上拉电阻,可直接接线
- 线与线之间保持距离,避免信号串扰
环境配置
1. 安装 ESP32 开发环境
本教程使用 Arduino IDE,这是最快速的入门方式。
步骤:
- 下载并安装 Arduino IDE(推荐 2.x 版本)
- 打开 Arduino IDE → 文件 → 首选项 → 附加开发板管理器网址,添加:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - 工具 → 开发板 → 开发板管理器 → 搜索 “ESP32” → 安装
- 安装完成后,在「工具 → 开发板」中选择 ESP32 Dev Module
2. 安装所需库
在 Arduino IDE 中:工具 → 管理库 → 搜索并安装以下库:
- DHT sensor library by Adafruit (v1.4.4+)
- Adafruit Unified Sensor by Adafruit (v1.1.9+)
- PubSubClient by Nick O’Leary (v2.8+)
- ArduinoJson by Benoit Blanchon (v6.21+)
完整代码
#include <WiFi.h>
#include <PubSubClient.h>
#include <DHT.h>
#include <ArduinoJson.h>
// ===== WiFi 配置 =====
const char* ssid = "你的WiFi名称";
const char* password = "你的WiFi密码";
// ===== MQTT 配置 =====
const char* mqtt_server = "你的MQTT服务器IP";
const int mqtt_port = 1883;
const char* mqtt_topic = "sensor/temperature-humidity";
// ===== DHT22 配置 =====
#define DHTPIN 4 // GPIO4 连接 DHT22 DATA
#define DHTTYPE DHT22 // DHT22 传感器 (AM2302)
DHT dht(DHTPIN, DHTTYPE);
// ===== 全局对象 =====
WiFiClient espClient;
PubSubClient client(espClient);
// ===== 上报间隔 =====
unsigned long lastMsg = 0;
const long interval = 30000; // 30 秒上报一次
// ===== WiFi 连接 =====
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("连接 WiFi: ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println();
Serial.println("WiFi 连接成功");
Serial.print("IP 地址: ");
Serial.println(WiFi.localIP());
}
// ===== MQTT 重连 =====
void reconnect() {
while (!client.connected()) {
Serial.print("连接 MQTT...");
String clientId = "ESP32Client-";
clientId += String(random(0xffff), HEX);
if (client.connect(clientId.c_str())) {
Serial.println("已连接");
} else {
Serial.print("失败 rc=");
Serial.print(client.state());
Serial.println(" 5 秒后重试");
delay(5000);
}
}
}
// ===== 初始化 =====
void setup() {
Serial.begin(115200);
Serial.println("ESP32 温湿度监控系统启动");
dht.begin();
setup_wifi();
client.setServer(mqtt_server, mqtt_port);
}
// ===== 主循环 =====
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
unsigned long now = millis();
if (now - lastMsg > interval) {
lastMsg = now;
// 读取温湿度
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
// 检查读取是否成功
if (isnan(humidity) || isnan(temperature)) {
Serial.println("DHT22 读取失败!");
return;
}
// 构建 JSON 数据包
StaticJsonDocument<200> doc;
doc["temperature"] = temperature;
doc["humidity"] = humidity;
doc["device"] = "esp32-001";
char buffer[256];
size_t n = serializeJson(doc, buffer);
// 发布到 MQTT
if (client.publish(mqtt_topic, buffer, n)) {
Serial.print("数据已发送: ");
Serial.print("温度: ");
Serial.print(temperature);
Serial.print("°C, 湿度: ");
Serial.print(humidity);
Serial.println("%");
} else {
Serial.println("MQTT 发布失败");
}
}
}
代码说明
关键函数解析:
setup_wifi():连接 WiFi,显示 IP 地址用于调试reconnect():MQTT 断线自动重连(带随机 Client ID 避免冲突)dht.readTemperature()/dht.readHumidity():读取 DHT22 数据client.publish():以 JSON 格式将数据发布到 MQTT Topic- 每 30 秒上报一次,防止数据过于频繁
为什么用 JSON 格式?
- 结构清晰,可扩展(以后可以添加更多传感器字段)
- Node-RED 和云平台都原生支持 JSON 解析
- 比纯文本格式更适合多字段数据
搭建 MQTT Broker
方案一:本地 Mosquitto(推荐)
使用 Docker 一键部署:
docker run -d \
--name mosquitto \
-p 1883:1883 \
-p 9001:9001 \
-v mosquitto_data:/mosquitto/data \
-v mosquitto_log:/mosquitto/log \
eclipse-mosquitto:2
方案二:公共云平台
| 平台 | 免费额度 | 特点 |
|---|---|---|
| EMQX Cloud | 100 连接 | 全球节点,延迟低 |
| 阿里云 IoT | 50 设备 | 国内速度快 |
| HiveMQ Cloud | 10 连接 | 无需注册,即开即用 |
| 腾讯云 IoT | 100 设备 | 与微信生态集成好 |
验证 MQTT 服务
安装 MQTT 客户端工具:
# 安装 mosquitto 客户端 (macOS)
brew install mosquitto
# 订阅数据(在另一终端窗口运行)
mosquitto_sub -h 你的MQTT服务器IP -t "sensor/temperature-humidity"
# 如果看到类似以下输出,说明系统跑通了
{"temperature": 26.3, "humidity": 58.2, "device": "esp32-001"}
Node-RED 仪表盘
1. 安装 Node-RED
# 使用 Docker 一键部署
docker run -d \
--name nodered \
-p 1880:1880 \
-v nodered_data:/data \
nodered/node-red:latest
2. 安装 Dashboard 插件
浏览器访问 http://你的服务器IP:1880,点击右上角菜单 → 管理面板 → 安装:
node-red-dashboard
3. 创建数据流
导入以下 JSON 流到 Node-RED:
- 复制下面的 JSON 代码
- 在 Node-RED 中:菜单 → 导入 → 剪贴板
- 粘贴后点击部署
[
{
"id": "mqtt-in",
"type": "mqtt in",
"topic": "sensor/temperature-humidity",
"broker": "localhost",
"port": "1883",
"name": "接收传感器数据",
"datatype": "json"
},
{
"id": "function-parse",
"type": "function",
"func": "msg.payload = JSON.parse(msg.payload);\nmsg.temperature = msg.payload.temperature;\nmsg.humidity = msg.payload.humidity;\nreturn msg;",
"name": "解析 JSON"
},
{
"id": "ui-temp",
"type": "ui_gauge",
"group": "sensor-group",
"label": "温度",
"format": "{{value}} °C",
"min": 0,
"max": 50,
"colors": ["#00b500","#e6e600","#ca3838"]
},
{
"id": "ui-humid",
"type": "ui_gauge",
"group": "sensor-group",
"label": "湿度",
"format": "{{value}} %",
"min": 0,
"max": 100,
"colors": ["#00b500","#e6e600","#ca3838"]
},
{
"id": "ui-chart",
"type": "ui_chart",
"group": "sensor-group",
"label": "温湿度趋势",
"chartType": "line",
"x": 10,
"y": 10,
"w": 20,
"h": 10
}
]
4. 访问仪表盘
浏览器打开 http://你的服务器IP:1880/ui,即可看到实时温湿度仪表盘:
- 温度仪表盘(0-50°C,绿-黄-红 三色)
- 湿度仪表盘(0-100%)
- 温湿度趋势折线图
调试与排错
常见问题
1. DHT22 读取失败(NaN)
- 检查 4.7kΩ 上拉电阻是否接好
- 确认 DATA 引脚连接到 GPIO4(代码中定义的 DHTPIN)
- 尝试将 DHT22 换成 DHT11(代码中
#define DHTTYPE DHT22改为DHT11)
2. WiFi 连接失败
- 检查 SSID 和密码是否正确
- ESP32 仅支持 2.4GHz WiFi,不支持 5GHz
- 确认路由器 DHCP 功能正常
3. MQTT 连接失败
- 检查防火墙是否开放 1883 端口
- 确认 MQTT Broker 正在运行:
docker ps | grep mosquitto - 查看 MQTT Broker 日志:
docker logs mosquitto
4. 数据乱码或不完整
- 确认 JSON 格式正确,可以使用在线 JSON 校验工具检查
- 增大 PubSubClient 缓冲区:在代码开头添加
#define MQTT_MAX_PACKET_SIZE 512
扩展方向
基础项目跑通后,你可以轻松扩展:
多传感器整合:
- 添加光照传感器(BH1750)→ 光照度数据
- 添加土壤湿度传感器 → 植物浇水监控
- 添加气压传感器(BMP280)→ 天气预报
数据持久化:
- 将 MQTT 数据存入 InfluxDB 时序数据库
- 使用 Grafana 创建更专业的仪表盘
远程访问:
- 使用 FRP 或 Ngrok 将 MQTT Broker 暴露到公网
- 或直接用云平台 MQTT 服务(阿里云/华为云/EMQX Cloud)
低功耗改造:
- 启用 ESP32 深度睡眠模式,电池供电
- 只在需要采集数据时唤醒,大幅延长续航
总结
本教程从零搭建了一个完整的 ESP32 温湿度监控系统,涵盖了:
- 硬件选型与接线
- Arduino IDE 开发环境配置
- DHT22 数据读取与 MQTT 上报
- Mosquitto Broker 部署
- Node-RED 仪表盘可视化
这个项目是物联网入门的最佳实践——它包含了 IoT 系统的完整链路:感知层 → 网络层 → 平台层 → 应用层。跑通这个项目后,你已经掌握了 IoT 开发的核心技能,可以轻松扩展到其他传感器和应用场景。
下一步推荐:尝试将 ESP32 切换到深度睡眠模式,用两节 AA 电池供电,做一个能运行数月的无线温湿度监测节点。