ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于W55MH32-ADK的室内外气象监测系统:传感器选型、数据链路与低功耗实践

基于W55MH32-ADK的室内外气象监测系统:传感器选型、数据链路与低功耗实践 去年冬天小区物业那块LED屏上的温度计成功把我骗了一整个星期——屏幕显示7℃外面草地上已经结霜每天出门穿多厚全靠体感在赌。后来实在忍不了我决定自己搭一套室内/室外气象监测系统室内机放客厅室外机挂阳台外墙温度、湿度、气压、风速、雨量、光照六个数据全部采回来既能本地显示也能通过 MQTT 上报到云端自动画曲线。整套系统的主控选了一块 32 位开发板——W55MH32-ADK。这篇文章把整个实现过程拆开讲清楚。既适合正在选主控板的人参考也适合手头有类似开发板、想搭环境监测却不知道从哪下手的新手。我会把传感器接线、滤波标定、通信协议、低功耗设计以及调试中踩过的坑都记录下来能直接复制的直接复制能避开的坑尽量帮你避开。1. 为什么选 W55MH32-ADK 做中枢选型对比与角色分工1.1 树莓派被淘汰嵌入式方案才是气象站的常态刚开始我也动过直接买成品智能气象站的念头搜了一圈发现要么数据封闭不开放要么传感器精度差而且你只能被动看它家APP里的图。自己动手做最关键的一步是选主控。我第一批对比方案里就有树莓派 Zero 2W。它的优点是 Python 生态好、写图表方便但缺点同样明显Linux 启动慢、掉电容易损坏 SD 卡、整板功耗按瓦算放室外长期通电心里没底。工业气象站没人用树莓派做传感器节点原因不是性能不够而是稳定性和功耗都撑不住。ESP32 也考虑过。它便宜、社区资料海量、自带 Wi-Fi 和蓝牙缺点是想要多串口同时挂传感器、再开 Web Server 和 MQTT 客户端时可用外设和内存比较紧张。做一个单节点传感器它很合适做室内外多节点汇聚网关就有点憋屈。1.2 W55MH32-ADK 的接口完整度恰好卡在需求上W55MH32-ADK 是围绕 W55MH32 主控的一套评估/开发套件板载调试接口和各种常用外设接口。我选择它的理由很朴素这块板子的接口完整度恰好卡在我的需求上。做气象站这种项目主控要同时面对三类东西传感器需要 I2C/SPI/ADC/定时器输入捕获室内外通信需要至少两个串口一个跑 RS485一个跑无线模块对外上网还需要网络或串口转以太网/无线模组。很多板子能干活但要么串口不够用要么得自己飞线改板。W55MH32-ADK 把这些外设接口集中在一块评估板上面包板和杜邦线就能完成初期原型验证不用一上来就画 PCB这一点对快速试错帮助很大。另外它作为 32 位 MCU处理速度和处理气象数据这种低频、低数据量的任务绰绰有余。很多人一上来就想着上 RTOS、上大内存实际上气象站每秒产生几十个字节整个固件跑裸机加几个中断就能稳稳当当。1.3 它在系统里的三层角色采集、汇聚、网关在整套系统里W55MH32-ADK 承担了三个角色。第一是采集层。室内机的温湿度、气压、光照直接挂在板子的 I2C 总线上室外机的风速和雨量通过脉冲计数器接入定时器输入捕获引脚风向传感器用 ADC 读取。所有传感器都由这颗主控周期轮询不需要额外的小单片机。第二是汇聚层。室外机采集的数据通过 RS485 或 LoRa 传到室内机室内机把六类数据统一成 JSON 格式再转发给显示和上云模块。这个中间层非常关键它让整套系统不依赖某个传感器的 I2C 地址或某种通信协议换传感器时只需要改一小段解析代码。第三是网关层。板子本地挂了一块 SPI 屏幕做实时显示同时自己跑一个极简 HTTP 服务局域网内任何设备都能访问/api/weather拿到 JSON 数据。此外还接了一个 MQTT 客户端把数据推送到 Broker云端画曲线和手机查看都走这条路。这样分层之后整个项目从一块板子连一堆传感器变成三层各司其职调试起来思路非常清晰。2. 室内外分离的采集架构传感器配置与接线2.1 室内机和室外机的职责边界很多 DIY 气象站项目最后做成一锅粥问题出在职责边界没划清楚。室内机和室外机不是简单地在不同位置放两组传感器而是各自有明确分工。室外机负责测得环境真实值包括温度、湿度、风速、风向、雨量、气压。它的环境最恶劣要面对太阳辐射、雨水、凝露、电线感应雷和各种小飞虫所以原则是传感器尽可能少通信尽可能省电不跑 LCD不跑 Web Server只把数据发给室内机。室内机负责展示和联网。它把室内温度和室外数据合并成统一格式驱动本地屏幕、提供 HTTP 接口、推送 MQTT。室内机对体积和功耗不敏感可以插电运行唯一要求是稳定不死机。这样划分后室外机做到极简低功耗室内机则可以做得很豪华。我的实际做法是室外机有一个塑料防水盒里面只放主控、传感器、RS485 收发器或 LoRa 模块以及电源管理部分室内机放在客厅电视柜上屏幕朝外后面拖一根网线或 USB 电源线完全本地供电。2.2 温湿度传感器优先 I2C避开单总线的坑温湿度传感器我最推荐 SHT30 或 BME280原因就一条它们走 I2C稳定性和精度都远好于 DHT11/DHT22 这类单总线传感器。DHT22 虽然是新手最爱但实际工程里很容易出问题。单总线时序要求非常严格主控稍被中断打扰一次就可能读到全 0xFF所以必须用 GPIO 模拟时序并且关闭中断这在复杂固件里很别扭。SHT30 就简单得多写两个字节的 I2C 命令然后等一小段时间再读结果出错时还能通过 CRC 校验判断数据是否有效。接线方面有个容易被忽略的点传感器的 VCC 和 GND 一定要先接再接 SCL/SDA不然热插拔可能把芯片搞死。另外I2C 总线上挂多个传感器时每个传感器的地址要靠 ADDR 引脚区分比如 SHT30 常用地址是 0x44 和 0x45BME280 是 0x76 和 0x77。我把室内和室外各放一个 SHT30地址错开用一根 I2C 总线还分不出来后来干脆让室外机独立跑室内 SHT30 挂在主控总线上省去了一堆地址冲突问题。2.3 风速、风向与雨量脉冲信号接法温湿度这类数字传感器接线简单真正考验硬件的是风速、风向和雨量这类机械传感器。我用的是常见的三杯式风速计内部霍尔器件或干簧管输出脉冲信号。风速和脉冲频率成正比不同型号系数差别很大常见风速计大概是每转输出一个脉冲风速约风速(m/s) 频率(Hz) × 0.75左右具体参数要查型号或自己实测。接线时信号线要加上拉电阻因为干簧管和霍尔输出大多是开漏不加上拉的话信号全是毛刺。雨量桶更直接——翻斗式雨量计每翻斗一次输出一个脉冲一般代表 0.2mm 降雨量。它的坑在于翻斗动作瞬间会产生抖动一个斗可能输出两三个脉冲必须在固件里做消抖处理连续检测到两个沿的时间间隔小于某个阈值就只算一次。风速计和雨量计的输出都接在主控的定时器捕获引脚上用输入捕获模式统计脉冲数和脉冲间隔这样 CPU 不用一直瞪着电平变化。风向传感器我简化成 8 方向磁簧开关8 根线接 GPIO哪个方向导通就读哪个值如果换成分压式风向标直接接 ADC 即可。2.4 气压、光照等扩展传感器的取舍气象站除了温湿度气压和光照也能带来不少信息。气压我用 BME280顺便还能把湿度一起读了一颗搞定三个参数。光照用 BH1750I2C 直接读 Lux 值非常省事放室内和放室外含义不同室外光照反映太阳辐射强度室内光照更多是判断窗帘要不要拉。这里要提醒一句传感器不是越多越好。每增加一个传感器就多一路供电、一份接线、一段调试时间还可能多一个故障点。我对扩展传感器的取舍原则是优先选 I2C 接口、3.3V 供电的设备因为这样可以共用电源域和总线电路和固件复杂度最低。模拟输出的传感器如果非用不可一定要确认主控 ADC 的输入范围和传感器输出范围匹配不然又要加分压电阻又要算偏移很麻烦。3. 模拟量采集与滤波ADC 出来的数据为什么不能直接用3.1 分压电路与参考电压的坑风向标、光电池、部分风速计模块输出的是模拟电压ADC 采集前要先过一遍脑子不能直接把线怼上去。第一个坑是参考电压。很多开发板的 3.3V 基准电压精度并不高如果板子供电来自 USB 口或开关电源Vref 可能有 2% 以上的偏差直接导致 ADC 读数系统性偏移。我的做法是先测一下实际 Vref比如用 1.024V 的外部基准模块校准或者直接用万用表量 3.3V 引脚电压把真实值写进固件做比例换算。第二个坑是分压电阻。有些传感器输出范围超过 MCU 的 ADC 最大量程比如 0~5V 的输出直接进 0~3.3V 的 ADC 必然削顶。用两只电阻分压时要注意等效输出阻抗阻值太大比如 100kΩ 对 100kΩ会导致 ADC 采样保持电容充不进电读数漂得离谱。我一般控制在 10kΩ 级别必要时加一级电压跟随器运放隔离。第三个坑是防护。室外模拟传感器线路很长信号线上难免感应雷电共模电压虽然不会打雷直接命中但夏季雷雨天气读数偶尔会跳变。我的临时做法是在 ADC 引脚前并联一个小电容比如 0.1uF和两个对地的保护二极管至少能滤掉大部分毛刺。3.2 平均滤波与窗口选择传感器原始数据即便接对了读数也往往是抖的尤其是温度、湿度这种缓慢变化的量。ADC 采一次 0.34V下一次 0.36V直接显示温度就变成 25.1℃、25.7℃ 来回跳看着特别不专业。我的滤波策略是中值滤波 滑动平均两段式先对一组 5 个原始采样取中值去掉异常尖刺再把中值结果放入一个长度为 10~20 的滑动窗口求平均用来展示和上报。滤波窗口长度需要根据量测对象调。温度变化很慢窗口拉长到 20 也没问题曲线会很顺滑雨量脉冲则完全不能滤波要的是实时计数风速介于两者之间窗口取 5~10 秒平均风速比瞬时风速更有参考价值。有一个细节值得注意气象数据普遍按 1 分钟或 10 分钟上报一次滑动窗口长度千万别拉到 60 秒以上否则你看到的是几十秒前的平均值极端天气反应不过来。3.3 标定用一个温度计做差值补偿的经验传感器出厂精度再高经过分压电阻、参考电压、接线电阻几层损耗后读数也会出现固定偏差。标定这件事没那么玄乎我的方法是家里准备好一支已经校准过的工业温度计把传感器和它放在同一个环境里稳定 2 小时后读取差值然后在固件里加一个线性补偿真实值 读数 × 斜率 偏移。湿度标定难度高一些可以用饱和盐溶液做参考比如氯化钠饱和溶液在 25℃ 时的相对湿度约 75.3%把传感器放在密封罐里隔 12 小时再看偏差。气压传感器一般不需要手动标定BME280 出厂校准系数都烧在芯片内部读出来的已经是补偿后的值。风速标定同样可以自己来用电风扇开到固定档位用手持风速计在旁边测记录风速和脉冲频率的对应关系多点拟合出系数。这一步不做的话风速计读出来的值只能算趋势不能算准确风速。4. 数据链路设计串口、RS485 与无线方案4.1 有线 RS485 方案稳定但施工麻烦室内机和室外机的距离通常不远从几米到几十米如果布线方便我首选 RS485 而不是普通 TTL 串口。原因很简单TTL 电平是 3.3V/0V线一长就容易衰减和受干扰RS485 用差分信号两根绞线可以跑几百米抗干扰能力强很多。RS485 接线只有两根线A 和 B半双工通信。连接时要注意两端各接一个 120Ω 终端电阻否则高速收发会出现反射实测波形会像台阶一样。用主从轮询模式最简单室内机为主机定时发送查询指令室外机作为从机收到后立刻回复当前数据。方向切换有一个容易踩的坑RS485 收发器在发送时要控制 DE/RE 引脚拉到发送态发完必须马上切回接收态否则总线上会一直占着不放。我一开始用延时 10ms 再切换短距离没问题后来线延长到几十米就需要改成发完一帧、等发送完成中断、再切接收否则最后几个字节会被自己的回环数据干扰。4.2 无线方案LoRa 是比 WiFi 更合适的选择如果不想拉线无线方案里我推荐 LoRa而不是 WiFi。室外机如果内置 WiFi 模块单次连接功耗高断网后重连逻辑又繁琐放室外电池供电完全扛不住。LoRa 的优势是低功耗、远距离、穿墙能力强433MHz 模块在普通住宅环境穿三四堵墙还能稳定通信单次发射耗电大约 120mA 只持续零点几秒。LoRa 模块配置时要注意频率、扩频因子、带宽三个参数。我用的是 433MHz 频段扩频因子 SF7带宽 125kHz实测室内外相距 20 米左右延迟很低。不建议在市区直接调 SF12 追求极限距离发射时间太长反而更容易被同频干扰。室外机平时让 LoRa 模块进入休眠每 10 分钟唤醒一次发数据发完立刻睡这样模块耗电几乎可以忽略。另外LoRa 和数据帧格式要提前想清楚它带宽很窄不适合一把 JSON 直接怼上去最好用紧凑二进制帧传输到室内机再解析展示。4.3 数据帧格式简单但够用无论 RS485 还是 LoRa室内外通信的帧格式我统一设计成如下结构帧头(0xAA 0x55) 数据长度 类型 数据 CRC16类型字段区分帧是风速数据环境数据还是心跳数据区按固定字节序排列。这样做的好处是解析端不用猜收到帧先查帧头、再验 CRC数据出错直接丢弃不会把坏数据当真实数据上报。温度传递我统一用放大 10 倍的整数比如 25.3℃ 传 253客户端再缩小回去。气压传整数 Pa光照传整数 Lux。这样固件里不用浮点运算内存占用更低串口调起来也更直观。数据帧里别忘了带序列号接收端可以判断是否丢帧丢帧太多就该提醒检查通信链路。5. 数据出口本地显示、Web 页面与 MQTT 上云5.1 LCD 本地显示室内机主控直接挂了一片 SPI 接口的 LCD不需要跑触摸只做展示。刷屏逻辑非常简单每秒重新刷新一次所有数值温度保留一位小数气压和气概取整风速保留一位小数。刷新 LCD 有个常见坑不要在传感器读取和数据处理的中断里做绘图SPI 刷屏很占时间容易把中断逻辑拖垮。正确做法是主循环里标记一个display_dirty标志等传感器数据都更新完再一次性刷新屏幕。屏幕放在室内机本身就是插电状态不需要考虑低功耗把刷新率从每秒 1 次降到每 2 秒 1 次肉眼几乎无区别还能降低发热。5.2 板端内置 Web Server本地屏幕只是入口真正方便的是在局域网里用手机随时看。我在 W55MH32-ADK 上跑了一个极简 HTTP 服务只做两件事提供静态页面和返回 JSON 接口。/api/weather返回当前所有数据{ indoor_temp: 25.3, indoor_hum: 55, outdoor_temp: 12.8, outdoor_hum: 68, pressure: 101325, wind_speed: 3.2, wind_dir: 135, rain: 0.2, lux: 3200, timestamp: 1734567890 }浏览器里打开同一 IP 的/路径就是一张自动刷新数据的简单 HTML 页面。做这一步的关键是 HTTP 解析不要太复杂固件里只处理 GET 请求解析 URL 路径对未知路径统一返回 404。千万别在一开始就给板子加 HTTP 长连接、分块传输这些功能内存和复杂度都会失控。5.3 MQTT 上云与按主题拆数据本地 Web 够用了但要做历史曲线还是得上云。我的做法是让室内机主控定时把 JSON 数据 publish 到 MQTT Broker按主题拆分weather/indoor/temperatureweather/outdoor/temperatureweather/outdoor/windweather/outdoor/rain每条主题的 payload 就是对应数值云端订阅这些主题后写入时序数据库再用 Grafana 或者 Home Assistant 画面板。这样拆主题的好处是以后想只显示温度曲线不用解析整个 JSON。MQTT 客户端在 32 位 MCU 上跑需要注意重连逻辑。家里路由器重启、宽带断线TCP 连接会被静默切掉客户端容易一直以为还连着。我设置了每 60 秒主动 ping 一次 Broker连续三次 ping 失败就断开重连实测稳定性提升非常明显。6. 功耗核算、太阳能供电与外壳防水的工程细节6.1 室外机低功耗模式与唤醒节奏室外机如果拉网线供电那所有功耗优化都可以跳过但想放阳台外、屋檐下甚至院子里就必须做电池供电。我用的是 3.7V 锂电池 低功耗主控 LoRa 的组合。低功耗的核心设计是按需唤醒。室外机默认进入深度睡眠模式只有定时器在跑每 10 分钟唤醒一次做以下事情读取传感器、计算平均风速和雨量累加、打包成帧、通过 LoRa 发送到室内机、再次睡去。发送完立即关掉传感器电源和 LoRa 模块电源通过 MOSFET 切电比软件关闭外设时钟更实在。MCU 深度睡眠电流一般在微安级别整个室外机真正耗电的不是主控而是传感器和通信模块。所以电源切换电路很关键平时把所有传感器和 LoRa 的 VCC 断开唤醒瞬间再打开等模块上电稳定几十毫秒后再读取数据。6.2 太阳能电池容量核算室外机如果只靠电池几个月就得换一次。有些位置实在不方便换电我就加了太阳能板。选型前先做一次功耗估算千万不能拍脑袋。我给的典型场景是室外机传感器采集阶段电流约 10mA持续 1 秒LoRa 发送阶段约 120mA持续 0.5 秒其他时间睡眠。10 分钟一个周期平均电流大概在几十微安到 0.5mA 之间再加上电源转换损耗和传感器上电损耗我给整机预算 5mA 平均电流。用 2600mAh 锂电池算不考虑太阳能时能撑约 20 多天这个余量已经够应付连续阴雨。太阳能板选 6V/2W晴天日均发电按 4 小时有效日照折算一天大约 8Wh 左右而负载一天耗电不到 0.5Wh充电量富余非常多。配合充电管理模块要特别注意不能用太阳能板直连电池必须经过带防反充的充电管理芯片否则晚上太阳能板反而变成负载把电池抽干。我实际测试下来的经验是这套组合在广东这种冬天阴雨天多的地方也能连续维持最差情况下半个月不见太阳电池电量也只掉一部分。6.3 室外机外壳的坑防晒、防水、防结露室外机外壳我选用 IP65 以上等级的防水接线盒但只用防水盒还远远不够。第一个坑是太阳辐射。黑色或深色外壳被阳光直射后内部温度会比真实气温高好几度温度传感器测出来根本不是气温而是盒子里的热空气。解决办法是把盒子刷成白色或银色放在屋檐下避免直射同时温度传感器尽量外置到盒子外面至少也要让测温探头紧贴外壳外侧。第二个坑是结露。盒内空气湿度大、温度变化剧烈时内部会凝露传感器直接短路。我的做法是盒内放两三包硅胶干燥剂并在盒子底部开一个小呼吸孔孔径几毫米内部贴防水透气膜让内外气压平衡又不进水。第三个坑是防风。雨量桶和风速计都是用支架固定在盒子外面的常规 L 型支架在台风天容易被吹歪。我用两个固定点把风速计支架夹在阳台栏杆上又加了一根钢丝备用这套装置经历过两次台风目前还没被吹跑。7. 固件架构和踩坑实录7.1 裸机调度几个定时器加一个状态机足够室外机和室内机的固件我都没有上 RTOS用裸机前后台架构跑得很稳。道理很简单任务少、周期固定、每个任务的耗时都可控RTOS 带来的线程切换反而引入不确定性。主循环里我是这样安排的一个毫秒级定时器产生时基每 10ms 处理一次按键和 Led 刷新每秒检查一次是否到了传感器采集时间每 10 分钟触发室外机唤醒完成采集和发送每 60 秒触发室内机 MQTT 数据上报。每个任务只是一个函数主循环轮询标志位到了就执行。这套结构最大好处是出问题好定位哪怕某个传感器卡住也不会影响其他任务因为每个任务都会在开头检查一下上一个周期是否正常完成。7.2 I2C 总线卡死一次把 SDA 拉死的故障排查踩坑实录里最典型的就是 I2C 卡死。某天室外机突然收不到 SHT30 的读数把传感器换到室内机单独测试发现每次读到一半I2C 总线就卡死SCL 正常跳SDA 一直拉低后续命令全部无响应。排查下来问题出在长线供电和接线毛刺上。室外传感器的线接近两米风吹日晒后接线端子氧化接触电阻变大供电瞬时跌落传感器内部逻辑混乱最后把 SDA 线拉在低电平不放。真正解决问题的办法有两步第一固件里加 I2C 总线恢复代码。当一次通信超时后把 SDA 和 SCL 引脚临时配置成普通 GPIO 输出手动翻转 SCL 九个时钟周期让卡死的从机释放 SDA再恢复正常 I2C 模式重试。这一步我实现成独立函数每次 I2C 失败都会调用。第二硬件上把所有接线端子换成压接端子并灌胶固定传感器供电端加一个 100uF 电解电容和 0.1uF 陶瓷电容保证电压稳定。加了这两个措施后再没有出现过 I2C 卡死。7.3 传感器失效与数据异常的判读室外设备长期风吹雨淋传感器一定会出问题所以要提前设计数据可信度判断逻辑而不是傻乎乎地一直显示失效值。我的规则很简单每次传感器读回来先做合理性检查。温度超过 -30℃~60℃ 直接判无效湿度和光照超过量程清零气压变化率一小时内超过 5 hPa 也标记异常。一旦判定异常该通道的值就不参与上报屏幕上会显示--云端曲线会断点而不是出现离谱的尖峰。这个逻辑在雨季特别有用。有一阵雨量计被落叶卡住翻斗误报了几十毫米降雨就是因为没做连续降雨合理性判断。后来加了规则连续 24 小时降雨超过 300mm系统自动提醒检查雨量计。虽然这个阈值过于严苛但至少把机械故障和真实暴雨区别开省掉了不少误报清洗工作。另外室外机和室内机之间如果连续 3 轮通信都失败室内机要主动标记室外机离线而不是继续展示上一份缓存数据这个状态提示能让用户第一时间发现链路故障而不是对着过时数据做判断。整套系统从画草图到跑稳定大概花了两个周末现在已经在阳台外连续运行了几个月。如果让我重做一遍我会第一版就直接上太阳能低功耗方案而不是先用有线调试、之后再改无线供电后者反而花掉更多调试时间。最后留一条建议气象站这类项目稳定性和长期运行比功能炫酷重要得多先跑通一个最简链路再一步步加传感器否则很容易卡在什么都想做、什么都没做稳的状态。
返回列表