资讯动态

ESP32-C6本地温度告警系统搭建:从传感器到MQTT推送

发布时间:2026/10/9 3:38:55 来源:尧图企业网站定制
1. 为什么我要自己搭一套温度告警系统去年夏天家里那台老冰箱差点把我一柜子的食材全毁了。冷藏室温度悄悄爬到了12度等我发现的时候冷冻层的冰淇淋已经化成了一滩甜水。更气人的是我明明装了一个几十块钱的蓝牙温度计但它只能在十米范围内用手机看我人在公司根本不知道家里发生了什么。这件事之后我就下定决心要搞一套真正能主动通知我的温度告警系统。市面上的成品方案我看了不少要么是云端服务按月收费要么是数据必须经过厂商服务器隐私上总觉得不太踏实要么就是功能太简陋连个自定义阈值都设不了。折腾了一圈我最后选了ESP32-C6这块芯片自己搭了一套完全本地运行、不依赖任何外部服务的温度告警系统。这套系统的核心思路很简单用ESP32-C6作为主控接上温度传感器定时采集数据当温度超过我设定的阈值时通过本地网络直接推送告警到我的手机和电脑上。整个过程数据不出家门不需要注册任何账号也不存在服务商跑路导致系统瘫痪的风险。整套硬件成本算下来不到一百块但给我的安全感远超这个价格。这篇文章我会把整个搭建过程拆开来讲从硬件选型、传感器接线、固件编写、告警推送方案到实际部署中踩过的坑和调试技巧全部毫无保留地分享出来。不管你是刚接触嵌入式的新手还是已经玩过几块开发板的老手都能从里面找到可以直接抄作业的内容。我尽量把每个决策背后的原因讲清楚让你不仅知道怎么做还知道为什么这么做。2. 硬件选型与整体方案设计2.1 为什么是ESP32-C6而不是其他型号ESP32系列芯片型号多得让人眼花缭乱从经典的ESP32到ESP32-S3、ESP32-C3、ESP32-C6每一款都有自己的定位。我选C6主要看中三点第一它支持Wi-Fi 6虽然家里路由器不一定支持但功耗和连接稳定性确实比老款好一些第二它内置了Thread和Zigbee的射频模块虽然我目前用不到但以后想扩展成Mesh网络的时候不用换硬件第三它的RISC-V单核架构对于这种简单的温度采集任务完全够用而且价格便宜某宝上裸芯片十几块钱开发板也就三四十。相比之下ESP32-S3虽然性能更强但多出来的算力和PSRAM对我这个场景完全是浪费。ESP32-C3也是个不错的选择价格更便宜但C6的Wi-Fi 6和Thread支持让我觉得多花几块钱值得。如果你手头已经有C3或者老款ESP32完全可以直接用代码逻辑基本通用只需要注意引脚定义和Wi-Fi库的细微差别。注意ESP32-C6的开发板在市面上有好几个版本有的带USB-C接口和板载天线有的需要外接天线。买的时候看清楚带板载天线的版本对新手更友好省得还要自己配天线匹配电路。2.2 温度传感器的选择与对比温度传感器我试过三种DS18B20、DHT22和SHT31。DS18B20是单总线数字传感器防水版本可以直接扔进水里测水温精度在±0.5度左右价格便宜但采样速度慢每次转换需要750毫秒。DHT22便宜是便宜但精度和长期稳定性都一般湿度读数经常漂移我不太推荐用在需要长期可靠运行的场景。SHT31是I2C接口精度±0.3度响应快长期漂移小价格大概十几块钱是我最终选用的型号。如果你只是测室温DS18B20完全够用而且防水探头可以延伸到冰箱里、鱼缸里、甚至室外。如果你需要同时测湿度和温度SHT31是更好的选择。我最终在冰箱冷藏室和冷冻室各放了一个DS18B20防水探头在客厅放了一个SHT31测环境温湿度这样一套系统覆盖了所有我关心的点位。传感器型号接口类型温度精度湿度支持防水版本参考价格DS18B20单总线±0.5°C不支持有5-8元DHT22单总线±0.5°C支持无10-15元SHT31I2C±0.3°C支持无15-20元2.3 告警推送方案的取舍告警推送是整个系统里最关键的环节也是我花时间最多的地方。我试过几种方案邮件推送、Telegram Bot、企业微信机器人、以及本地MQTT加手机App。邮件推送的延迟不稳定有时候几分钟才到而且容易被当成垃圾邮件。Telegram Bot在国内用起来不方便直接排除。企业微信机器人需要企业认证个人用不了。最后我选了本地MQTT加手机App的方案配合一个简单的Webhook转发实现了秒级推送。具体来说ESP32-C6通过MQTT协议把温度数据发布到本地运行的Mosquitto broker上然后我用一个Node-RED流来订阅这些数据判断是否超过阈值如果超过就调用手机App的Webhook接口推送通知。整个链路都在本地网络内完成不经过任何外部服务器。手机App我用的是Bark它是一个开源的通知推送工具自己搭一个服务端就能用iOS和Android都支持。提示如果你不想折腾MQTT和Node-RED也可以用ESP32直接调用HTTP接口推送告警。但这种方式的问题是如果网络临时抖动告警就丢了。MQTT的QoS机制可以保证消息至少送达一次可靠性高很多。3. 核心细节解析与实操要点3.1 硬件接线与供电注意事项DS18B20的接线很简单三根线VCC接3.3VGND接地DQ接任意GPIO。但有一个细节很多人会忽略DQ引脚需要接一个4.7kΩ的上拉电阻到3.3V。有些开发板自带了上拉电阻但大部分没有你必须自己加一个。我一开始没加上拉电阻读数一直是-127度排查了半天才发现是这个问题。SHT31通过I2C连接需要接SDA、SCL、VCC和GND四根线。ESP32-C6的默认I2C引脚是GPIO 6和GPIO 7但你可以在代码里改成任意可用的GPIO。我建议用默认引脚省得改代码。SHT31的I2C地址是0x44如果你同时接多个I2C设备注意地址不要冲突。供电方面ESP32-C6的工作电压是3.3V但开发板通常带一个USB转3.3V的稳压芯片所以你直接用USB线供电就行。如果你要部署在冰箱附近可以用一个5V的USB电源适配器接一根长一点的USB线。注意USB线的质量劣质线材压降大会导致ESP32重启。3.2 固件框架的选择Arduino还是ESP-IDFESP32-C6可以用Arduino框架也可以用官方的ESP-IDF。Arduino上手快库多适合快速原型开发。ESP-IDF更底层控制更精细但学习曲线陡峭。我这个项目对实时性要求不高Arduino完全够用而且DS18B20和SHT31都有现成的Arduino库省去了自己写驱动的麻烦。不过有一点要注意ESP32-C6在Arduino框架下的支持是最近才完善的你需要用比较新的Arduino IDE版本并且在开发板管理器里安装最新的ESP32开发板支持包。我一开始用的是旧版本编译一直报错升级到最新版就好了。// 这是DS18B20读取温度的核心代码片段 #include OneWire.h #include DallasTemperature.h #define ONE_WIRE_BUS 4 // DQ接在GPIO4上 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(oneWire); void setup() { Serial.begin(115200); sensors.begin(); } void loop() { sensors.requestTemperatures(); float tempC sensors.getTempCByIndex(0); if (tempC DEVICE_DISCONNECTED_C) { Serial.println(传感器未连接); } else { Serial.print(温度: ); Serial.println(tempC); } delay(2000); }3.3 MQTT主题设计与数据格式MQTT的主题设计看起来简单但设计不好后期扩展会很麻烦。我用的主题结构是home/sensor/位置/类型比如home/sensor/fridge/temperature和home/sensor/livingroom/humidity。这样设计的好处是我可以用通配符home/sensor//temperature一次性订阅所有温度数据也可以用home/sensor/fridge/#订阅冰箱的所有传感器数据。数据格式我用的是JSON虽然比纯文本多几个字节但可读性和扩展性好很多。一个典型的消息体是这样的{ value: 4.2, unit: C, timestamp: 1712345678, sensor: DS18B20, rssi: -52 }里面包含了温度值、单位、时间戳、传感器型号和Wi-Fi信号强度。信号强度这个字段是我后来加的因为有一次冰箱门关上之后信号衰减严重导致数据断断续续加了RSSI之后就能提前发现信号问题。注意MQTT的QoS等级我设的是1保证消息至少送达一次。如果你对重复消息不敏感QoS 0也够用但告警场景下我建议至少用QoS 1。4. 实操过程与核心环节实现4.1 开发环境搭建与固件编译第一步是装Arduino IDE。去官网下载最新版安装的时候记得勾选驱动。装完之后打开首选项在“附加开发板管理器网址”里填入ESP32的板支持包地址。然后在开发板管理器里搜索esp32安装最新版本。这个过程需要下载几百兆的文件网络不好的话可能要等一会儿。装好之后在工具菜单里选择开发板为“ESP32C6 Dev Module”端口选择你的开发板对应的串口。如果你用的是Linux或者Mac可能需要手动安装CH340或者CP2102的驱动。Windows一般会自动装好。接下来安装库。在库管理器里搜索并安装以下几个库OneWire、DallasTemperature、Adafruit SHT31 Library、PubSubClient。PubSubClient是MQTT客户端库我用的是它但如果你需要TLS加密可以考虑用AsyncMqttClient。4.2 Wi-Fi连接与MQTT客户端初始化Wi-Fi连接这部分有一个坑ESP32-C6默认的Wi-Fi模式是STA但如果你之前刷过其他固件可能残留了AP模式的配置。我在代码里显式调用了WiFi.mode(WIFI_STA)来确保模式正确。另外Wi-Fi连接超时时间我设的是20秒超时后自动重启避免设备卡死在连接状态。#include WiFi.h #include PubSubClient.h const char* ssid 你的Wi-Fi名称; const char* password 你的Wi-Fi密码; const char* mqtt_server 192.168.1.100; WiFiClient espClient; PubSubClient client(espClient); void setup_wifi() { delay(10); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); int retries 0; while (WiFi.status() ! WL_CONNECTED retries 40) { delay(500); retries; } if (WiFi.status() ! WL_CONNECTED) { ESP.restart(); } } void reconnect_mqtt() { while (!client.connected()) { String clientId ESP32C6-; clientId String(random(0xffff), HEX); if (client.connect(clientId.c_str())) { // 连接成功 } else { delay(5000); } } }4.3 温度采集与阈值判断逻辑温度采集我用了非阻塞的方式每2秒读一次传感器但每30秒才发布一次MQTT消息。这样做的原因是DS18B20的转换时间比较长频繁读取会影响其他任务的执行。阈值判断我设了两级警告阈值和严重阈值。比如冰箱冷藏室警告阈值是8度严重阈值是10度。超过警告阈值发一条普通通知超过严重阈值发一条带声音的紧急通知。阈值的设定需要根据你的实际场景来调整。冰箱冷藏室的正常温度是2到5度所以我把警告阈值设在8度留了3度的缓冲。冷冻室正常是-18度我把警告阈值设在-12度。客厅的舒适温度范围我设的是18到28度超出就提醒。float lastTemp 0; unsigned long lastPublish 0; const unsigned long publishInterval 30000; void loop() { client.loop(); if (!client.connected()) { reconnect_mqtt(); } sensors.requestTemperatures(); float tempC sensors.getTempCByIndex(0); if (tempC ! DEVICE_DISCONNECTED_C) { lastTemp tempC; } if (millis() - lastPublish publishInterval) { String payload {\value\: String(lastTemp, 1) ,\unit\:\C\,\rssi\: String(WiFi.RSSI()) }; client.publish(home/sensor/fridge/temperature, payload.c_str()); lastPublish millis(); } delay(100); }4.4 Node-RED告警流配置Node-RED的安装很简单一条命令搞定。装好之后在浏览器里打开http://你的IP:1880就能看到图形化编程界面。我搭的流是这样的一个MQTT输入节点订阅home/sensor//temperature一个函数节点判断温度是否超过阈值一个HTTP请求节点调用Bark的推送接口。函数节点的代码逻辑是这样的var temp msg.payload.value; var location msg.topic.split(/)[2]; var threshold 8; // 警告阈值 if (temp threshold) { msg.payload { title: 温度告警, body: location 当前温度 temp °C超过阈值 threshold °C }; return msg; } return null;Bark的推送接口就是一个简单的GET请求把标题和内容拼在URL里就行。如果你用的是其他推送工具比如Pushover或者Gotify接口格式不同但逻辑一样。提示Node-RED的函数节点里可以加一个去重逻辑比如5分钟内同一个位置只发一次告警避免温度在阈值附近波动时疯狂推送。5. 常见问题与排查技巧实录5.1 传感器读数异常怎么办DS18B20最常见的异常是读数-127度这通常意味着传感器没有正确响应。排查顺序是这样的先检查接线是否松动特别是DQ引脚然后检查上拉电阻是否接好4.7kΩ是标准值但3.3kΩ到10kΩ之间都能工作最后检查传感器是否损坏换一个试试。如果读数偶尔跳变可能是线太长导致信号衰减缩短线长或者降低上拉电阻值可以改善。SHT31的常见问题是I2C地址冲突或者总线锁死。如果你发现读数一直是0或者固定值先用I2C扫描程序确认设备地址是否正确。总线锁死的话给SHT31断电重启通常能解决。5.2 Wi-Fi连接不稳定导致数据断流ESP32-C6的Wi-Fi性能整体不错但在冰箱这种金属屏蔽环境里信号衰减会很严重。我的解决办法是在冰箱附近放一个Wi-Fi中继器或者用外接天线版本的开发板。另外在代码里加一个看门狗定时器如果Wi-Fi断开超过60秒就自动重启这样即使网络临时出问题设备也能自己恢复。还有一个容易被忽略的点是路由器的DHCP租期。如果租期太短ESP32的IP地址会频繁变化导致MQTT连接断开。我建议在路由器里给ESP32分配一个静态IP一劳永逸。5.3 MQTT消息丢失或延迟MQTT消息丢失通常是因为QoS等级设得太低或者broker的性能不够。Mosquitto在树莓派上跑几百个主题完全没问题但如果你用的是更弱的设备可能需要调整max_queued_messages参数。另外ESP32的PubSubClient库默认的缓冲区大小是256字节如果你的JSON消息超过这个长度消息会被截断。在PubSubClient.h里把MQTT_MAX_PACKET_SIZE改大就行。延迟问题一般是网络问题不是MQTT本身的问题。你可以用mosquitto_sub命令在电脑上订阅同样的主题对比一下延迟。如果电脑上延迟正常那就是ESP32的Wi-Fi信号问题。问题现象可能原因排查方法解决方案读数-127°C传感器未连接检查接线和上拉电阻重新接线加4.7kΩ上拉读数跳变线太长或干扰缩短线长远离电源线加屏蔽层或降低上拉电阻Wi-Fi频繁断开信号弱或DHCP租期短查看RSSI值加中继器或设静态IPMQTT消息截断缓冲区太小检查消息长度增大MQTT_MAX_PACKET_SIZE告警重复推送阈值附近波动查看Node-RED日志加去重逻辑5.4 设备长期运行的稳定性优化嵌入式设备长期运行最大的敌人是内存泄漏和看门狗复位。Arduino框架下String类的频繁使用会导致内存碎片化我建议尽量用字符数组代替String。另外在loop()里加一个ESP.wdtFeed()或者用esp_task_wdt_reset()喂狗防止看门狗误复位。还有一个小技巧每隔24小时自动重启一次ESP32。虽然听起来有点粗暴但确实能解决大部分长期运行导致的奇怪问题。我是在Node-RED里加了一个定时流每天凌晨3点给ESP32发一个重启命令。6. 系统扩展与进阶玩法6.1 增加更多传感器节点一套系统只测一个点太浪费了ESP32-C6支持多个GPIO你可以同时接多个DS18B20。DS18B20的单总线协议支持在一根线上挂多个传感器每个传感器有唯一的64位地址。你只需要在代码里遍历所有地址就能读取每个传感器的温度。我目前一根总线上挂了3个DS18B20分别测冷藏室、冷冻室和室外温度工作很稳定。如果你需要覆盖更大的范围可以再买几块ESP32-C6每块负责一个区域通过MQTT发布到不同的主题。Node-RED那边只需要加一个通配符订阅就能全部收进来。6.2 数据持久化与历史曲线光有告警还不够我还想把温度数据存下来看看冰箱的制冷周期是否正常。最简单的方案是在Node-RED里加一个InfluxDB输出节点把数据写到InfluxDB里然后用Grafana画曲线。InfluxDB和Grafana都可以跑在同一个树莓派上资源占用不大。如果你不想折腾数据库也可以用Node-RED的file节点把数据追加到CSV文件里简单粗暴但有效。我两种都试过CSV方案适合快速查看InfluxDB加Grafana适合长期趋势分析。6.3 断电恢复与数据补传ESP32-C6断电后重新上电会自动重连Wi-Fi和MQTT这个没问题。但断电期间的温度数据就丢了。如果你在意这个可以在ESP32上加一个SD卡模块把数据先写到SD卡里联网后再补传。不过对于温度告警这个场景断电期间的数据意义不大我选择不补传保持系统简单。注意如果你用SD卡方案注意SD卡在断电时可能损坏文件系统。建议用LittleFS或者SPIFFS文件系统它们对断电的容忍度比FAT32好。7. 我踩过的坑和最后分享几个技巧第一个坑是上拉电阻。我一开始以为开发板自带了结果读数一直是-127查了半天数据手册才发现需要外接。这个坑很典型新手很容易忽略。第二个坑是MQTT的客户端ID冲突。我同时跑了两块ESP32用了相同的客户端ID结果两块板子互相踢下线。后来在客户端ID里加了随机数才解决。第三个坑是Node-RED的函数节点返回值。如果函数返回null消息会被丢弃这是正常的。但如果你不小心返回了undefinedNode-RED会报错。写JavaScript的时候注意一下。最后分享一个实用技巧在ESP32的代码里加一个LED指示灯Wi-Fi连接成功时常亮MQTT连接成功时慢闪有数据发布时快闪一下。这样你不用打开串口监视器就能知道设备的工作状态排查问题的时候特别方便。这套系统我已经稳定运行了大半年期间成功预警了两次冰箱门没关严和一次冷冻室化霜异常。硬件成本不到一百块但避免的损失远超这个数。如果你也想搭一套建议先从一块开发板和一个传感器开始跑通了再逐步扩展。不要一上来就搞太复杂容易半途而废。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑