上个月我把园区一个办公楼的室内环境监测项目收了尾,核心设备就是标题里这组“以太网温湿度气体多参量传感器”。说得直白点,它是一个能同时采集温度、湿度、二氧化碳、TVOC,并且直接走网线上报数据的终端节点;如果把这栋楼比作一个人,楼宇自控平台是大脑,网线是神经,这些传感器就是分布在各处的神经末梢。这套系统上线之后,物业不再靠人工拿手持表去一层层测,运维人员打开后台就能看到每一个房间的实时环境曲线。写这篇东西,不是要讲一个多么前沿的概念,而是把我从选型、画板、调协议、现场装点位上摸出来的一套完整做法整理出来,给正在做楼宇环控、实验室监控或者机房环境监测的朋友一个可直接抄的参考。
1. 项目缘起:一栋楼最不缺的是数据,最缺的是靠谱的数据
1.1 真实痛点:空调开了 24 小时,投诉却从没停过
这个项目来自一个十二层的园区办公楼,痛点非常典型:不同朝向的办公室温差能到 4 到 5 摄氏度,朝阳面夏天闷热,背阴面冬天阴冷;会议室下午二氧化碳浓度经常破 1500ppm,参会的人昏昏欲睡;个别房间偶尔有装修残留的异味,但物业查不到源头。原有的楼宇自控系统只采集了新风机组和空调箱的供回水温度,至于每个房间到底什么环境,完全靠人工巡检。业主的诉求其实很朴素:不能只在机房看设备温度,必须知道人所在的空间是什么状态。这正是“环境感知神经”要解决的问题。
这类需求听起来简单,真正落地却卡在设备形态上。如果每个房间装一个温度计、一个湿度计、再单独装一个二氧化碳检测仪,线缆、安装、维护三座大山立刻压过来;如果只装单一的温湿度传感器,业主又抱怨闻不到“味道”。所以“多参量”这个方向几乎是必然选择。一个设备同时测温湿度、二氧化碳和 TVOC,用一根网线既通数据又供电,省掉了传感器箱、串口服务器、小电源适配器和一堆乱七八糟的线缆。节点数量一旦超过五十个,这种省法就是决定项目利润和后期维护量的关键。
1.2 方案选型:为什么我最终选了以太网而不是 RS485 或无线
同行看到我的方案,第一反应都是问:这种传感器用 RS485 不就行了,干嘛非要碰以太网?我确实也想过 RS485。从成本看,RS485 芯片便宜,布线距离长,带 Modbus 协议也很成熟。但它有两个硬伤:第一,楼内跨楼层走线必须总线串联,一旦某一段短路,后面整串设备全部离线,排障能把人逼疯;第二,RS485 本质上需要一个串口服务器或者采集器去转成 IP 协议,增加了一层故障点,后期替换设备还要去改地址、改波特率。对于动辄几十上百个点的建筑空间,RS485 的“一根总线拖到底”反而成了维护噩梦。
无线方案我也测过 LoRa 和 Zigbee,安装在灵活性上确实占优,但在这类钢筋混凝土结构的楼里,无线信号穿墙衰减非常明显,金属吊顶、电梯井、强弱电间都会让数据一跳再跳。更关键的是,楼宇环境监测的数据最终要交给上层平台做分析和告警,主流的楼宇自控系统、能耗平台、数字孪生平台对 IP 网络的接入远比串口友好。以太网方案相当于让每个传感器直接获得一个 IP 地址,平台侧用 Modbus TCP 轮询,上层用 MQTT 订阅推送,中间不需要任何协议转换网关。我把几种方案的成本、可靠性和维护难度拉了个表:
| 对比项 | RS485 总线 | LoRa/Zigbee 无线 | 以太网(本项目采用) |
|---|---|---|---|
| 传输距离 | 1200m 内,但受总线拓扑限制 | 空旷距离可观,楼内衰减大 | 100m 以内网线直连,楼层内可走交换机堆叠 |
| 部署复杂度 | 需串联布线,节点越多风险越大 | 无需布线,但网关和电池/供电麻烦 | 星型拓扑,单点故障不影响全局 |
| 响应速度 | 半双工轮询,节点多时延迟高 | 上行延迟不稳定 | 全双工 TCP,毫秒级响应 |
| 与平台对接 | 必须加串口服务器 | 需要专用网关 | 直接 TCP/IP,天然友好 |
| 供电方式 | 需额外布供电线或带 RS485 的电源线 | 电池或本地电源 | PoE 或网线旁路供电 |
| 维护难度 | 总线故障排查困难 | 电池更换、网关故障常见 | 单点排查,网口状态透明 |
这个表的结论很明确:以太网方案在建筑侧的综合维护成本其实是最低的。尤其是 PoE 供电的引入,让传感器真正做到“一根网线全干完”,施工队只需要敷设标准网线,不用再考虑现场有没有 220V 插座,也不用担心强电干扰传感器信号。后面我会重点讲 PoE 供电的板级设计和现场预算,这是很多人容易翻车的地方。
2. 硬件方案:传感器怎么选、主控怎么搭、PCB 怎么画
2.1 温湿度与气体传感器选型:先搞懂测量原理再下单
多参量传感器的硬件核心不是主控,而是传感器探头选型。温湿度这块,早期很多项目喜欢用 DHT11、DHT22,便宜是便宜,但精度、一致性和长期稳定性都一般。DHT22 标称精度 ±0.5°C,实际在批量装配中经常差到 1°C 以上,而且潮湿环境下容易失效。我这次选的是 SHT30,I2C 接口,精度可以做到 ±0.3°C 和 ±2%RH 左右,贴片封装,体积小,适合放在探头的末端。再往上还有 SHT40、SHT45,但普通楼宇监测用 SHT30 已经完全够用,性价比很高。
二氧化碳是“气体多参量”里最不能省的一项。市面上二氧化碳传感器主要有两类:电化学和红外(NDIR)。电化学模块便宜,但寿命短、容易漂移,不适合做建筑长期监测。我选的是 MH-Z19 这类 NDIR 二氧化碳模块,原理是让红外光穿过气室,根据二氧化碳分子对特定波长的吸收程度计算浓度。它寿命更长,能到五年以上,量程 0 到 5000ppm,精度大约 ±50ppm 再加 5% 读数误差,对室内空气质量判断完全够用。模块自带 UART 和 PWM 输出,接主控时可以用 UART,省事。
另一路气体参数我选了 SGP30,用来测 TVOC 和 eCO2。SGP30 属于金属氧化物半导体传感器,内部有一个加热元件,污染气体接触半导体表面后会造成电导率变化,通过算法折算成总挥发性有机物浓度。这类传感器有个特点:绝对值别太较真,更适合看趋势和突发事件。比如有人喷了空气清新剂、装修散味、午餐时间茶水间气味飙升,SGP30 都能很快反映出来。用它去“精确测量甲醛浓度”不现实,但楼宇场景里我们需要的是“有没有异味、空气质量是否恶化”的指示信号,这就够了。如果项目有特殊需求,比如医院或实验室要求甲醛,也可以在这路接口上替换为电化学甲醛模块,代价是定期标定和维护。
2.2 主控、PHY 与 PoE 供电:一个工程板级的组合方案
主控我选了 STM32F407VET6。原因很直接:这颗芯片内置以太网 MAC,配合一颗外置 PHY 就能跑 TCP/IP,不需要外挂复杂的网络协议栈芯片。F407 的主频 168MHz,内部 Flash 和 RAM 足够跑 LwIP 协议栈,同时还能处理三个传感器的数据采样、滤波和状态管理,性能冗余很大。板级网络方案是 STM32 的 RMII 接口接了一颗 LAN8720A 的 PHY,再通过内置网络变压器的 RJ45 座(比如 HR911105A)出线。需要特别注意,RJ45 座一定要带网络隔离变压器,这不是省成本的地方,雷击浪涌、地环路和静电都可能通过网线传导进板子,没有变压器隔离,烧一片 PHY 不是开玩笑。
供电方面,如果现场有条件用 PoE 交换机,我会在板上预留 PoE PD 模块的位置,比如 MP8007 或 TPS23753。PoE 供电后进入板内 DC-DC,再生成多路电压给主控、传感器和以太网 PHY。传感器和气体模块的供电纹波要控制好,特别是 SGP30 的加热器对电源质量比较敏感,我用了一路单独的 LDO 给模拟传感器供电,电源纹波控制在 50mV 以内。如果不走 PoE,则预留 9 到 36V 宽压 DC 输入,这样现场可以用原有的 24V 电源总线,也方便后期改造。PoE 模式的典型功率在 3W 左右,一个以太网交换机端口带动十个这样的传感器完全没问题。
2.3 结构设计:别让传感器“自己骗自己”
这个部分踩的坑最值钱。气体传感器和温湿度传感器对环境温度非常敏感,而以太网 PHY、DC-DC 电源和主控都是发热源。如果 SGP30 紧挨着 LAN8720A,板子工作半小时后局部温度能比环境温度高 5°C 以上,直接影响 SHT30 的湿度读数,也会让 SGP30 的基线产生严重偏移。我第一版 PCB 就是这么翻车的,温度读数永远比实际高两度,后来热成像一照,问题一目了然。
我的调整思路是:把温湿度传感器放到探头的末端,尽量远离 PCB 上的功率器件;SGP30 放在板子边缘,开散热通风孔,让自然对流把热量带走;MH-Z19 因为体积大,单独做气室,四周不要紧贴金属外壳,避免外壳导热造成测量腔体温度畸变。结构上还要留校准孔,这样工厂标定和现场零点校准时不需要拆壳。防护等级方面,普通办公室做到 IP30 足够,如果用在厨房或者潮湿环境,传感器探头要有防尘罩和防冷凝设计。
3. 固件与协议:把采集值变成别人能用的数据
3.1 网络协议栈与通信模式:LwIP 是首选,但别裸写 TCP
STM32F407 跑以太网,我首选的协议栈是 LwIP。LwIP 的开源生态非常成熟,支持 TCP、UDP、DHCP、DNS,代码体积也小,适合在嵌入式 MCU 上跑。它的接口模式有两类:一类是 raw/callback API,性能好但代码写起来很绕;另一类是 netconn/socket API,写起来像普通 socket 编程,可读性高。考虑到后续要同时维护 Modbus TCP 和 MQTT 两条链路,我用的是 netconn API,牺牲一点点性能换维护效率。
通信模式上,我让设备同时扮演两个角色:一是作为 TCP 服务器,在 502 端口监听 Modbus TCP 请求,方便楼宇自控系统用标准的 Modbus 轮询读取数据;二是作为 MQTT 客户端,主动连接后台的 MQTT Broker,把实时数据推送给上层平台。这两个链路可以并存,Modbus TCP 是“被拉”,MQTT 是“主动推”。很多项目只做 Modbus TCP,结果平台侧全部靠轮询,数据刷新不够及时;只做 MQTT 又不好接老旧的 BA 系统。双通道设计可以兼容新旧平台,实际交付时业主非常认可。
3.2 寄存器表与 JSON 数据帧设计:数据格式必须一开始就定死
协议设计最关键的是数据帧,对楼宇这个场景来说,字段必须清晰,带时间戳,还要有数据质量标志。Modbus TCP 部分,我把关键数据放在保持寄存器里,用的是标准线圈和寄存器语义,方便用 Modbus Poll 之类的工具直接调试。寄存器地址表大致是这样的:
| 寄存器地址 | 内容 | 数据类型 | 数据说明 |
|---|---|---|---|
| 0x0000 | 设备类型 | 只读 U16 | 固定值 0x0018,表示多参量环境传感器 |
| 0x0001 | 固件版本 | 只读 U16 | 例如 0x0103 表示 V1.0.3 |
| 0x0010 | 温度 | 只读 Int16 | 单位 0.1°C,230 表示 23.0°C |
| 0x0011 | 相对湿度 | 只读 U16 | 单位 0.1%RH,462 表示 46.2%RH |
| 0x0012 | 二氧化碳浓度 | 只读 U16 | 单位 ppm |
| 0x0013 | TVOC 浓度 | 只读 U16 | 单位 ppb |
| 0x0014 | 状态字 | 只读 U16 | bit0 温湿度正常,bit1 CO2 正常,bit2 TVOC 正常,bit3 数据失效 |
| 0x0020 | 采样周期 | 读写 U16 | 单位秒,默认 30,范围 10 到 600 |
MQTT 的推送报文我用 JSON 格式,按行发送,便于数字孪生平台直接用 JSON 解析。一个典型的报文长这样:
{"device_id":"ACU-03-121","ts":"2025-03-18T10:24:31+08:00","temp":23.4,"rh":46.2,"co2":612,"tvoc":156,"status":1}注意这里status是一个整型状态标志位,不是直接把寄存器拆开,而是固件内部算好之后打包,客户端拿到不需要做位运算。MQTT 的 topic 我按项目编号和楼层组织,比如building/floor03/room121/acusensor,设备只往自己的 topic 发数据,推荐用 QoS 1,确保不丢包。如果上层平台需要历史数据,就直接订阅 topic 写时序数据库;如果需要指令下发,比如改采样周期,再用一个.../cmd的 topic 回传。
3.3 断线重连、看门狗与本地缓存:网线掉了也不能丢数据
现场最容易出问题的不是传感器,而是网络。固件里我做了三重保险。第一重是断线检测:TCP 长时间没有收到对端 ACK,就主动断开重连;MQTT 断线后按指数退避算法重连,第一次等 5 秒、第二次 10 秒、第三次 20 秒,最大间隔 5 分钟,防止所有设备同时上线把 Broker 打爆。第二重是独立看门狗:除了 MCU 的 IWDG,我还在 App 层维护一个“网络心跳计数器”,如果网络任务超过 60 秒没有成功收发任何报文,看门狗强制复位系统。这个设计帮我解决过一次 TCP 协议栈卡死的问题,不加的话设备可能“假活”好几天。
第三重是本地缓存。每 30 秒一条数据,如果网络断开,数据先写入外部 SPI Flash 的一块环形缓冲区,能存 24 小时的量。网络恢复后,设备先把缓存的旧数据按时间顺序补传到平台,再继续上报实时数据。为了避免 Flash 频繁擦写造成寿命损耗,我在固件里加了磨损均衡逻辑,并且设置了缓存上传成功后的擦除策略。这个功能在改造项目里非常重要,因为甲方网络经常因为割接、重启、弱电间跳闸而不稳定,有了缓存,至少数据不丢。
4. 现场部署与调参:完整走一遍项目流程
4.1 点位选择和安装高度:一错毁所有
设备做好了,如果点位选错,数据再准也没有意义。办公室的温湿度传感器高度我一般装在 1.2 到 1.5 米,大概是人坐姿呼吸带的高度。千万不能装在空调出风口正下方、窗边阳光直射处、或者暖气散热片附近,否则测出来的温度不是房间温度,而是设备周围那一点局部“小气候”。气体传感器的安装位置还要考虑空气流动,不能塞在文件柜后面死角和吊顶里,尤其是二氧化碳传感器,它靠空气扩散进气,如果周围被遮挡,响应会慢很多。
一些特殊区域的点位需要单独加参数:地下车库和机房里,我会在气体接口上追加一氧化碳传感器,车位密度大的地方 CO 数据很有价值;实验室和化学品存储区则适合换装可燃气体探测器,并把报警阈值单独调低。点位编号必须和设备 ID 严格对应,我每台设备出厂时就把设备ID、MAC地址、楼层房间号烧进一个二维码标签,贴在外壳上,现场施工人员用手机扫一下就能把设备装到指定位置。这个细节在大项目中能省掉大量后期排障时间。
4.2 网络规划与 PoE 预算:把隐患掐在施工前
以太网传感器对网络是“即插即用”,但前提是网络规划做在前面。我的做法是单独划一个 IoT VLAN,比如10.24.3.0/24,只允许传感器和平台之间通信,禁止传感器直接跨 VLAN 访问办公网络。平台服务器通过防火墙白名单访问 502 端口和 MQTT 端口。这里一定要和甲方的网络管理员提前对齐,特别是 VLAN、DHCP 地址段和端口开放策略。我吃过一次亏:设备出厂默认 DHCP,现场网络没有配置地址保留,结果传感器 IP 频繁漂移,平台侧一会儿连不上这个一会儿连不上那个。
PoE 预算也要算准。每个传感器的功耗大概 3W,但如果后期加了主动式气泵或电化学传感器,功耗会到 4.5W 左右。交换机 PoE 端口的总功率要留 25% 余量,比如一台 24 口 PoE 交换机预算 400W,实际接满 24 台设备按每台 5W 算只要 120W,看似够,但交换机本身的 PoE 总功率和端口功率是两码事,端口功率预算不足会导致设备启动瞬间反复掉电。方案沟通时我给甲方写了一个硬指标:传感器供电使用 802.3af 标准 PoE,端口最大功率不低于 15W,这样即使后期升级带加热除湿的传感器也不需要重换交换机。
4.3 标定与零点校准:数据准确性的最后一道关
出厂时,温湿度传感器本身有厂商校准,但气体传感器尤其是 SGP30 不能直接“开箱即用”。我建议每一批设备在通电老化 48 小时后,在干净的空气环境里做一次零点校准。SGP30 内部有基线算法,首次上电的 12 小时数据波动很正常,不要让施工人员拿这个时间去试报警阈值。二氧化碳传感器的零点校准也很关键。MH-Z19 支持零点标定功能,做法是在户外空气流通的地方短接校准引脚,让模块把 400ppm 作为基线。这一步不能省,尤其是长期在室内运行的模块,基线漂移会导致读数越来越离谱。
现场校准还有一个小技巧:多参量传感器要放在同一个环境里做对比测试,而不是拿着手持仪表去挨个“敲”数值。手持仪表和传感器的响应时间不一样,直接对比会让人觉得数据全是错的。我通常是让设备稳定运行 30 分钟,再用手持仪表在设备旁边测 5 分钟取平均,误差在温湿度 ±0.5°C / ±5%RH、CO2 ±100ppm 以内就认为通过。TVOC 不做绝对精度判断,只做趋势一致性判断。
5. 常见问题与排查技巧实录
5.1 现场故障速查表:遇到问题先看现象再动设备
设备上线后,现场排障不可避免。我习惯把所有常遇到的问题整理成速查表,发给现场运维人员,这样可以减少大量无效沟通。以下是这个项目里最常碰到的几类问题:
| 现象 | 可能原因 | 处理步骤 |
|---|---|---|
| 温度读数明显偏高 | 传感器离发热元件太近或被阳光直射 | 检查安装位置,改善通风,必要时重新装 |
| 湿度长期显示 99% | 探头进水或冷凝 | 取出传感器,放在干燥环境恢复,检查外壳密封 |
| CO2 数值偏高且不回零 | 传感器长期未做基线校准 | 户外空气下做零点标定,若仍漂移则返厂 |
| TVOC 数值乱跳 | SGP30 预热不足或酒精等干扰 | 老化 48 小时,加数据滤波,不要追求绝对值 |
| 设备网口灯亮但 ping 不通 | IP 冲突或交换机端口 VLAN 不对 | 检查 MAC 与 DHCP 保留,核对交换机 access/trunk 配置 |
| Modbus TCP 502 端口超时 | 防火墙阻断或平台侧请求地址写错 | 检查白名单,用 Modbus Poll 联调 |
| 设备反复重启 | PoE 功率不足或电源纹波大 | 更换 802.3af 端口,检查 DC-DC 输出 |
| 数据断续上报 | 网线压接不良或 DHCP 租期太短 | 重新做水晶头,检查 DHCP lease time |
这里我再多说一句:现场很多“传感器坏了”的问题,最后都出在网线和水晶头上。很多人觉得六类线随便压压就行,但 PoE 供电对线对的接触电阻很敏感,水晶头接触不良造成供电不稳,设备会表现成随机重启。排查这类问题时,先换一根成品网线试一下,最快。
5.2 排查工具:Modbus Poll + Wireshark + tcpdump
设备联调的时候,我的三件套是 Modbus Poll、Wireshark,还有 Linux 服务器上的 tcpdump。Modbus Poll 用来直接读寄存器,验证地址映射和字节序。Wireshark 抓包主要是看 TCP 握手是否正常、Modbus 报文的功能码和数据长度对不对。抓包过滤器可以写成:
tcp.port == 502在服务器端如果不想开图形界面,tcpdump 更轻量:
tcpdump -i eth0 port 502 -n -XX还有一次 MQTT 上报延迟的问题,就是用 tcpdump 抓出设备重连频率异常高,才发现 MQTT Broker 的 keepalive 配置和固件里的心跳间隔不匹配。这种问题看平台日志看不出来,抓包一眼就清楚。
5.3 我踩过的几个坑
第一个坑是 SGP30 离 PoE 电源太近。第一版板子温度读数偏高两度,后来把 SGP30 挪到板子边缘,温度偏差就消了。所以画板阶段一定要做热仿真或者直接用热成像仪验证,别等装到现场再去贴隔热棉。第二个坑是 DHCP 地址保留没做,设备 IP 漂移导致平台数据断档,后来把每台设备的 IP 和 MAC 绑定才解决。第三个坑是 MQTT 重连没有退避策略,现场五十台设备同时掉线重连,Broker 直接被连接风暴打挂。第四个坑是部署完没有立刻做二氧化碳零点校准,第一周数据整体偏高近 100ppm,业主差点以为传感器质量不行。
如果你也准备做类似项目,我最大的建议是:不要先急着做平台界面,先把单台设备的网络、数据、标定闭环打通,再批量复制。环境监测项目表面上是硬件问题,本质上是系统可靠性问题。一块板子能跑通不算本事,五十块板子在弱电间里持续稳定跑三个月,才叫真本事。后面我打算把 PM2.5、光照度和噪音也做进这套节点里,顺便把设备固件升级做成远程 OTA,目前这套东西已经在实验室跑通了,等我再沉淀一段时间,找机会把远程升级和边缘校准的部分单独写一篇。