资讯详情

基于STM32、Lora与4G的物联网水质监测系统设计与实践

📅 2026/9/17 8:29:19 | 华诺云谱 👁 阅读
基于STM32、Lora与4G的物联网水质监测系统设计与实践
1. 为什么是STM32Lora4G这个组合1.1 水质监测现场的通信难题先聊点实际的。你被安排做水质监测或者说毕业论文选了这个方向第一反应肯定是想传感器一接、数据一读、往平台一扔完事。真到了现场才会发现事情没那么简单。水质监测的场景往往是河道、水库、养殖塘、污水处理站排口这些地方有一个共同点现场根本没有网线甚至没有稳定的电源。你没法蹲在河边插着笔记本跑 Python 脚本也没法指望在漂浮的浮标上拉一根光纤。那用WiFi行不行覆盖范围就几十米信号过个水面的雾气都打折扣而且现场根本不具备铺设路由器的条件。用蓝牙距离太短做产品原型可以做工程部署不现实。这时候就会想到蜂窝网络也就是直接上一块4G模块让每个采集点独立上云。方案可行但成本高——每个监测点位都要单独买一张SIM卡、单独缴流量费如果监测点有十几个、几十个这是一笔不小的运营开销。而且水质监测点位密集布置时很多采集点之间的距离其实只有几百米用4G是把资源浪费在了“每个点都有一副卫星天线”这件事上。于是就有了业界非常成熟的组合STM32做边缘采集主控Lora负责把几十个甚至上百个采集点的数据汇聚到网关4G放在网关这一侧作为骨干回传通道。1.2 三层架构与分工整个系统是一个典型的物联网三层结构感知层每个采集点有一块STM32最小系统板挂接水温、pH、浊度、溶解氧等传感器定期采集、本地存储、定时上报。网络传输层采集点通过Lora无线模块把数据发给附近的网关。Lora工作在Sub-1GHz频段常用433MHz或470MHz穿透力和绕射能力远强于2.4GHz的WiFi/蓝牙在野外水面上能轻松打几百米到几公里。网关收到数据后通过4G模块走MQTT协议上报到云平台。应用层云平台做数据解析、存储、展示和报警手机端或大屏端实时查看监测指标。这套架构的核心逻辑是就近短距离通信用Lora解决远距离回传用4G解决中间用STM32当大脑把两边粘起来。Lora解决的是“最后一公里”的组网问题4G解决的是“骨干通道”问题。你不需要每个传感器都装SIM卡只需要一个网关装SIM卡这就把运营成本降了一个数量级。1.3 这套组合的取舍有人会问为什么不用NB-IoTNB-IoT确实是低功耗广域网的正统选择但它在很多地区面临网络覆盖不稳定、运营商套餐不灵活的问题而且它本质上也是每点一卡费用结构并不比Lora汇聚的方式便宜。更重要的是NB-IoT的接入延迟和数据速率都比Lora苛刻对于水质监测这种“传感器种类多、数据帧参数大”的场景Lora的开放性高得多你可以自定义协议把pH、温度、浊度、溶解氧打包在一块帧里发出去。还有人问那直接把4G模块挂在STM32上行不行也行但你要面对的是每个采集点都塞一张卡、都做一次网络鉴权的问题。而且4G模块发射瞬间电流能达到2A峰值对电池供电的采集终端来说是灾难。Lora模块的峰值电流也就120mA左右差距非常明显。所以这套组合不是拍脑袋选的是成本、功耗、覆盖、可维护性四方面综合权衡下来的结果。接下来的内容从硬件选型到软件调通按整条链路走一遍。2. 硬件选型从传感器到主控一个都不能省2.1 先搞清要测什么指标水质监测这个词太宽泛。在动手买传感器之前一定要先明确监测项目。常规地表水监测的核心指标一般包括水温基础指标几乎所有水质模型都需要温度补偿。pH值衡量水体酸碱度反映污染状况的重要参数。浊度水体中悬浮颗粒物的含量直接影响水体透明度。溶解氧DO衡量水体自净能力的关键指标水产养殖用户最关注它。电导率/TDS反映水体中离子总浓度判断是否混入工业废水或海水倒灌。新手最容易犯的错是一上来就买“多合一水质传感器”——这种探头确实方便但价格动辄几千上万而且一旦某个通道坏了整个探头都要返厂。工程上我更推荐用分离式传感器哪个坏了换哪个维护成本可控。传感器选型上有两条路一是选工业级变送器一般输出RS485Modbus RTU协议或4-20mA模拟量二是选实验室级别的电极加变送电路自己搭。后者精度可控但不适合野外长期部署漂移问题很难解决。我的建议是做系统集成就选带RS485输出的工业变送器省下的时间远比你纠结那几百块钱值。2.2 主控STM32F103还是STM32L431主控的选择取决于你的功耗约束。如果现场有市电供电比如污水处理站排口在线监测站房那直接用STM32F103C8T6就够了几十块钱一片、资料铺天盖地、Keil里点几下就能跑起来开发效率最高。如果现场是电池供电比如河道浮标、养殖塘无人值守站点那就得上低功耗系列STM32L431或者STM32L4系列支持多级低功耗模式STOP模式电流只有几微安RTC唤醒后到正常采集模式的切换时间也短。我实际开发的这个系统用的是STM32L431RCT6原因很简单浮标站只能靠蓄电池太阳能板供电功耗控制是第一优先级。如果你只是做毕业设计或者站房式监测F103完全够用不用被“低功耗”三个字吓住。主控和外设的连接关系大致是pH变送器、浊度变送器、溶解氧变送器全部走RS485总线STM32的USART方向控制引脚接MAX485/SP3485芯片一根两线总线并行挂多个传感器用Modbus协议分地址读取。水温DS18B20单总线或者变送器自带的温度输出走GPIO。电源控制每个传感器的供电通过MOS管开关控制采集时才上电采完就断电这是低功耗设计的核心手段。Lora模块走SPI接口SX1278/SX1262方案或UART接口成品AT指令模块推荐带PALNA的成品模块射频性能更有保证。2.3 Lora模块的讲究Lora模块的选型有两条路线一是直接用Semtech SX1278/SX1262射频芯片自己画射频电路二是买集成好的模块如E22-400M系列、ATK-LORA-01等。前者适合量产降成本后者适合开发调试。我建议项目前期先用成品模块你只需要关心SPI或UART接口不用折腾阻抗匹配和天线调试。重点说天线。433MHz的波长大约0.7米1/4波长单极天线长度约17cm。实际部署时天线的安装位置和方向对通信距离影响极大——天线尽量垂直放置远离金属物体和地面高度每提高一倍通信距离能提升约40%。很多人在实验室里测试Lora能跑几百米一到河边贴地放模块就连不上多半就是天线高度和极化方向的问题。工作参数上我常用的是中心频率433MHz、带宽125kHz、扩频因子SF10、编码率4/5。这个配置空口速率约1kbps左右单帧传30字节以内的数据包绰绰有余空旷环境下能达到3公里以上。如果你更看重距离可以调成SF12但速率会降到300bps左右帧长稍长一发就是几百毫秒反而不利于组网效率。扩频因子不要盲目调最高要根据你的上报频率和数据帧大小平衡。2.4 4G模块Cat.1比Cat.4更现实网关回传端我用的是合宙Air724UG一款Cat.1 4G模块。这里说明一下现在市面上的“4G模块”分两种Cat.4如移远EC200S和Cat.1如Air724UG。Cat.1的上行速率大概5Mbps下行10Mbps虽然不如Cat.4快但水质监测上报的数据量是KB级的Cat.1完全够用而且Cat.1模块的价格只有Cat.4的一半左右功耗也更低。模块和MCU之间走串口AT指令。Air724UG 支持MQTT、TCP、UDP、HTTP等协议你只需要在串口上发AT指令建连、订阅、发布就可以了不需要自己用PPP协议栈去拨号。开发方式可以参照“MCU发AT指令、模块解析回应”的标准模式也可以通过Lua脚本在模块内部做二次开发。我个人还是更推荐让MCU发AT指令这样逻辑都集中在STM32侧便于统一调试和升级。2.5 电源与低功耗设计这套系统里最容易翻车的就是电源部分。采集节点的典型供电方案是太阳能板铅酸蓄电池DC-DC降压。12V蓄电池经过降压到5V给传感器变送器供电再降压到3.3V给MCU和Lora模块供电。千万别直接用AMS1117线性稳压从12V降到3.3V压差8.7V乘以电流功耗全烧在芯片发热上了——我曾经量过一片AMS1117空载1.2W发热整个模块烫得摸不了。用MP1584、TPS5430这类开关降压芯片效率轻松90%以上。低功耗设计上采集节点每隔10分钟唤醒一次唤醒后完成四件事给传感器上电、等待200毫秒稳定、轮询读取所有指标、断电传感器。整个活跃周期控制在500毫秒以内其余时间MCU进入STOP模式Lora模块进入Sleep模式。我实测这配置的静态电流大约是MCU STOP模式4uALora Sleep模式2uA传感器全部断电电源系统自身消耗约30uA整机静态电流约40uA左右。工作状态瞬时电流约80-120mALora发射瞬间。折算下来日平均功耗非常低一块20Ah的12V蓄电池配40W太阳能板在连续阴雨七天的条件下还能稳定运行。3. 软件实现STM32采集、Lora组网、4G上云的完整链路3.1 STM32传感器采集Modbus RTU是基本功工业水质变送器绝大多数支持Modbus RTU协议。这套协议本身不复杂主站STM32发起请求帧从站传感器返回响应帧。RTU格式里一个字节起始位、8个数据位、1个停止位无校验——或者带CRC校验。重点记住帧结构设备地址(1字节) 功能码(1字节) 寄存器起始地址(2字节) 寄存器数量(2字节) CRC16(2字节)传感器上电后默认地址一般是01波特率9600或4800。用STM32的USART3连485芯片发送请求后切换方向为接收等待传感器回复。这里有几个坑必须提第一485方向切换时序。发送完请求帧后必须预留至少3-5个字节的收发切换时间否则传感器返回帧前几个字节会被吃掉。我习惯在发送完成后延时2ms再切换接收模式实测稳定。第二读取寄存器的数量。pH变送器一般用功能码03读取多个寄存器比如地址0x0000存pH值带两位小数0x0001存温度。你在发送前先确认每个寄存器的精度描述——有的传感器是存原始ADC值而不是物理量需要在STM32侧做换算这一步就藏在产品手册的角落务必找出来。第三CRC校验不能省。Modbus RTU末尾两字节是CRC16protocol的实现网上代码很多。虽然有的传感器即使你算错CRC也会响应但工程上必须自己算一遍校验否则总线上混入垃圾数据时你根本查不出来。我自己的代码把传感器抽象成一层“统一的采集接口”一个函数、一个入口传传感器地址进去返回物理量。这样后面加新传感器只需要给传感器节点加地址和设备类型不用改主流程。3.2 Lora通信协议设计帧格式是自己定的Lora本身只管“物理层无线收发”不管应用层协议。所以你要自己定义一套帧格式把节点号、数据类型、数据值、CRC打包发给网关。我在项目里用的是如下格式帧头0xAA 0x55用于接收方识别一帧的开始。类型1字节0x01表示数据上报0x02表示配置下发0x03表示网关应答。节点ID1字节支持255个采集点。数据长度1字节。数据区按顺序放水温、pH、浊度、溶解氧、电导率等字段每个字段2字节整数物理量乘以100取整1字节符号位。CRC162字节对“类型节点ID长度数据区”做校验。这块帧格式看着简单实际坑在“网关应答”那一环。数据上报后网关收到会回一个ACK帧节点如果在500ms内没收到ACK就重发重发3次后丢弃这一帧。别小看ACK机制没有它丢包了你都不知道数据去哪儿了。而且当多个节点同时上报时必须错开上报时间——我用了简单的TDMA时分复用方式每个节点有自己固定的上报时隙比如节点1在第0秒上报节点2在第30秒以此类推。如果上报间隔是10分钟那每10分钟可以容纳20个节点60个节点就分布在3个上报周期里。这样在最底层规避了同频碰撞的问题。LoRa配置上我用的是433MHz中心频点带宽125kHzSF10输出功率20dBm100mW。为什么不用SF12SF12意味着接收灵敏度更好距离更远但空口传输时间会拉长到几百毫秒甚至上秒。在水质监测这种“每帧20字节”的小数据应用里过长的空中占用时间只会增加碰撞概率不值得。3.3 4G模块与云平台的MQTT对接网关端硬件上是一块STM32F103Air724UG 4G模块Lora模块逻辑上是把Lora收到的各个节点的数据通过4G-MQTT转发到云平台。MQTT的架构是发布/订阅模型要先把数据发布到“主题”Topic。我使用的是阿里云物联网平台设备接入方式为MQTT协议。整个AT指令流程如下上电后发AT等待模块返回OK。用ATCSQ查信号质量返回值范围0-31大于15基本可用。ATCGATT1附着数据业务ATCEREG? 查看EPS网络注册状态返回1或5表示已注册。配置MQTT接入点信息。阿里云里面需要填入ProductKey、DeviceName、DeviceSecret经过一长串的TLS握手和签名校验。这个过程如果手动一帧帧拼AT指令会很痛苦建议先把所有AT指令拼成一个字符串模板逐一替换三个参数再用轮询方式等待每个步骤的返回值确认后再进下一步。一个比较重要的调试技巧当MQTT连不上时先用ATCMQTTDISCONN将旧连接断开很多时候是上一次会话没有正常关闭端口被占住新连接就无法建立。云平台侧的数据解析我用的是物模型Product Model方式。在三方平台定义一个“水质监测”物模型包含温度、pH、浊度、溶解氧、电导率五个属性。上报的payload按照物模型定义用JSON格式上传比如{ temperature: 25.6, ph: 7.32, turbidity: 12.8, do: 8.1, conductivity: 312 }云平台收到JSON后自动解析并落库如果要可视化大屏直接用平台自带的报表功能还可以配置告警规则比如pH低于6.5或高于8.5时触发短信报警。这些功能各平台大同小异但能做到开箱即用。3.4 节点固件主流程与状态机节点端STM32的完整主流程可以抽象成一个简单的状态机初始化状态系统时钟、GPIO、USART、RTC、Lora模块SPI初始化读取Flash中保存的节点ID和上报周期。休眠状态进入STOP模式RTC定时唤醒中断里唤醒后跳到采集状态。采集状态依次打开传感器电源等待200ms稳定通过Modbus协议读取各传感器数据全部读取后关闭传感器电源将数据写入待上报缓冲区。上报状态向Lora模块写入上报帧等待网关ACK最多重发3次。回到休眠状态无论上报成功还是失败都要进入休眠等待下一个RTC周期。状态机的关键在于每个状态都要有超时保护。比如在“采集状态”中如果Modbus总线上的传感器没有响应你不能让系统一直卡在等待循环里——5秒超时后自动跳过该传感器上报空值并打上标志位。我见过有同行在传感器故障时整个采集节点死机最后发现就是Modbus等待没有超时机制一个传感器故障整个站点停摆。4. 实测踩坑与排查清单4.1 上电不通与串口乱码新画好的板子或新买的模块上电后串口打印乱码或者完全没有输出这是老朋友了。排查顺序是固定的先万用表量供电电压3.3V必须稳定在3.3V±5%如果有压降波动查LDO或DCDC的负载。再检查晶振是否起振。STM32用8MHz晶振配合PLL如果晶振焊反或谐振电容不匹配芯片根本跑不起来。然后检查BOOT0引脚电平如果BOOT0被拉高MCU会进入系统存储器模式不会跑你的Flash程序。最后确认串口波特率。注意晶振频率不同内部时钟误差可能导致串口波特率偏移比如用HSI内部时钟跑115200经常出乱码换成外部晶振后就好了很多。4.2 Lora通信距离断崖式下降成因Lora最诡异的问题是“昨天能通3公里今天300米都连不上”。排查方向按影响从大到小排序天线故障。这是最常见的原因。天线接头进水氧化、天线外皮破损、或者天线末端被人为剪短都会导致驻波比飙升射频能量发射不出去。用网分测一下驻波比最准确没有网分就换一根天线测试对比。天线周围环境变化。天线旁边新装了一根金属水管或者天线被人捆到了金属杆上辐射效率会急剧下降。注意天线周围30cm内不要有大的金属平面。频点偏移。晶体老化或温度变化导致晶振频率偏移实际发射频率偏离中心频点几百kHz接收端灵敏度骤降。长年在野外暴晒的模块这个概率不低。电池电压过低。Lora模块在低电压下输出功率锐减。实测3.3V供电比3.6V供电的发射功率要低3dB以上相当于距离减半。所以如果节点是电池供电发现距离变短时先量电压。4.3 4G模块频繁掉线与MQTT断连4G模块连着连着就掉线重连后又掉这个在项目部署初期几乎必现。排查思路先用ATCSQ看信号值低于10说明信号覆盖很差考虑换运营商或加外置吸盘天线。确认SIM卡是否开通了物联网流量套餐。普通手机卡在某些物联网设备上会被运营商的风控系统检测并封停表现形式就是“能注册网络但无法拨号PDP激活”。检查MQTT心跳包间隔。运营商NAT超时时间一般是5分钟左右如果MQTT保活时间超过90秒连接可能被运营商静默踢掉。阿里云MQTT的心跳周期建议设置在30-60秒之间。重连逻辑要加退避机制。不要断线后立刻疯狂重连容易触发模块的过流保护。我用的是指数退避第一次5秒重连第二次10秒第三次20秒最多到300秒封顶。这样哪怕运营商基站做夜间维护模块也能平稳自动恢复。4.4 数据异常漂移与精度校准数据漂移的问题是硬件和软件交织的也是最耗时间的部分。pH值漂移pH电极观察校准必须在探头使用前及使用中定期进行。河边浮标站的探头泡在流动水体中电极表面非常容易结垢或附着生物膜导致响应变慢、读数漂移。解决的方法有两个层面一是站点维护制度上规定每两周用标准液校准一次二是硬件设计上给pH探头加自动清洗装置——简单点就是装一个微型水泵每次测量前用清水冲喷探头2秒。在自动化要求高的站点上这个改造非常管用。浊度数据跳变浊度传感器测量的本质是红外光散射信号任何气泡、浮游生物、或者传感器窗口附近的微小颗粒都会引起剧烈跳变。除了采样时的滑动均值滤波我取5次读数的中值再加一次3点移动平均更重要的是将传感器探头布置在远离水面的一个固定深度。很多项目把探头直接吊在水表之下30cm处水位一波动数据就乱跳。可以的话在探头外增加一个稳流桶效果立竿见影。溶解氧传感器荧光帽老化荧光法溶解氧传感器的荧光帽通常寿命一年左右随着时间推移响应会变慢、读数偏低。这属于耗材更换范畴应该纳入运维预算表里。我在后台管理页面里加了一个“探头寿命倒计时”字段根据安装日期自动计算剩余使用周期到期前一个月提醒更换能有效避免因探头老化导致的误报警。5. 部署与运维的几点经验系统调通后在真实水体环境连续运行了一个多月积累了一些经验挑几条值得说的。5.1 现场布线的防护比什么都重要实验室里调通的系统拉到现场最大的不稳定因素不是代码而是线缆。河边风大、湿度大、盐雾重户外防水接头里如果没有灌胶铜线裸露的部分很快就会氧化发绿接触电阻升高导致信号异常。我现在养成了习惯所有户外接点必须做三种防护——热缩管套住焊点、绝缘胶带缠紧、整段接头再用防水胶泥包裹。听起来土但实测一年后拆开检查内部依然干爽如新。5.2 数据上报要有“雪崩保护”当Lora网络里节点数量超过20个时需要格外小心“雪崩效应”。正常情况各节点按时间片轮流上报但如果网关重启后所有节点同时检测到网络恢复它们会一起尝试上报——Lora是半双工通道同频碰撞必然发生。解决办法是在节点代码里加入随机退避苏醒后先计算自己所在的时隙再叠加一个0-3秒的随机偏移。这样即使多个节点同时醒来数据也会错开到达网关。5.3 云平台上的数据要保留原始帧云平台上展示的数据尽量用“物理量单位时间戳”来存但底层最好留一份原始上报帧的日志哪怕是存到文件里都行。原因是有时候数据看起来“不对”可能是传感器标定问题、变送器系数算错、或者是协议解析错误。如果你只存了最终结果很难回溯问题在哪一环。我在阿里云上除了物模型属性还额外开了一个“原始数据”日志流每帧消息的完整payload都原样落一份日志排查数据问题时效率提高了太多。5.4 固件远程升级预留好接口出野外更新的痛经历过一次就懂了。如果条件允许尽量在一开始就给节点预留固件升级通道。Lora本身带宽有限传固件不现实但你可以把网关的网络通道利用起来——网关从云端下载固件包存到TF卡或Flash里再通过Lora分帧下发节点收到后写入Bootloader区校验通过后跳转执行。我这套系统的节点支持这个功能后部署在几公里外的站点更新参数再也不用跑现场了。哪怕你这次用不上预留一个升级指令也花不了多少代码。这套系统做到后面更大的感触是物联网项目的难点从来不在于某一项技术有多深奥而在于把传感器、无线通信、嵌入式底层、云平台、现场施工这些环节像齿轮一样啮合到一起。STM32、Lora、4G这套组合每一项都是成熟得不能再成熟的技术但把它们按正确的顺序、正确的方式组织起来才是一个能真正落地跑一年的水质监测系统。
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。