物联网实战|农业电子围栏:双激光测距 + WiFi‑MQTT 上云,完整实验踩坑实录
物联网实战|农业电子围栏:双激光测距 + WiFi‑MQTT 上云,完整实验踩坑实录
🔥 前言
做物联网课程实验的时候,遇到一个很有意思的项目:农业电子围栏。 传统电子围栏大多依赖 GPS 定位,但是大棚、农田内部 GPS 信号差,定位漂移严重,误报警满天飞。 于是方案改用两路 DYP‑R01 激光测距传感器做入侵检测,STM32+LiteOS 多任务开发,ESP8285 WiFi 实现 MQTT 对接华为云 IoT,本地声光告警 + 云端告警上报双向交互。
踩了一大堆坑:串口引脚重映射分时复用、状态机驱动 ESP8285、GPS 漂移误触发、断网报文丢失、事件队列溢出…… 今天把整套方案、核心代码、工作流程、踩坑排错全部分享出来,适合嵌入式、鸿蒙 LiteOS、物联网课程作业参考。
硬件平台:NBV2.0 鸿蒙开发板 OS:OpenHarmony‑LiteOS 外设:DYP‑R01 激光测距 ×2、ESP8285 WiFi、OLED、蜂鸣器 LED 告警
📌项目方案设计
需求分析
农业场景,大棚围栏入侵检测:
- 检测是否有物体闯入围栏区域,本地 LED + 蜂鸣器声光报警
- 越界告警通过 MQTT 上报华为云 IoT 平台
- 云平台下发指令修改围栏参数,设备应答
- OLED 显示围栏状态、网络状态、NTP 网络时间
- 断网状态下本地报警依然可用
❗痛点:农田大棚内 GPS 信号弱,GPS 电子围栏误报严重,本项目改用双激光测距实现入侵检测。
硬件巧妙设计:一路串口分时驱动两个激光传感器
板子引出两个 4Pin 插座JP2、JP3外接 DYP‑R01‑V1.0 激光测距。 重点:两个传感器共用同一套 LPUART1 串口外设!
表格
| 插座 | 引脚 | 说明 |
|---|---|---|
| JP2 | PB10(TX) PB11(RX) | LPUART1 默认引脚 |
| JP3 | PC0 PC1 | 普通 GPIO,软件重映射为 LPUART1 |
✅工作机制(分时复用)
- 读 JP2 传感器:PB10/PB11 复用为 LPUART1,PC0、PC1 设置普通输入;和第一路激光测距通信获取距离。
- 读 JP3 传感器:重映射 LPUART1 外设到 PC0、PC1,PB10/PB11 降级普通 GPIO;读取第二路测距数据。
优点:节约宝贵的串口硬件资源; 缺点:不能并行采集,分时采集存在时间差,软件必须切换引脚 + 重新初始化串口。
整体架构|物联网三层架构
- 感知层:双路激光测距采集距离,LiteOS 电子围栏任务做本地边缘判断;LED 蜂鸣器本地告警;OLED 状态显示
- 网络层:ESP8285,状态机 + 环形事件队列,AT 指令驱动 WiFi、MQTT 华为云接入、NTP 网络授时
- 应用层:华为云 IoT 平台,接收告警上报,下发远程控制命令
RTOS 多任务划分:
- 电子围栏任务:采集测距,入侵判断
- 控制任务:蜂鸣器、LED 报警输出
- 视图任务:OLED 屏幕刷新
- WIFI 任务:ESP8285 状态机、事件队列处理
- 1ms 系统任务:超时计时、看门狗检测
💻核心代码片段(关键部分)
main 函数,LiteOS 任务创建
int main(void)
{
UINT32 uwRet = LOS_OK;
HAL_Init();
sysclkinit();
task_view_init();
task_control_init();
uwRet = LOS_KernelInit();
if (uwRet != LOS_OK)
return LOS_NOK;
//创建各个业务任务
creat_control_task();
creat_view_task();
creat_fence_task(); //电子围栏任务
ESP8285_Init(); //WiFi模块初始化
LOS_Start(); //启动操作系统调度
while(1){}
}
⚠️注意:
LOS_Start()之后,main 里面 while 循环不会跑,全部交给 RTOS 调度。
ESP8285 驱动核心思想:状态机 + 环形事件队列
esp8285.c 没有裸机轮询,采用状态转移表驱动: 当前状态 + 触发事件 → 下一个状态 + 执行回调函数
static void _Event_Handle(WIFI_PACKAGE* wifi)
{
int i = 0;
for(i = 0 ; i < RELATION_MAX_NUM; i++)
{
if((_State_Relation[i].state == wifi->state) && (0 != ((_State_Relation[i].event) & (wifi->event_info.event))))
{
wifi->state = _State_Relation[i].next_state;
if(_State_Relation[i].action)
{
_State_Relation[i].action(wifi);
}
break;
}
}
}
上报数据上层只需要调用:
//上报JSON告警
ESP8285_Write_Data(send_buf,strlen(send_buf));
内部压入事件队列,wifi 任务异步完成 MQTT 发布。
电子围栏业务逻辑简述
//伪代码
while(1)
{
read_laser_ch1(&dis1); //切换串口读取JP2
read_laser_ch2(&dis2); //重映射串口读取JP3
//根据两路测距判断入侵
if(dis1 < threshold || dis2 < threshold)
{
//触发本地声光报警
set_alarm(1);
//网络正常则上云
if(Is_ESP8285_Connected() == True)
{
//组装JSON上报告警
ESP8285_Write_Data(json_buf,strlen(json_buf));
}
}
else
{
set_alarm(0);
}
LOS_TaskDelay(500);
}
📊实验结果 & 和预期的差距
✅实现功能:
- LiteOS 多任务正常运行,OLED 展示围栏、网络、NTP 时间
- 双激光测距入侵检测,入侵触发 LED 蜂鸣器本地报警
- MQTT 上报告警至华为云,云平台下发指令,设备应答
- WiFi 断开,本地报警依旧工作;网络恢复模块自动重连
⚠️存在偏差(真实踩坑)
- 分时采集两路激光,两次测量存在时间差,高速移动入侵可能漏检;
- WiFi 断网时产生告警直接丢弃,没有 Flash 缓存,恢复后不会补发历史告警;
- 事件队列长度
MQ_MAX_NUM=4,高频告警会队列溢出丢事件; - ESP8285 重连需要数秒,恢复期间事件无法上报。
🚨踩坑排错总结(血泪经验)
- 串口引脚重映射坑 切换激光传感器,只改引脚 GPIO 复用还不够,必须重新初始化 LPUART 串口,否则收到乱码。
- ESP8285 一直卡在设置中 很多人忘记在 1ms 任务调用
ESP8285_Time_Deal(),超时计时、看门狗完全失效! - MQTT 连不上华为云 核对
PROD_ID、设备密钥,HMAC‑SHA256 签名生成 MQTT 密码,签名错永远连不上。 - 本地报警正常,上报失败 上报之前一定要判断
Is_ESP8285_Connected();没连接直接调用上报接口报文直接丢。 - cJSON 内存泄漏
cJSON_CreateObject()之后必须cJSON_Delete,cJSON_PrintUnformatted()返回堆内存需要my_free()释放,不然系统慢慢卡死。
💡拓展创新方向
- 增加数据滤波,对激光测距多次采样取平均,消除测距抖动误报警;
- 增加断网告警缓存,断网存入 Flash,网络恢复批量上报历史告警;
- 云平台下发参数,远程修改入侵距离阈值,不用重新烧录固件;
- 多级告警:距离接近阈值预报警,真正入侵严重报警;
- 扩大事件队列深度,减少高频上报丢包问题。
✨写在最后
这个项目很典型,把 RTOS 多任务、串口 IO 重映射、状态机驱动 WiFi 模块、MQTT 华为云接入、边缘本地判断全部揉在一起。 做物联网不要一味依赖云端,边缘本地判断非常重要,断网也要保障基础业务可用。
适合课程大作业、鸿蒙 LiteOS 入门参考,完整实验报告也已经整理完毕。
如果对你有帮助,欢迎点赞收藏~
更多推荐


所有评论(0)