物联网实战|农业电子围栏:双激光测距 + 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 告警


📌项目方案设计

需求分析

农业场景,大棚围栏入侵检测:

  1. 检测是否有物体闯入围栏区域,本地 LED + 蜂鸣器声光报警
  2. 越界告警通过 MQTT 上报华为云 IoT 平台
  3. 云平台下发指令修改围栏参数,设备应答
  4. OLED 显示围栏状态、网络状态、NTP 网络时间
  5. 断网状态下本地报警依然可用

❗痛点:农田大棚内 GPS 信号弱,GPS 电子围栏误报严重,本项目改用双激光测距实现入侵检测

硬件巧妙设计:一路串口分时驱动两个激光传感器

板子引出两个 4Pin 插座JP2、JP3外接 DYP‑R01‑V1.0 激光测距。 重点:两个传感器共用同一套 LPUART1 串口外设!

表格

插座引脚说明
JP2PB10(TX) PB11(RX)LPUART1 默认引脚
JP3PC0 PC1普通 GPIO,软件重映射为 LPUART1

✅工作机制(分时复用)

  1. 读 JP2 传感器:PB10/PB11 复用为 LPUART1,PC0、PC1 设置普通输入;和第一路激光测距通信获取距离。
  2. 读 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);
}

📊实验结果 & 和预期的差距

✅实现功能:

  1. LiteOS 多任务正常运行,OLED 展示围栏、网络、NTP 时间
  2. 双激光测距入侵检测,入侵触发 LED 蜂鸣器本地报警
  3. MQTT 上报告警至华为云,云平台下发指令,设备应答
  4. WiFi 断开,本地报警依旧工作;网络恢复模块自动重连

⚠️存在偏差(真实踩坑)

  1. 分时采集两路激光,两次测量存在时间差,高速移动入侵可能漏检;
  2. WiFi 断网时产生告警直接丢弃,没有 Flash 缓存,恢复后不会补发历史告警;
  3. 事件队列长度MQ_MAX_NUM=4,高频告警会队列溢出丢事件;
  4. ESP8285 重连需要数秒,恢复期间事件无法上报。

🚨踩坑排错总结(血泪经验)

  1. 串口引脚重映射坑 切换激光传感器,只改引脚 GPIO 复用还不够,必须重新初始化 LPUART 串口,否则收到乱码。
  2. ESP8285 一直卡在设置中 很多人忘记在 1ms 任务调用ESP8285_Time_Deal(),超时计时、看门狗完全失效!
  3. MQTT 连不上华为云 核对PROD_ID、设备密钥,HMAC‑SHA256 签名生成 MQTT 密码,签名错永远连不上。
  4. 本地报警正常,上报失败 上报之前一定要判断Is_ESP8285_Connected();没连接直接调用上报接口报文直接丢。
  5. cJSON 内存泄漏cJSON_CreateObject()之后必须cJSON_DeletecJSON_PrintUnformatted()返回堆内存需要my_free()释放,不然系统慢慢卡死。

💡拓展创新方向

  1. 增加数据滤波,对激光测距多次采样取平均,消除测距抖动误报警;
  2. 增加断网告警缓存,断网存入 Flash,网络恢复批量上报历史告警;
  3. 云平台下发参数,远程修改入侵距离阈值,不用重新烧录固件;
  4. 多级告警:距离接近阈值预报警,真正入侵严重报警;
  5. 扩大事件队列深度,减少高频上报丢包问题。

✨写在最后

这个项目很典型,把 RTOS 多任务、串口 IO 重映射、状态机驱动 WiFi 模块、MQTT 华为云接入、边缘本地判断全部揉在一起。 做物联网不要一味依赖云端,边缘本地判断非常重要,断网也要保障基础业务可用

适合课程大作业、鸿蒙 LiteOS 入门参考,完整实验报告也已经整理完毕。

如果对你有帮助,欢迎点赞收藏~

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐