基于NB-IoT与STM32的智慧农业大棚环境监测系统设计 📅 发布时间:2026/9/3 18:50:39 👁 浏览次数: 简介一套基于NB-IoT的STM32温室大棚环境监测系统资料包面向物联网、嵌入式及智慧农业方向学习者与开发者用于解决大棚环境远程监测与设备联动控制问题。系统集成sht30高精度温湿度、光敏、土壤湿度传感器配合继电器控制LED补光灯、排气扇和浇水水泵可实现自动浇水灌溉、灯光自动调节与自动通风并通过NB-IoT窄带通信将数据上传阿里云用户通过手机APP即可远程查看数据、控制设备、调节触发阈值。资料核心为Android APP源码压缩包共617个文件、约24.88MB文件类型以flat、json、xml工程文件为主另含dex、class、jar等编译产物及apk安装文件能完整体现从代码工程到安装包的构建链路。已有230人学习浏览适合毕业设计、课程设计或项目二次开发参考重点是云平台交互流程、远程控制逻辑与阈值设置界面的实现方式。 做农业物联网项目这几年我最大的感受是这个方向看着不如工业互联网、车联网那么“高级”但真把一个系统从选型到部署跑起来里面要踩的坑一点不比那些热门领域少。今天想跟你们聊聊我刚完成的一套基于NB-IoT窄带物联网和STM32的温室大棚环境监测系统属于典型的智慧农业应用场景核心工作是采集大棚里的空气温湿度、土壤湿度、光照强度等关键环境参数通过NB-IoT网络传到云平台让种植户在手机和电脑上就能看到实时数据。这套系统我用了STM32F103C8T6作为主控搭配BC26 NB-IoT模组完成数据传输硬件成本压缩在百元级别功耗实测下来待机电流能做到微安级。如果你是做嵌入式开发的学生、想切入智慧农业领域的工程师或者已经在大棚里用过那种“只显示不联网”的简陋仪表、想自己动手做一套真正能远程监控设备的开发者这篇文章都值得你看完。下面我会从方案选型、硬件设计、代码实现到现场问题排查完整复盘一遍这个项目的实际过程把踩过的坑和解决问题的思路都摊开讲。1. 系统整体设计思路为什么在智慧农业场景里我最终选了 NB-IoT没有用 Wi-Fi 或者 LoRa先回答一个我经常被问到的问题大棚环境监测这种场景距离不远、数据量又不大为什么不用 Wi-Fi、蓝牙或者 Zigbee非要上 NB-IoT这个选择不是拍脑袋定的是结合大棚现场的真实条件反复权衡后的结果。1.1 通信方案选型NB-IoT 为什么适合农业现场大棚的分布有个很明显的特点绝大多数在郊区、野外甚至是山坳里位置分散而且一个种植基地可能同时有好几十个大棚。如果每栋棚都拉一根网线或者指望现场有个稳定可靠的 Wi-Fi 路由器基本不现实。Wi-Fi 覆盖距离短大棚的金属骨架和薄膜对信号衰减非常明显实测穿两栋棚之后信号就基本不可用了。Zigbee 和 LoRa 这类方案需要自建网关网关又要联网等于把问题从“每个棚联网”变成了“网关联网”成本和高维护点并没有真正消失。NB-IoT 的核心优势就在这儿它直接复用运营商的蜂窝网络和手机一样插卡就能入网不需要自己布基站、不需要配网关只要手机有信号、且运营商开通了 NB-IoT 覆盖的地方就能用。它的单连接功耗极低非常适合这种“每几分钟上报一次、每次只传几十字节”的周期性小数据量场景。前年我在一个丘陵地区的茶园部署设备周围几百米都没有 Wi-Fi 路由器但 NB-IoT 信号满格设备装好上电两分钟就完成入网注册了这种体验是 Wi-Fi 方案完全给不了的。1.2 系统架构与数据链路这套系统的整体架构我拆成三层来看感知层、传输层、应用层。感知层是挂在 STM32 上的各类环境传感器负责把物理量转成电信号传输层是 NB-IoT 模组负责把 MCU 处理好的数据打包发到运营商网络应用层是云平台和手机端负责数据存储、展示和阈值告警。数据链路具体是这样走的STM32 按照设定的周期我一般设 5 分钟一次读取传感器数据做滤波和标度变换之后按约定的 JSON 格式拼装成字符串通过串口发给 BC26 模组模组再通过 NB-IoT 网络把数据包投递到云平台。云平台端我一开始用 MQTT 协议接入后面为了方便开发又接了 HTTP 方式做双通道备份。整个链路里 STM32 只做采集和协议封装不负责复杂的网络逻辑NB-IoT 模组内部已经处理了物理层和数据链路层的通信这大大降低了 MCU 端的开发负担。2. 核心硬件选型与电路设计要点硬件的选型决定了整个系统的成本、功耗和稳定性下限。我在这个项目里主控用了 STM32F103C8T6模组选了移远的 BC26传感器部分用的是 DHT11 以外的升级方案下面逐个说清楚理由和设计细节。2.1 STM32 选哪一颗才是够用不浪费很多新手一上来就想用 STM32F407 甚至 H7 系列觉得性能越强越好。实际上大棚环境监测这种应用传感器数据量少、实时性要求不高一颗 Cortex-M3 内核的 STM32F103C8T6 已经完全够用而且它的资料多、开发工具链成熟、芯片价格便宜批量采购几块钱一颗不管是学生做课设还是小批量生产都非常合适。如果你做的是电池供电的户外部署版本我更推荐 STM32L431 或者 STM32L0 系列因为它们在低功耗模式下的表现比 F1 好很多。我在这个项目里先用 F103 验证了全部功能后面做低功耗版本时换成了 STM32L431软件上基本只改了时钟初始化和低功耗配置的部分其他代码几乎原样复用这种软件兼容性也是选 ST 平台的一个重要原因。2.2 NB-IoT 模组选型与供电设计NB-IoT 模组我选了移远 BC26原因很直接它支持 PSW省电模式和 eDRX扩展非连续接收在所有主流 NB-IoT 模组里功耗做得是数一数二的而且封装小、价格便宜、配套文档成熟。它的通信接口很简单走的就是 UART 加 AT 指令任何一个用过 GSM 模组的工程师都能无缝上手。供电部分是这个项目里最容易掉链子的地方我吃了两次亏才彻底改对。BC26 在发射瞬间的峰值电流可以达到 250mA 左右如果用线性稳压器直接供电电压会被瞬间拉低模组就直接重启了。我最终的方案是用一节 18650 锂电池3.7V 标称加上一颗 TPS63020 升降压芯片把电压稳定在 3.8V 给模组供电同时在模组的 VBAT 引脚旁边并联一个 1000uF 的钽电容和一个 100nF 的陶瓷电容。这个电容组的作用就是提供瞬态电流缓冲实测下来模组发射时电压跌落不超过 100mV系统稳定运行再也没有出现无故重启的问题。2.3 传感器选型与接线细节传感器的选型要考虑精度、成本和现场环境的耐久性。我实际用下来觉得最合理的搭配是这样的空气温湿度SHT30I2C 接口精度比 DHT11 高一个量级价格也就几块钱关键是出厂校准好不用自己做标定。土壤湿度电容式土壤湿度传感器注意不要买那种裸露铜板的电阻式插在土里几个月就会被电解腐蚀。电容式的电极是镀镍处理的抗腐蚀能力强很多。光照强度BH1750I2C 接口直接输出勒克斯值接在 STM32 的 I2C 总线上和 SHT30 共用一条总线省引脚。接线细节上有两个要点一是所有传感器和模组的电源线要尽量粗短特别是土壤湿度传感器这种模拟量输出的线长了会引入明显的压降和噪声干扰二是 I2C 总线的上拉电阻不能省STM32 内部的上拉太弱总线长了波形会失真我一般在外部加 4.7k 的上拉电阻到 3.3V。如果传感器和主板之间的连线超过 20cm最好用带屏蔽的线材并且屏蔽层单端接地。3. 软件实现从数据采集到云平台上报硬件搭好只是完成了三分之一的工程真正决定系统好不好用的是软件。这一节我把 STM32 端的采集逻辑、NB-IoT 模组的 AT 指令交互流程以及低功耗策略设计完整讲一遍。3.1 STM32 端数据采集与处理MCU 端的核心逻辑其实不复杂就是一个“定时采集、即时上报”的状态循环。我用 TIM2 做了一个 5 分钟的软件定时时间到之后触发一次完整的采集流程先读 SHT30 得到温度和湿度再读 BH1750 得到光照强度最后通过 ADC 读取土壤湿度传感器的模拟量输出。这里有个容易被忽略的点土壤湿度传感器的模拟量输出和供电电压是正相关的如果供电电压有波动读到的 ADC 值就不准。我在设计里用 STM32 的内部参考电压VREFINT做了补偿每次采集前先读一次内部基准电压然后按比例修正 ADC 结果这样即使电池电压从 4.2V 降到 3.5V湿度读数的误差也能控制在 3% 以内。数据采集完不是直接打包发送的我会先做一步简单的滤波。对于温湿度和光照这种变化比较慢的物理量我连续读三次取中值这样能有效剔除传感器偶发的毛刺数据。我之前用 DHT11 的时候赶上大棚里喷雾系统启动湿度数据会瞬间跳到 99%如果不滤波直接上报云平台上就会看到一个完全不合理的跳变点。3.2 AT 指令与数据上报NB-IoT 模组和 STM32 之间的通信完全是 AT 指令驱动的协议栈都在模组内部完成。我用的 BC26 接入云平台的核心指令流如下// 1. 上电后的第一条指令查询模组是否就绪 AT // 2. 等待模组注册上 NB-IoT 网络 ATCGATT1 // 附着网络 ATCGDCONT1,IP,cmiot // 设置 APN // 3. 查询信号强度判断现场网络质量 ATCSQ // 4. 连接云平台 MQTT 服务器 ATQMTOPEN0,你的MQTT服务器地址,1883 ATQMTCONN0,client_id,username,password // 5. 发布数据topic 是设备唯一标识 ATQMTPUB0,0,0,0,device/001/data {temp:25.6,humi:68.3,light:12500,soil:42.5}这里有几个关键点。APN 必须和物联网卡运营商匹配移动的普遍是 cmiot电信是 ctiot联调的时候如果连不上网首先要查的就是这个。ATCSQ 返回的信号值建议必须在 10 以上才可能稳定通信低于这个值就是典型的覆盖盲区怎么调软件都没用。发布数据时 MQTT 的 QoS 级别我选的 0因为大棚数据对实时性和可靠性要求没那么极致丢了下一周期补上就行选 QoS 0 可以降低网络开销和模组功耗。数据协议我用的是 JSON虽然比二进制协议多传一部分字节但胜在调试方便、云平台解析直观。如果你对流量成本特别敏感可以考虑用 TLV 格式一条数据从 80 字节压缩到 30 字节左右但在项目初期完全没必要牺牲调试便利性去省这点流量。3.3 低功耗策略这个系统能不能用电池撑过一季大棚现场基本没有稳定的 220V 市电可用大部分情况下是用太阳能板和锂电池的组合供电。一套系统能不能用电池撑过整个种植季完全取决于功耗设计做了多少。我在这个项目里做了两级功耗优化。第一级是 MCU 的低功耗模式STM32 在两次采集之间的 4 分多钟空档期进入 STOP 模式用 RTC 闹钟定时唤醒唤醒后完成采集和上报再睡回去。实测下来 F103 在 STOP 模式下的电流是 8uA 左右换成 L431 能做到 1uA 以下。第二级是 NB-IoT 模组的省电模式。BC26 支持 PSM省电模式数据上报完成后模组进入 PSM 状态此时它对网络侧表现为不可达但有下行数据时网络会缓存等下次设备醒来再下发。在 PSM 模式下 BC26 的电流可以降到 5uA 以下几乎可以忽略不计。这里有个细节要注意PSM 的生效需要网络侧配合运营商默认可能不开启需要在云平台上或者通过 AT 指令主动请求我用的指令是 ATCPSMS1然后设置 TAU跟踪区更新定时器和 Active Time 的值。按照我的实测数据5 分钟上报一次MCU 和模组都进入低功耗模式的情况下系统的平均电流大约是 15mA 左右其实大部分功耗集中在模组发射的 2 秒内一节 3000mAh 的 18650 电池配一块 6V 5W 的太阳能板在晴天条件下可以做到电量一直不掉阴天连续一周也能撑得住。4. 常见问题与排查技巧实录这部分是我最想跟你们分享的因为很多问题不是看芯片手册能看出来的必须真实去过现场、亲手调过设备才能积累这些经验。我把这个项目里最典型的五个问题和排查思路列在这里。4.1 物联网卡连不上网先查 APN再查信号最后查套餐这个是我遇到最多的第一坑而且坑得很隐蔽。最开始我用的是某运营商的测试卡ATCGATT1 执行后一直返回 ERROR后来用串口抓模组的 log 才发现是默认 APN 不对。换用运营商文档里指定的 APN 之后30 秒内就成功附着网络了。另外提醒一句很多物联网卡是定向流量卡只能访问白名单里的服务器地址。如果你连的是自己的云服务器一定要先确认这张卡有没有开通相应域名的访问权限否则模组显示网络附着成功了但数据包一个都发不出去。4.2 数据偶发丢失或乱码串口电平匹配和缓冲区管理STM32 的串口 TX 是 3.3V 电平BC26 的 RX 也是 3.3V理论上直接对接就行。但我遇到过一种怪现象系统运行一两天之后偶尔会收到一帧乱码而且这种乱码没有规律。排查到最后发现是 STM32 发送数据时连续调用多次 HAL_UART_Transmit 导致帧间隙太短模组在接收缓冲区还没来得及处理完上一条的时候下一条已经进来了于是产生了字节覆盖。解决办法是发送数据前给模组留一个处理时间我每发完一条 AT 指令之后延时 100ms 再读模组的回应解析完回应之后才发下一条。同时我还在 MCU 端做了一个简单的发送缓冲区所有要发的数据先入队由 DMA 通道统一发送避免 CPU 频繁打断导致字节间延迟过大。4.3 传感器数据漂移土壤湿度传感器是重灾区土壤湿度传感器在潮湿环境里连续工作几天后读数会缓慢漂移最严重的时候能偏出 20%。这个问题的根因是电极表面在电场和土壤电解质的共同作用下产生了极化现象。应对方案有两个一个是换用交流激励的传感器很多工业级传感器内部是方波激励不是直流另一个是在软件里做定期校准。我的做法是在软件里加了一个“干湿校准”功能设备通过指令进入校准模式把传感器分别放在空气中和水中记录两个基准值之后所有读数都按照这两个基准值线性插值。这个校准流程我写成了一个命令行工具现场调试的时候用串口发一条指令就能完成实测校准之后的数据精度可以恢复到 5% 以内。4.4 功耗降不下去模组没有真正进入 PSM 模式这是我做了两版低功耗才搞定的问题。第一版我以为只要发了 ATCPSMS1 指令模组就会自动进入 PSM但实测待机电流一直在 20mA 以上怎么优化 MCU 都没用。后来查了 BC26 的手册才发现PSM 模式不是固件侧单方面决定的还需要网络侧分配一个 TAU 周期模组只有在 TAU 到期前一直处于 inactive 状态才会在 Active Time 超时后真正进入 PSM。正确的做法是先查询网络侧的 PSM 参数配置用 ATCPSMS? 看返回值如果 Active Time 是 0就说明网络侧没分配需要通过 ATCPSMS1, , , 00100101,00000101 这类指令主动请求。这里面的两个十六进制字符串分别代表 TAU 请求值和 Active Time 请求值具体的编码规则在模组手册里有复制之后对应改成你需要的周期就行。我最后把上报周期调成 30 分钟一次之后整个系统的平均电流降到了 5mA 以下。4.5 云平台数据异常和告警规则的设计经验数据上云之后不是就万事大吉了还要处理断线重连、数据补传和告警策略这几个问题。我在云平台上设计了这样的规则每个设备有单独的 topic设备上报数据后云端记录时间戳如果超过 15 分钟没有收到任何数据平台就推一条“设备离线”告警。温湿度超过阈值时也会告警但这个阈值不是固定死的而是按作物生长阶段动态调整的。比如番茄苗期和开花结果期的适宜温度范围完全不同这个参数我是通过云平台远程下发到设备的MCU 收到之后动态修改报警判断逻辑这个功能的实际体验比固定阈值好太多了——不然每次作物换茬都要重新烧写一遍固件现场工人根本搞不定。最后再分享一个调试阶段的小技巧整个项目做下来我最大的体会是这类系统的技术难点不在于某个单一模块而在于把所有环节串起来之后的稳定性和可维护性。特别是现场部署在外地、不能随时跑去调试的情况下设备的自诊断能力就变得非常重要。我在固件里加了一个简单的“心跳日志上报”机制设备每次上报数据时顺手把当前信号强度CSQ、电池电压、传感器状态、上次上报耗时时长一起打包发到云平台。这样即使在千里之外我打开手机就能看到每台设备的健康状态。有一次用户的设备突然离线我看云端记录发现上报数据之前信号值从 18 骤降到 6基本能判断是大棚附近新修了建筑遮挡了信号让工人把天线挪个位置就恢复了不用专门跑一趟现场。最后再分享一个低成本调试技巧给 BC26 模组的 UART 调试口接一个 3.3V 的 USB-TTL 模块在设备运行的时候可以实时看到模组透传出来的日志。这个日志在联调阶段排bug特别好用但正式部署的时候记得把调试日志关掉不然日志输出本身也是不小的功耗来源。本文还有配套的精品资源点击获取