ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于ESP32的物联网室内空气质量监测系统搭建指南

基于ESP32的物联网室内空气质量监测系统搭建指南 装修完第二年我总觉得家里空气不对劲。手边那台几百块的检测仪只能看个瞬时数值想对比不同房间还得来回跑后来把净化器的PM2.5读数和检测仪放在一起发现数字差了快一倍两个设备到底谁在说谎谁也说不清楚。与其天天猜我决定自己搭一套能连续记录、多点部署、能联动报警的物联网室内空气质量监测系统。这篇文章就是我搭建过程的完整复盘包括硬件选型、传感器校准、数据链路、实测结果还有那些翻了大跟头才总结出来的坑。这套系统适合谁看如果你手头有ESP32、树莓派或者只是想给家里添置一套更靠谱的空气质量记录工具又不想被品牌生态绑住那这篇文章可以直接抄作业。我会把每一步的选型理由、为什么这样做、以及我试过的失败方案都说清楚尽量让你少走弯路。1. 为什么自己搭一套物联网空气质量监测系统——先搞清楚需求边界1.1 成品检测仪与自建系统的差距市面上的成品空气质量检测仪大多只做“单点、瞬时、本地显示”这件事。你按一下按钮它给出当前PM2.5、甲醛、TVOC的数据然后就没有然后了。问题在于室内空气质量是个动态变化的过程做饭时厨房颗粒物会瞬间升高晚上卧室关窗睡觉CO2会慢慢积累新家具里的甲醛在温度升高时会加速释放。这些变化靠一台几百块的机器根本捕捉不到。即便是一些支持App联网的智能检测仪也存在两个硬伤一是数据闭源你拿不到原始数值只能看厂商给你算好的“指数”二是无法跨品牌联动不能同时控制多个房间的新风机、空气净化器。对我来说我需要知道的是“客厅现在PM2.5多少”“卧室的CO2什么时候超过安全线”“厨房做饭后多长时间能降回来”——这些需求只有自己搭一套可编程、可组合的物联网系统才能满足。1.2 设计目标与整体框架动手之前我先给自己定了几个硬指标支持多点部署至少三个监测节点客厅、卧室、厨房节点能独立工作。数据必须连续记录至少保留一周以上的历史曲线方便分析作息对空气的影响。传感器模块化颗粒物、CO2、甲醛、温湿度分开坏哪个换哪个。通信采用本地优先不依赖某个厂商云数据能自己备份。最好能联动家里已有的智能设备比如自动开空气净化器、推送到手机。整体框架其实很简单就是一条流水线传感器采集 → 主控读取 → 网络传输 → 平台存储/展示 → 报警/联动。硬件上我选择了ESP32作为主控传感器用串口和I2C接入数据通过Wi-Fi以MQTT协议发给本地的Home Assistant再由Home Assistant负责展示和自动化。下面我详细说每个环节的选择。2. 硬件选型传感器、主控与供电每一步都有讲究2.1 颗粒物、CO2、甲醛传感器怎么选这是整套系统里最核心的部分。传感器选错了后面所有数据处理都是白搭。我对比过市面上常见的几类传感器最终选择了以下组合。检测项推荐型号原理输出接口参考价格说明PM2.5/PM10Plantower PMS5003激光散射UART60-80元性价比极高性能稳定市面上很多净化器都采用它CO2SenseAir S8非色散红外UART/PWM200-300元寿命长精度高抗干扰好甲醛Winsen ZE08-CH2O电化学UART120-160元测甲醛的常见方案需要通电预热温湿度SHT30电容式I2C15-20元精度足够功耗低比DHT22靠谱得多颗粒物传感器我用了PMS5003选它的核心原因是便宜且应用广泛。它通过风扇把空气吸进光腔用激光照射颗粒物根据散射光的强度和时间估算浓度。这个传感器虽然不能等同于专业仪器但在家用场景下已经很能说明问题了。CO2传感器我选了SenseAir S8没有用更便宜的MH-Z19B。原因有两点S8的长期稳定性更好年漂移率很小适合需要连续运行的场景另外S8的功耗和体积也更有优势。如果预算紧张MH-Z19B其实也够用但市面上假货多需要仔细辨别。甲醛传感器选的是Winsen ZE08-CH2O电化学原理。这里要提醒一句电化学传感器刚通电时输出不稳定建议让它预热至少10分钟再读取数据。而且甲醛传感器对温度和湿度敏感如果系统里没有温湿度传感器测出来的甲醛数字基本没法看。温湿度传感器用了SHT30它比DHT22的精度高而且是工业级I2C接口不容易出现DHT22那种时序问题。如果你只需要大概参考DHT22也能凑合但我建议既然做了就做做好。2.2 主控选型ESP32为什么是性价比之选主控我用的是ESP32 DevKitC。为什么不是ESP8266、STM32或者树莓派ESP8266价格更便宜但它只有一个UART而我的传感器里PMS5003、S8、ZE08都需要UART三路串口加上温湿度I2CESP8266根本不够用。STM32的串口和外设资源丰富但开发门槛高还要额外配Wi-Fi模块对于这种连着无线网络的家用物联网项目来说属于自找麻烦。树莓派作为主控更是没必要它适合做后端服务放在传感器节点上等于拿大炮打蚊子功耗和成本都不划算。ESP32的优势正好卡在中间两个UART可以分配给颗粒物和CO2传感器再加一个软件模拟串口给甲醛传感器剩下I2C给温湿度它自带Wi-Fi和蓝牙可以直接连路由器不需要外挂模块双核处理器一个核跑业务逻辑一个核做网络通信不会互相卡顿。开发用Arduino框架生态成熟代码写起来也顺手。如果你需要更稳定可靠的工业级方案可以换ESP32-WROOM模块再扩展RS485但家用场景下DevKitC已经足够了。2.3 供电与外壳稳定压倒一切供电是新手最容易翻车的地方。空气质量监测节点是24小时不间断运行的如果供电不稳传感器数据会跳成锯齿状甚至直接重启。我最初用手机充电头供电5V/1A直连ESP32的5V引脚结果颗粒物数值忽高忽低检查半天发现是充电头纹波太大。后来我改用12V电源适配器经过降压模块输出5V并在电源输出端并联一个470uF电解电容和一个100nF陶瓷电容问题立刻消失。这里建议采购质量好一点的降压模块别用那种几块钱的。另外ESP32的3.3V由板载LDO稳压但传感器模块最好单独从5V取电避免ESP32板载稳压器发热影响传感器精度。外壳方面我一开始用的是全封闭亚克力盒子结果传感器被闷在里面数值比实际高了不少。后来学聪明了给颗粒物传感器开进风口和出风口给CO2传感器露出气孔甲醛传感器也是多孔设计。如果不想自己打孔可以直接买成品带开口的接线盒再配合几张防尘网效果不错。3. 从采集到上云数据链路搭建与协议选择3.1 主控端读取传感器的关键细节硬件连接好之后第一步就是让主控能读到准确的传感器数据。PMS5003和SenseAir S8都是UART接口波特率分别9600和19200它们会主动向上位机推送数据帧。我使用ESP32的硬件串口分别连接读取时只需要解析固定格式的帧头。比如PMS5003的数据帧以0x42 0x4D开头后面包含PM1.0、PM2.5、PM10的浓度值。MH-Z19B或S8则遵循各自的协议通常也是主动上报。甲醛传感器ZE08-CH2O也是UART我用的软件串口读取波特率9600。下面是ESP32读取PMS5003和S8并通过MQTT发布的示例代码片段。这里只展示关键逻辑实际项目里建议加看门狗和超时重试。#include WiFi.h #include PubSubClient.h #include SoftwareSerial.h #include Wire.h #include Adafruit_SHT31.h // 硬件串口根据实际接线调整 #define PMS_RX 16 #define PMS_TX 17 #define S8_RX 18 #define S8_TX 19 #define ZE8_RX 26 #define ZE8_TX 25 HardwareSerial pmsSerial(1); HardwareSerial s8Serial(2); SoftwareSerial ze8Serial(ZE8_RX, ZE8_TX); Adafruit_SHT31 sht31 Adafruit_SHT31(); WiFiClient espClient; PubSubClient mqttClient(espClient); void setup() { Serial.begin(115200); pmsSerial.begin(9600, SERIAL_8N1, PMS_RX, PMS_TX); s8Serial.begin(19200, SERIAL_8N1, S8_RX, S8_TX); ze8Serial.begin(9600); Wire.begin(); if (!sht31.begin(0x44)) { Serial.println(SHT31 not found); } // 连接WiFi和MQTT... } void loop() { // 从硬件串口读取PMS5003一帧数据并解析PM2.5 // 从s8Serial读取CO2 // 从ze8Serial读取甲醛 // 读取sht31温度湿度 // 组合成JSON发布到MQTT }需要注意一点所有传感器模块必须与ESP32共地否则串口通信会出现大量乱码。这是最简单也最容易踩的坑接线之前先确认地线连通。3.2 MQTT协议物联网数据传输的胶水层室内空气质量监测本质上就是多个节点定期上报数据这种场景非常适合MQTT。MQTT是一种轻量级的发布/订阅消息协议几十个字节的头就能承载一条消息对带宽和功耗都很友好。主控端只需要把采集到的数据组装成JSON然后发布到某个主题Topic就行。我在主题设计上采用了树形结构方便服务端订阅和分类home/air/kitchen {pm25: 35.2, co2: 860, hcho: 0.06, temp: 24.5, humidity: 52.0} home/air/bedroom {pm25: 12.8, co2: 1450, hcho: 0.03, temp: 23.1, humidity: 50.2}MQTT的QoS级别我使用的是QoS 0因为空气质量数据是周期性上报偶发丢一帧不影响整体趋势。如果要做联动控制比如CO2超标后必须关窗那建议使用QoS 1确保消息至少送达一次。3.3 云端/本地平台选型不用纠结先跑通再优化平台是整个系统的“大脑”。我的选择是在本地跑Home Assistant配合Mosquitto MQTT Broker。这样数据不出家门隐私安全断网也能用而且Home Assistant的自动化能力非常强。它自带的控制器会把MQTT主题变成本地实体我可以在仪表盘上直接看到每个节点的数据曲线。如果你不想折腾Home Assistant也可以直接用ThingsBoard或Node-RED。ThingsBoard有现成的设备管理、数据可视化界面适合做更复杂的物联网项目但对家用来说偏重。Node-RED更轻适合只做数据流转和简单告警。如果是第一次尝试我建议就在一台旧电脑或树莓派上跑Home Assistant这是上手最快、教程最丰富的路线。后期如果要支持移动网络报警再考虑接入云平台也不迟毕竟MQTT架构天然支持云桥接。4. 校准不是玄学传感器数值可信的四个关键步骤4.1 温湿度测量与交叉干扰很多人以为温湿度传感器买回来直接用就行实际上它也会受安装位置和电路散热影响。如果ESP32板载稳压器紧挨着SHT30测出来的温度会偏高2-3度。我最初就把SHT30焊在ESP32旁边结果室温显示32度实际只有27度。解决办法是把温湿度传感器通过一小段杜邦线引出远离主控板热源。甲醛传感器的交叉干扰更严重。ZE08-CH2O对温湿度变化很敏感温度每升高1度读数可能漂移3%-5%。所以我的做法是读取甲醛浓度时根据SHT30的温度和湿度做经验补偿。公式不复杂就是查厂商手册里的温度系数表做线性修正。当然这只能提升参考价值无法达到计量级精度。4.2 颗粒物传感器零点校准与一致性激光散射式颗粒物传感器的零点校准通常需要在干净空气中进行。我在室外空气污染指数小于20的清晨把节点拿到室外通风处开机运行30分钟记录PM2.5基线值。如果读数是5-10ug/m³说明传感器正常如果读数为0或长期高于20那可能是风扇卡滞或光腔积灰。多节点部署后还要注意一致性。我手头两个PMS5003在同一环境下读数相差约8%这属于正常范围。如果你需要更精确的对比可以在同一个空间里多台设备并排放置24小时然后做一个线性修正把每个节点的偏差纠正到同一基准。4.3 CO2传感器的自动基线校正ABC陷阱非色散红外CO2传感器普遍带自动基线校正ABC功能它会定期把传感器每天测到的最低CO2浓度假设为400ppm左右的新鲜空气然后自动校正。听起来很智能但有一个大坑如果某个房间长期没人开窗CO2整天都在800ppm以上ABC就会把800当作基线导致真实CO2浓度被低估。我家里卧室就是这种场景夜间CO2经常在1500ppm白天开窗通风后最低700ppm。ABC功能会把700ppm当成“新鲜空气”结果传感器显示900ppm时实际可能已经1300ppm。解决方法是关闭ABC功能或者把节点放在能定期通风的位置。SenseAir S8支持关闭ABCMH-Z19B也能通过命令关闭。4.4 综合空气质量指数IAQI的计算方法单一指标不够直观用户看着PM2.5、CO2、甲醛三四个数字会懵。我参考常见的空气质量指数计算方法把五个维度的数据归一化成一个0-200的综合指数。每个单项先按“实测值/标准限值”映射成子分再取所有子分的最大值作为综合指数。例如在我的系统里PM2.5的参考限值为35ug/m³CO2的参考限值为1000ppm甲醛的参考限值为0.08mg/m³温度舒适范围为18-28度湿度舒适范围为40%-60%单项超过限值的程度越大得分越高。这样综合指数可以直观地反映当前环境是否适合活动同时保留每个子项的原始数据供溯源。当然这个算法只是我个人项目里的定义不能替代专业空气质量评价体系但用作日常参考足够了。5. 真机实测我记录了一周的室内空气质量5.1 测试环境与设备布局我在两室一厅一厨的小户型里部署了三个节点客厅放在电视柜上离地板0.8米卧室放在床头柜上距离人睡觉的位置约0.5米厨房放在冰箱顶部避开直接烟气。每个节点都是ESP32加传感器套装数据每30秒上报一次Home Assistant自动记录。测试期间没有开空气净化器新风系统仅在发生开关事件时记录。整个测试持续一周我挑选了比较有代表性的周二的数据来做分析。5.2 数据结果解读颗粒物、CO2、甲醛的典型曲线先看卧室CO2的曲线这是最让我意外的一组数据。时间CO2 (ppm)PM2.5 (ug/m³)甲醛 (mg/m³)20:00620180.0422:00760160.0500:00980140.0502:001460120.0606:001680110.0707:001200150.06夜间关窗睡觉后两个人的呼吸让CO2在凌晨逼近1700ppm这个浓度会让人次日起来头昏脑涨。以前我并不知道卧室空气这么差因为人体对CO2升高几乎没有感知。看到这组数据后我立刻设置了一个提醒当卧室CO2超过1200ppm时自动推送通知建议开窗。再看厨房PM2.5。中午做饭炒了一盘辣椒炒肉整个厨房的PM2.5在10秒内从20冲到120ug/m³。虽然开着吸油烟机但油烟完全散尽也花了十分钟。这说明即便有抽油烟机烹饪造成的颗粒物依然很可观更印证了厨房需要单独监测的必要性。甲醛方面白天温度升高后玄关柜附近检测到0.06-0.08mg/m³的数值闷热的午后偶尔能到0.09虽然没超过0.1的参考限值但已经提醒我该多通风了。如果你的房子装修年限短甲醛数据会敏感得多。5.3 数据驱动的联动从报警到自动通风数据只是第一步真正让这套系统发挥价值的是联动。我用Home Assistant写了两个自动化逻辑卧室CO2超过1200ppm且窗户未开就推送通知到手机提醒开窗。客厅PM2.5超过50ug/m³且持续10分钟就自动打开客厅的空气净化器。后来我加了一组智能插座做联动当综合空气质量指数超过120时会自动启动风扇进行通风指数降到80以下且稳定15分钟后风扇再自动关停。这个逻辑比定时开关聪明得多——因为空气质量变化不是按固定时间表走的数据驱动才能真正解决问题。6. 踩坑实录这些细节能让你的系统少折腾一个月6.1 电源纹波把传感器数值打成了锯齿这是我最崩溃的一个坑。系统装好第二天所有数据都正常但第三天开始客厅节点的PM2.5读数在0到200之间疯狂跳变没有规律。我一度以为是传感器坏了换了个新的PMS5003还是不行。最后用示波器测量电源发现输出纹波超过200mV而PMS5003的正常工作纹波应该小于50mV。问题出在某个劣质12V电源适配器上。我替换成品牌电源适配器后数值立刻稳定。后来我不仅在电源输出端加了电容还给传感器供电加了LC滤波彻底解决了传感器之间通过电源线引发的干扰。经验就是不要为了省二十块钱买杂牌电源传感器对电源质量要求比主控高得多。6.2 I2C地址冲突与电平匹配问题我给卧室节点加了一个OLED屏幕结果SHT30读数怎么都读不到。排查后发现OLED和SHT30的默认I2C地址都是0x3C或0x44产生了冲突。解决方法是把SHT30的地址引脚改接到0x45然后在代码里指定新地址。另外ESP32是3.3V逻辑但部分传感器模块是5V供电I2C引脚如果没有做电平转换可能损坏ESP32的GPIO。我用的SHT30是3.3V版本但甲醛模块的通讯引脚是5V输出所以我做了一个简单的分压电平匹配。如果你要同时接入多个模块最好统一买3.3V逻辑的版本尽量避免5V直接怼进GPIO。6.3 Wi-Fi信号不佳导致的“幽灵离线”三个节点中厨房节点每隔几小时就离线但看路由器的连接列表这个节点明明还连着。后来发现原因很简单厨房节点距离路由器最远中间还隔着冰箱和承重墙Wi-Fi信号强度只有-75dBm触发了ESP32的掉线阈值但Wi-Fi模块并没有完全断开导致数据发不出去。我尝试过调整ESP32的Wi-Fi发射功率效果有限。最终解决方法是加了一个Mesh路由器放在走廊厨房节点的信号强度从-75dBm提升到-58dBm问题消失。如果是大面积住宅建议优先考虑Mesh组网或电力猫别指望一个路由器带全家。6.4 长时间运行的漂移与防尘维护系统连续运行一个月后颗粒物传感器读数整体偏低原因不是传感器失效而是滤网和光腔积灰。我把PMS5003拆开用气吹清理了风扇和进气道数据立刻恢复。甲醛传感器也有类似问题长时间不维护零点会偏移。所以我养成了两个习惯每个月底用气吹清洁所有传感器的进风口每个季度做一次零点校准把数据恢复到可参考的范围。如果你担心传感器寿命也可以直接从功耗和价格入手把这些模块当作耗材一年一换成本也不算高。搭建这套系统最深的体会是传感器数据永远只是参考不是计量级仪器但连续监测的趋势比单次瞬时值有价值得多。有了趋势你才会发现很多舒服其实是错觉。如果你也想做类似的系统建议别一开始就追求完美先用一个ESP32加一个PM2.5传感器跑通全链路再逐步加CO2、甲醛和其他自动化。等到你看到第一张完整的24小时空气质量曲线时你就知道为什么值得折腾了。
返回列表