基于STM32设计的防丢手环电子围栏报警系统

2024-11-13 13:57   重庆  

一、前言


本项目里用到的工具软件、相关资料可以去网盘下载【实时更新】。

https://pan.quark.cn/s/145a9b3f7f53

1.1 项目开发背景

随着社会的发展和技术的进步,人们对于个人安全和健康管理的需求日益增长。特别是在儿童、老人以及特殊人群的照护方面,何有效地保障他们的安全成为了家庭和社会关注的重点。在此背景下,结合现代物联网技术、移动通信技术和嵌入式系统技术,开发一款具备防丢功能的智能手环变得尤为必要。这款手环不仅能够满足日常健康管理的需求,计步、监测运动姿态等,还能在紧急情况下快速发出求救信号,并且通过设定电子围栏来防止佩戴者走失,为用户提供了一个全方位的安全解决方案。

本项目的开发一个集健康监测与安全保障于一体的智能穿戴设备——防丢手环电子围栏报警系统。它利用了先进的传感器技术来监测用户的活动状态,通过内置的MPU6050陀螺仪实现对用户运动姿态的精准捕捉;同时,借助ATGM336H-GPS模块,该系统能够准确获取用户的位置信息,从而使得家长或监护人能够在手机APP上设定特定的安全范围即“电子围栏”,一旦佩戴者离开预设的安全区域,系统将立即触发警报机制,向预设的联系人发送短信通知并激活手环上的蜂鸣器提醒佩戴者。此外,考虑到用户可能处于没有网络覆盖的情况,系统还配备了Air724-4G模块以确保即使在偏远地区也能保持连接,及时将重要信息传递出去。

为了增强用户体验,该手环配备了一块0.96寸的SPI协议OLED显示屏用于直观地显示各种信息,包括但不限于时间、步数统计以及GPS信号强度等,让用户随时掌握自身状况及环境情况。特别地,当遇到紧急情况时,只需按下SOS按钮即可迅速发起求助,极大提高了应急响应速度。而这一切功能的背后,离不开强大的后台支持——华为云物联网云平台,通过MQTT协议保证数据传输的安全性与稳定性,使得手环能够与手机APP之间建立起稳定高效的信息交互渠道。手机应用程序采用Qt(C++)进行开发,提供了友好且易于操作的界面设计,不仅可以让用户轻松设置各项参数,调整时间、定义电子围栏边界等,还可以利用百度地图API实现位置信息的可视化呈现,让监护变得更加直观便捷。

这款基于STM32设计的防丢手环电子围栏报警系统,是面向未来的一款创新型产品,它集合了健康管理、安全防护与智能互联三大核心优势,致力于为广大用户提供更加安心舒适的使用体验,同时也体现了科技服务于人的美好愿景。

1.2 设计实现的功能

本款基于STM32设计的防丢手环电子围栏报警系统,集成了多种先进技术和实用功能,以满足用户的多样化需求。在健康管理和日常活动监测方面,手环内置了MPU6050陀螺仪传感器,可以实时监测用户的运动姿态,并准确记录下用户的步数。这一功能不仅有助于用户了解自己的身体活动情况,也便于他们根据这些数据调整日常锻炼计划,促进身体健康。

为了使用户能够方便快捷地获取到这些信息,手环配备了一块0.96英寸的SPI协议OLED显示屏,这块屏幕不仅可以用来显示来自MPU6050传感器收集到的运动数据,比步数和当前的运动状态,还可以显示由ATGM336H-GPS模块提供的位置信息状态,以及当前时间等基础信息。这样的设计极大地提升了手环的实用性,使得用户无需频繁查看手机就能了解到自己所需的各种信息。

安全是本项目设计的核心之一。为此,为手环添加了SOS紧急求助功能。在遇到危险或者需要帮助的情况下,用户只需简单地按下手环上的SOS按键,系统就会自动发送一条包含当前位置信息的求助短信给预先设置好的联系人,同时手环也会发出蜂鸣声引起周围人的注意。这为用户提供了额外的安全保障。

考虑到不同用户可能会有不同的生活习惯或是作息规律,还开发了一款配套的Android手机应用,该应用采用了Qt(C++)进行编写。通过这款应用,用户不仅可以远程校准手环的时间,确保所有信息的准确性,还可以根据自己的实际需求设定个性化的电子围栏。当佩戴者离开所设定的安全区域时,手环将自动向指定联系人发送通知短信,并通过蜂鸣器发出警告声。同时,手机应用利用百度地图API接口实现了电子围栏的地图可视化展示,让用户能够清晰地看到安全区域的具体位置以及围栏边界。

为了实现手环与云端之间的无缝对接,整个系统采用了华为云IoT物联网平台作为数据处理中心,并通过Air724-4G模块加上MQTT协议完成设备端与云端的数据交换。这样做的好处在于,一方面确保了数据传输过程中的安全性与可靠性;另一方面也让用户能够随时随地通过手机应用查看最新的运动统计数据以及接收到来自手环的所有重要通知。综上所述,本项目不仅仅是一个简单的可穿戴设备,而是一个综合了健康管理、安全保护以及智能互联等多种功能于一体的整体解决方案。

基于STM32设计的防丢手环电子围栏报警系统实现的功能总结:

(1)实时运动姿态检测与步数记录

  • • 通过MPU6050陀螺仪传感器实时检测佩戴者的运动姿态(行走、跑步、静止等),并记录运动步数。

(2)OLED显示屏实时显示信息

  • • OLED显示屏显示采集的运动传感器数据、GPS位置信息、以及手环的当前状态(例电池电量、网络连接状态等)。

  • • 支持时间显示,显示当前的系统时间。

(3)SOS报警功能

  • • 当用户按下手环上的SOS按钮时,系统会自动发送求救短信,向预设的紧急联系人请求帮助。

(4)手机APP远程时间校准

  • • 手机APP可以与手环进行无线通信,通过云平台进行时间同步或校准,确保手环上的时间准确。

(5)电子围栏功能与报警

  • • 手机APP允许用户在地图上指定一个虚拟围栏区域(电子围栏)。当手环的GPS定位超出此设定区域时,手环会自动发送警报短信给指定联系人。

  • • 同时,手环上的蜂鸣器会发出警告声音,提示用户已超出安全区域。

(6)步数查询功能

  • • 用户可通过手机APP查看当天的步数数据,帮助用户跟踪运动进度。

(7)数据上传至云平台

  • • 设备通过Air724 4G模块与华为云物联网平台建立连接,并使用MQTT协议将手环的运动数据、GPS位置信息及状态上传到云端。

  • • 手环与云平台之间的数据传输实现远程监控和管理。

(8)手机APP与设备远程通信

  • • 手机APP通过华为云物联网平台与手环进行远程通信,接收实时数据(GPS定位、步数等),并发送控制指令(时间校准、电子围栏设置等)。

(9)电子围栏地图可视化展示

  • • 手机APP通过百度地图API接口,提供电子围栏区域的可视化展示,用户可以在地图上设置围栏区域,并实时查看手环的地理位置。

(10)低功耗设计与电池管理

  • • 手环采用可充电锂电池供电,系统设计具有低功耗特点,确保长时间使用。支持电池充电和电池电量显示功能。

1.3 项目硬件模块组成

(1)STM32F103RCT6 主控芯片

  • • 负责整个手环系统的核心控制,执行各项任务传感器数据采集、处理、控制通信、显示等。

  • • 具有丰富的外设接口,支持I2C、SPI等通信协议。

(2)MPU6050 陀螺仪模块

  • • 负责实时检测佩戴者的运动姿态(行走、跑步、静止等)。

  • • 提供三轴加速度和三轴角速度数据,帮助识别佩戴者的活动状态。

  • • 通过I2C接口与STM32主控芯片进行数据通信。

(3)OLED显示屏(0.96寸SPI协议)

  • • 用于显示手环的实时数据,运动步数、GPS位置、当前时间等信息。

  • • 采用SPI接口与STM32主控芯片进行数据传输和显示控制。

(4)高电平触发的有源蜂鸣器

  • • 用于发出提示音或报警音,特别是在电子围栏区域外或按下SOS按钮时,提醒用户或周围人。

  • • 通过GPIO口控制,产生蜂鸣提示。

(5)ATGM336H-GPS模块

  • • 提供实时GPS定位数据,用于确定手环的地理位置。

  • • 通过串口(UART)与STM32主控芯片进行数据通信。

(6)Air724-4G模块

  • • 提供手环的无线通信功能,支持4G网络连接,确保手环能够上传数据到云平台(华为云物联网平台)并接收远程指令。

  • • 通过串口(UART)与STM32主控芯片进行通信。

(7)可充电锂电池

  • • 提供手环的电力供应,支持设备的长期运行。

  • • 配合充电管理模块,支持充电和电池电量监控。

(8)充电管理模块(TP4056)

  • • 负责锂电池的充电管理,确保安全的充电过程。

  • • 提供电池电量监控、充电保护等功能。

(9)SOS按钮

  • • 当用户遇到紧急情况时,可以按下SOS按钮,触发紧急求救信号,手环会自动发送求救短信至预设联系人。

  • • 通过GPIO口与STM32主控芯片进行连接。

(10)电池电量监测模块

  • • 监控电池电量状态,提供低电量报警功能,提醒用户充电。

  • • 通过ADC接口与STM32主控芯片连接,实时采集电池电压信息。

1.4 设计思路

本项目的目标是设计一款基于STM32的防丢手环电子围栏报警系统,旨在提供用户实时的运动监测、GPS定位、防丢报警等功能。通过与手机APP的配合,手环能够实现电子围栏功能、SOS求助以及步数查询等功能,同时将数据上传至云平台,提供更加全面的监控和管理服务。

硬件设计思路

系统的硬件设计以低功耗、集成化和稳定性为核心要求。STM32F103RCT6作为主控芯片,具有丰富的外设接口,能够与各类传感器和模块进行通信,并能有效处理复杂的任务。为了实现实时运动监测,系统选用了MPU6050陀螺仪模块来检测佩戴者的运动姿态,捕捉加速度和角速度数据。通过对这些数据的实时处理,系统能够判断佩戴者是行走、跑步还是处于静止状态。

GPS模块负责为系统提供精准的位置信息,确保电子围栏功能的正确执行。当用户佩戴手环进入或超出设定的围栏区域时,系统会通过蜂鸣器发出警报,并通过短信通知预设的紧急联系人,确保在危险情况下能及时响应。

OLED显示屏作为系统的本地输出设备,提供实时的传感器数据和状态信息,包括步数、GPS位置信息以及当前时间等。蜂鸣器的设计也很简单,能够通过GPIO控制来发出声音警告,提醒用户已经超出预设的安全区域或在紧急情况下发出求助信号。

软件设计思路

软件方面,系统的设计重点是实现高效、稳定的数据采集与处理,同时确保系统的实时响应和用户交互的便捷性。STM32的固件开发将通过C语言实现,主要任务包括传感器数据采集、步数计数、姿态检测、电子围栏区域判断等。对于GPS定位数据的处理,系统需要进行解析,并与手机APP中设定的围栏区域进行对比,判断是否超出设定范围。

手环的数据上传部分通过Air724-4G模块实现。该模块支持4G LTE通信,可以实现与华为云物联网平台的数据交互。系统通过MQTT协议将采集的数据上传至云平台,确保数据的远程访问和实时更新。同时,手机APP也通过云平台与设备进行通信,获取实时数据(步数、GPS位置等)并进行相应的操作(设置围栏区域、调整时间等)。

SOS功能是本系统的核心安全功能之一。当用户按下手环上的SOS按钮时,系统将自动向预设的紧急联系人发送求救短信,提供位置信息,并通过蜂鸣器发出报警。SOS功能在软件中需要实现按钮状态检测、短信发送、蜂鸣器控制等多个步骤。

为了确保手环显示的信息准确,系统提供了手机APP远程时间校准功能,允许用户通过APP同步或调整手环的系统时间。这一功能通过蓝牙或Wi-Fi与手环进行通信,并通过云平台进行同步。

手机APP设计思路

手机APP是用户与手环互动的主要界面,主要功能包括电子围栏区域设定、实时步数查询、时间校准、报警设置以及地图展示等。APP通过百度地图API实现围栏区域的可视化展示,用户可以在地图上任意设置围栏区域,并实时查看手环的当前位置。

通过与云平台的通信,APP可以接收手环的实时数据并展示给用户,例当前步数、手环的电池电量、GPS位置等。此外,APP还能够提供电子围栏的报警设置,当手环位置超出指定围栏时,APP会收到提示消息,用户可根据需要进一步处理。

系统的整体架构

系统的架构是基于硬件和软件的有机结合,确保每个模块的协同工作。硬件部分提供了强大的传感器支持和通信功能,能够确保实时监测和报警;软件部分负责数据的处理、通信和交互,确保系统稳定高效运行。

系统的数据流主要分为两部分:一部分是从传感器采集到的数据(步数、运动姿态、GPS定位等),另一部分是设备状态的控制和远程操作。所有的数据都将通过4G模块上传到云平台,保证数据存储和访问的便利性。同时,手机APP作为用户界面,提供了全面的设备管理功能和实时数据查看。

低功耗与电池管理

手环系统采用可充电锂电池供电,并通过充电管理模块实现安全的充电与电池保护。系统在设计时充分考虑了低功耗特性,确保手环能够在长时间内持续工作。各个模块(MPU6050、GPS模块、4G模块等)在不同的工作状态下采用适当的休眠策略,最大程度地延长电池续航。

总结

整个设计的核心是确保手环能够在保障用户安全的同时,提供简单、直观的操作体验。通过STM32作为主控芯片,结合各类传感器和通信模块,系统实现了高效的数据采集和处理,同时通过4G模块与云平台进行数据上传与远程控制。手机APP则提供了用户交互界面,能够直观显示数据和设定围栏区域,实现实时监控和报警功能。

1.5 系统功能总结

功能类别具体功能描述
健康监测- 实时检测用户的运动姿态
- 记录用户的运动步数
显示信息- 通过0.96寸SPI OLED显示屏显示传感器信息
- 显示GPS状态
- 展示当前时间
紧急求助- 按下手环上的SOS按键后自动发送求助短信给预设联系人
- 同时通过蜂鸣器发出警告声音
时间管理- 支持通过手机APP远程校准手环时间
地理位置服务- 利用ATGM336H-GPS模块提供精确的位置信息
- 通过手机APP设置电子围栏区域
- 当用户离开设定区域时自动报警
步数追踪- 手机APP上可以查看当日行走步数
数据上传与通信- 通过Air724-4G模块及MQTT协议将数据上传至华为云IoT平台
- 手机APP通过云平台与设备端进行双向通信
地图可视化- 使用百度地图API在手机APP中展示电子围栏区域

1.6 开发工具的选择

【1】设备端开发

STM32的编程语言选择C语言,C语言执行效率高,大学里主学的C语言,C语言编译出来的可执行文件最接近于机器码,汇编语言执行效率最高,但是汇编的移植性比较差,目前在一些操作系统内核里还有一些低配的单片机使用的较多,平常的单片机编程还是以C语言为主。C语言的执行效率仅次于汇编,语法理解简单、代码通用性强,也支持跨平台,在嵌入式底层、单片机编程里用的非常多,当前的设计就是采用C语言开发。

开发工具选择Keil,keil是一家世界领先的嵌入式微控制器软件开发商,在2015年,keil被ARM公司收购。因为当前芯片选择的是STM32F103系列,STMF103是属于ARM公司的芯片构架、Cortex-M3内核系列的芯片,所以使用Kile来开发STM32是有先天优势的,而keil在各大高校使用的也非常多,很多教科书里都是以keil来教学,开发51单片机、STM32单片机等等。目前作为MCU芯片开发的软件也不只是keil一家独大,IAR在MCU微处理器开发领域里也使用的非常多,IAR扩展性更强,也支持STM32开发,也支持其他芯片,比:CC2530,51单片机的开发。从软件的使用上来讲,IAR比keil更加简洁,功能相对少一些。果之前使用过keil,而且使用频率较多,已经习惯再使用IAR是有点不适应界面的。

【2】上位机开发

上位机的开发选择Qt框架,编程语言采用C++;Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些宏,Qt很容易扩展,并且允许真正地组件编程。Qt能轻松创建具有原生C++性能的连接设备、用户界面(UI)和应用程序。它功能强大且结构紧凑,拥有直观的工具和库。

1.7 参考文献

1. 钱银,武康,郁李鑫等.基于STM32防丢器设计[J].新型工业化,2020. 
2. 纪一凡,宁闯.电子围栏的应用设计 附视频[J].山西电子技术,2024. 
3. 王俊文.基于MEMS和三重定位的老年人安全报警器的研究与实现[J].智能计算机与应用,2019. 
4. 杨婷,黄韬,谢亮.基于STM32微控制器的智能手环的设计[J].科技广场,2016. 
5. 雷思睿.基于STM32单片机的智慧防丢失系统设计与实现[J].无线互联科技,2020. 
6. 伍永忠.电子安全围栏系统发展现状和市场前景及在国内送变电站的应用[J].中国安防,2008. 
7. 李其元.基于STM32的张力式电子围栏的软硬件开发[D].西南科技大学,2017. 
8. 李梦婷,曳永芳.基于STM32的智能手环系统设计[J].电子质量,2022. 
9. 朱扬,杨延宁,董晨乐等.基于STM32F103C8T6的游乐场智能手环设计 附视频[J].计算机测量与控制,2024. 
10. R. Navarro, M. Angel. “Diseño e implementación de alarma antirrobo independiente, fiable y económica.” (2016). 
11. 焦凤敏,景苏梁,王春柳等.基于STM32的防丢及摔倒报警系统设计与实现[J].信息与电脑(理论版),2022. 
12. 西南交通大学光电工程研究所.基于虚拟仪器及DSP的静电感应式电子围栏设计[J].现代电子技术,2011. 
13. 华南理工大学计算机科学与工程学院.基于STM32的智能家居安防系统设计[J].信息技术,2024. 
14. 毕庆生.基于STM32的围栏报警系统[J].电脑知识与技术,2016. 
15. 中关村硬创空间集团有限公司.一种基于IOT的智能电子围栏设计[J].兵工自动化,2024. 
16. 王春妍.电子围栏监控平台的整体概要设计[J].电子世界,2013. 
17. 高原,沈虹.电台电子围栏预警防御系统[J].广播与电视技术,2015. 
18. 刘海忠.电子围栏中心监控平台的设计与开发[D].华中师范大学,2012. 
19. 曾贵苓,叶素娣,王苹.基于STM32单片机的智能手环设计[J].西安文理学院学报(自然科学版),2023. 
20. 北京城市学院.基于STM32防丢器的设计与实现[J].电子技术与软件工程,2016. 
21. 常印,佟强.电子围栏技术在视觉监控报警系统中的应用[J].科技传播,2020. 
22. 李涛.基于STM32的新型家用报警器的研究与实现[D].燕山大学,2016. 
23. 海南医学院.基于STM32的老年人智能健康手环的设计与实现[J].科技与创新,2023. 

1.8 模块的技术详情介绍

【1】Air724UG-4G模块

Air724UG是一款功能强大且广泛应用于物联网(IoT)领域的4G通信模块。它专为低功耗广域网(LPWAN)应用设计,兼具高性能和稳定性,适用于多种物联网终端设备,包括智能表计、移动支付、智能家居、车载电子等场景。该模块支持4G LTE Cat 1网络制式,是一款具备高性价比的无线通信解决方案。

Air724UG这款模块支持LTE FDD网络,能够提供稳定的语音和数据传输服务,并向下兼容2G GSM网络,使得在4G信号弱或不可用的区域仍可正常通信。由于其双网支持能力,这一模块可以灵活适应不同的网络环境,从而更广泛地满足客户需求。

在数据通信方面,Air724UG模块支持SMS(短消息服务)、TCP/UDP、HTTP/HTTPS、MQTT等协议,为用户开发与应用提供了多种可选方案。其良好的传输能力,能够满足物联网设备对数据可靠性、响应速度等方面的严苛需求。这使其在多种行业和领域中得到了广泛应用,工业自动化、智能物流、移动支付等。模块具备高效的数据传输和低延迟特性,是许多物联网解决方案中的理想选择。

Air724UG模块在设计上注重低功耗特性,这在许多长期依赖电池供电的IoT设备中显得尤为重要。模块支持深度睡眠模式和待机模式,有效降低功耗,延长设备的使用寿命。此外,Air724UG的尺寸较为紧凑,提供易于集成的设计,能够在有限的空间内实现灵活部署,适应各种复杂应用场景。

在接口和硬件配置方面,Air724UG-4G模块集成了丰富的接口,包括UART、I2C、SPI、ADC、GPIO等,为用户提供了极大的开发灵活性。此外,模块还具备支持多种通信协议和功能的AT指令集,便于用户进行功能扩展和定制。模块的工作温度范围广,能够在严苛的环境下保持稳定性能,使其在工业、户外和其他环境条件变化较大的场景中表现出色。

综合而言,Air724UG模块是一款兼顾高性能与灵活性的4G模块,专注于物联网应用的低功耗和高稳定性需求。它的多网络支持、强大的数据传输能力、低功耗特性以及灵活的硬件接口设计,使其成为物联网设备开发中备受青睐的选择。

【2】MQTT协议

MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议)是一种轻量级、发布/订阅模式的消息传输协议,专为低带宽、不可靠网络环境设计。它最早由IBM提出,现已成为物联网(IoT)通信的重要协议之一。由于其高效、低功耗和实时性等特点,MQTT在智能家居、工业自动化、远程监控和车联网等领域得到了广泛应用。

MQTT的工作原理基于发布/订阅模型。这种模型有别于传统的客户端-服务器模型,通信方不需要直接建立连接。MQTT由三个核心组件构成:客户端、代理(Broker)和主题(Topic)。客户端可以作为消息的发布者或订阅者,消息通过代理进行路由。代理是一个中间服务端,用于接收和分发来自不同客户端的消息。发布者发送消息到一个特定的主题上,代理负责将这些消息分发给所有订阅了该主题的客户端。通过这种解耦的架构设计,客户端之间可以实现松耦合的通信,降低了复杂性和依赖性。

在MQTT协议中,消息被分为不同的主题(Topic),例“home/sensor/temperature”可以用来代表温度传感器数据。客户端可以订阅这个主题,当发布者发送新的数据到该主题时,所有订阅该主题的客户端都会收到更新信息。这种灵活的主题结构和层次化的命名规则,使得MQTT在复杂场景下也能快速组织和管理消息流。

MQTT协议支持三种服务质量(QoS)等级,分别为“至多一次”(QoS 0)、“至少一次”(QoS 1)和“仅一次”(QoS 2)。QoS 0表示消息传输尽力而为,可能会丢失或重复;QoS 1确保消息至少送达一次,但可能会有重复;QoS 2则确保消息恰好传输一次,保证消息的严格可靠性。这种设计使MQTT能够适应不同的应用场景,用户可以根据应用需求选择合适的QoS级别。

为了保证通信的安全性,MQTT支持用户名和密码验证,代理可以对连接进行身份认证。此外,许多实现中还支持TLS/SSL加密通信,确保数据在传输过程中不会被窃取或篡改。用户也可以使用不同的认证方式来增强系统的安全性,适应物联网应用中对安全性的高需求。

MQTT非常注重轻量化和低功耗。它的报文头非常小,通信开销很低,这使其特别适合在资源受限的设备或不稳定的网络环境中使用。MQTT支持“保持连接”和“遗嘱消息”功能,客户端可以在连接断开时自动向代理发送遗嘱消息,通知其他客户端连接状态的变化。这种特性有助于提高网络的健壮性和系统的可用性。

MQTT的典型使用场景包括物联网设备数据采集、实时监控、消息推送和控制命令的发布。比在智能家居中,传感器可以发布环境数据,温湿度、烟雾浓度等,控制设备根据收到的消息作出响应,实现自动化操作。在工业场景中,MQTT可以帮助收集和管理大规模设备的运行状态,实现集中化和高效的设备监控。

总的来说,MQTT协议凭借其低功耗、高效能、实时性强等优势,已成为物联网通信的主要协议之一。它的发布/订阅模式简化了设备之间的通信,使其特别适合多对多、低延迟、高可靠性的数据传输场景。MQTT易于使用、拓展性强,为开发者提供了灵活的解决方案来构建各种物联网应用。

【3】中科微ATGM336H-GPS模块

中科微ATGM336H-GPS模块是一款高性能、低功耗的全球定位模块,专为卫星定位导航应用设计。该模块集成了GNSS基带处理器和RF接收器,支持GPS、GLONASS、BDS(北斗)等多种卫星系统的定位信号,能够实现快速精准的定位,并提供稳定可靠的位置、速度和时间数据。ATGM336H模块广泛应用于车辆定位、物流跟踪、无人机导航、智能穿戴设备、户外运动设备和物联网等领域。

ATGM336H模块采用小巧的LCC封装,尺寸为16mm x 12.2mm x 2.3mm,便于集成到各种紧凑型设备中。模块内置高灵敏度接收芯片,具有-165dBm的高灵敏度,即使在复杂环境下也能快速捕获和跟踪卫星信号。其冷启动时间在开阔地带一般小于30秒,热启动时间约为1秒,重捕获时间小于1秒,使其在车辆移动和各种快速切换的场景下表现出色,定位精度可达2.5米。

该模块支持多种工作模式,以满足不同应用的功耗要求。它不仅可以在普通模式下连续定位,还支持周期性模式和节电模式,通过关闭部分功能或降低数据输出频率来减少功耗,适合电池供电的便携式设备。其最低功耗在微安级别,能够显著延长电池续航时间,使其成为移动设备的理想选择。

ATGM336H-GPS模块的接口丰富,支持UART、I2C、SPI等多种通信接口,方便与主控MCU进行数据交换。模块提供的标准NMEA协议输出和二进制格式数据能够直接对接多种导航应用程序。此外,模块还具有内置的天线检测功能和动态干扰抑制技术,有助于在有较强电磁干扰的环境中保持定位精度,并能实时检测和报告天线状态,进一步提高定位可靠性。

为了提高用户体验和简化开发过程,中科微为ATGM336H模块提供了完善的开发手册和技术支持,便于开发者快速上手并将其应用到多种设备中。此外,模块还支持多卫星系统协同定位的功能,通过融合GPS、BDS、GLONASS等卫星数据,提高在市区、高山、森林等卫星信号受限环境下的定位精度和稳定性,使其适用于复杂环境的高精度定位需求。

【4】MPU6050模块

MPU6050是一款高度集成的运动处理单元,它结合了三轴加速度计、三轴陀螺仪以及数字运动处理器(DMP),使其成为众多小型化电子设备的理想选择,尤其是在需要进行精确运动跟踪的应用场景中。MPU6050由InvenSense公司设计制造,广泛应用于智能手机、平板电脑、游戏控制器、无人机以及各种可穿戴设备当中。

MPU6050内部的三轴加速度计可以测量物体沿X、Y、Z三个方向上的线性加速度变化,这对于判断设备是否在移动以及移动的方向非常有用。例,在健身追踪器中,加速度计可以帮助计算步数;而在遥控飞行器或机器人导航中,则可以用来估计位置变化。此外,该加速度计还能感知重力方向,从而确定设备的姿态,比设备是处于水平放置还是垂直放置的状态。

三轴陀螺仪则是用来测量绕X、Y、Z轴旋转的角速度。与加速度计相比,陀螺仪更擅长于捕捉短时间内的快速转动动作,对于维持稳定的姿态控制至关重要。在诸虚拟现实头盔这样的应用里,陀螺仪能够快速响应头部的转动,从而提供流畅无延迟的视觉体验。同样,在无人机的姿态稳定算法中,陀螺仪也是不可或缺的一部分。

MPU6050还包含了数字运动处理器(DMP),这是一个专门处理来自加速度计和陀螺仪原始数据的小型处理器。DMP可以在不占用主控制器资源的情况下执行复杂的运动处理任务,比融合来自不同传感器的数据以提高精度,或者是执行一些基本的动作识别算法。这意味着,即便是在性能较低的微控制器上,也可以通过MPU6050实现高质量的运动感知功能。

通信方面,MPU6050使用I2C或SPI总线与主机进行数据交换。这两种串行通信协议都非常适合于低功耗、低成本的设计需求。其中,I2C接口因为其简单的两线制设计而更为常用,但当需要更高的数据传输速率时,则可以选择SPI接口。

由于其紧凑的封装尺寸、低功耗特性和良好的性价比,MPU6050成为了许多消费电子产品和专业级运动分析工具中的首选组件。无论是对于开发者还是最终用户而言,MPU6050都提供了一个强大且易用的平台来探索各种基于运动感知的应用。

二、硬件选型(搭建模型参考)

果大家想自己搭建模型,完成这个项目的功能测试。

那么可以看参考下面的部分硬件模块选型。

2.1 STM32开发板

主控CPU采用STM32F103RCT6,这颗芯片包括48 KB SRAM、256 KB Flash、2个基本定时器、4个通用定时器、2个高级定时器、51个通用IO口、5个串口、2个DMA控制器、 3个SPI、2个I2C、1个USB、1个CAN、3个12位ADC、1个12位DAC、1个SDIO接口,芯片属于大容量类型,配置较高,整体符合硬件选型设计。当前选择的这款开发板自带了一个1.4寸的TFT-LCD彩屏,可以显示当前传感器数据以及一些运行状态信息。

2.2 蜂鸣器模块

2.3 OLED显示屏

选择7针SPI接口的0.96寸OLED显示屏。

2.4 GPS模块

2.5 MPU6050陀螺仪

三、部署华为云物联网平台

华为云官网: https://www.huaweicloud.com/

打开官网,搜索物联网,就能快速找到 设备接入IoTDA

3.1 物联网平台介绍

华为云物联网平台(IoT 设备接入云服务)提供海量设备的接入和管理能力,将物理设备联接到云,支撑设备数据采集上云和云端下发命令给设备进行远程控制,配合华为云其他产品,帮助快速构筑物联网解决方案。

使用物联网平台构建一个完整的物联网解决方案主要包括3部分:物联网平台、业务应用和设备。

物联网平台作为连接业务应用和设备的中间层,屏蔽了各种复杂的设备接口,实现设备的快速接入;同时提供强大的开放能力,支撑行业用户构建各种物联网解决方案。

设备可以通过固网、2G/3G/4G/5G、NB-IoT、Wifi等多种网络接入物联网平台,并使用LWM2M/CoAP、MQTT、HTTPS协议将业务数据上报到平台,平台也可以将控制命令下发给设备。

业务应用通过调用物联网平台提供的API,实现设备数据采集、命令下发、设备管理等业务场景。

3.2 开通物联网服务

地址:https://www.huaweicloud.com/product/iothub.html

开通免费单元。

点击立即创建

正在创建标准版实例,需要等待片刻。

创建完成之后,点击详情。可以看到标准版实例的设备接入端口和地址。

下面框起来的就是端口号域名

点击实例名称,可以查看当前免费单元的配置情况。

开通之后,点击接入信息,也能查看接入信息。当前设备准备采用MQTT协议接入华为云平台,这里可以看到MQTT协议的地址和端口号等信息。

总结:

端口号:   MQTT (1883)| MQTTS (8883)    
接入地址:dab1a1f2c6.st1.iotda-device.cn-north-4.myhuaweicloud.com

根据域名地址得到IP地址信息:

打开Windows电脑的命令行控制台终端,使用ping 命令。ping一下即可。

Microsoft Windows [版本 10.0.19045.5011]
(c) Microsoft Corporation。保留所有权利。

C:\Users\Lenovo>ping dab1a1f2c6.st1.iotda-device.cn-north-4.myhuaweicloud.com

正在 Ping dab1a1f2c6.st1.iotda-device.cn-north-4.myhuaweicloud.com [117.78.5.125] 具有 32 字节的数据:
来自 117.78.5.125 的回复: 字节=32 时间=37ms TTL=44
来自 117.78.5.125 的回复: 字节=32 时间=37ms TTL=44
来自 117.78.5.125 的回复: 字节=32 时间=37ms TTL=44
来自 117.78.5.125 的回复: 字节=32 时间=37ms TTL=44

117.78.5.125 的 Ping 统计信息:
    数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
    最短 = 37ms,最长 = 37ms,平均 = 37ms

C:\Users\Lenovo>

MQTT协议接入端口号有两个,1883是非加密端口,8883是证书加密端口,单片机无法加载证书,所以使用1883端口合适

3.3 创建产品

链接:https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-dev/all-product?instanceId=03c5c68c-e588-458c-90c3-9e4c640be7af

(1)创建产品

(2)填写产品信息

根据自己产品名字填写,下面的设备类型选择自定义类型。

(3)产品创建成功

创建完成之后点击查看详情。

(4)添加自定义模型

产品创建完成之后,点击进入产品详情页面,翻到最下面可以看到模型定义。

模型简单来说:就是存放设备上传到云平台的数据。

你可以根据自己的产品进行创建。

比:

烟雾可以叫  MQ2
温度可以叫  Temperature
湿度可以叫  humidity
火焰可以叫  flame
其他的传感器自己用单词简写命名即可。 这就是你的单片机设备端上传到服务器的数据名字。

先点击自定义模型。

再创建一个服务ID。

接着点击新增属性。

3.4 添加设备

产品是属于上层的抽象模型,接下来在产品模型下添加实际的设备。添加的设备最终需要与真实的设备关联在一起,完成数据交互。

(1)注册设备

(2)根据自己的设备填写

(3)保存设备信息

创建完毕之后,点击保存并关闭,得到创建的设备密匙信息。该信息在后续生成MQTT三元组的时候需要使用。

(4)设备创建完成

(5)设备详情

3.5 MQTT协议主题订阅与发布

(1)MQTT协议介绍

当前的设备是采用MQTT协议与华为云平台进行通信。

MQTT是一个物联网传输协议,它被设计用于轻量级的发布/订阅式消息传输,旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务。MQTT是专门针对物联网开发的轻量级传输协议。MQTT协议针对低带宽网络,低计算能力的设备,做了特殊的优化,使得其能适应各种物联网应用场景。目前MQTT拥有各种平台和设备上的客户端,已经形成了初步的生态系统。

MQTT是一种消息队列协议,使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合,相对于其他协议,开发更简单;MQTT协议是工作在TCP/IP协议上;由TCP/IP协议提供稳定的网络连接;所以,只要具备TCP协议栈的网络设备都可以使用MQTT协议。本次设备采用的ESP8266就具备TCP协议栈,能够建立TCP连接,所以,配合STM32代码里封装的MQTT协议,就可以与华为云平台完成通信。

华为云的MQTT协议接入帮助文档在这里: https://support.huaweicloud.com/devg-iothub/iot_02_2200.html

业务流程:

(2)华为云平台MQTT协议使用限制

描述限制
支持的MQTT协议版本3.1.1
与标准MQTT协议的区别支持Qos 0和Qos 1支持Topic自定义不支持QoS2不支持will、retain msg
MQTTS支持的安全等级采用TCP通道基础 + TLS协议(最高TLSv1.3版本)
单帐号每秒最大MQTT连接请求数无限制
单个设备每分钟支持的最大MQTT连接数1
单个MQTT连接每秒的吞吐量,即带宽,包含直连设备和网关3KB/s
MQTT单个发布消息最大长度,超过此大小的发布请求将被直接拒绝1MB
MQTT连接心跳时间建议值心跳时间限定为30至1200秒,推荐设置为120秒
产品是否支持自定义Topic支持
消息发布与订阅设备只能对自己的Topic进行消息发布与订阅
每个订阅请求的最大订阅数无限制

(3)主题订阅格式

帮助文档地址:https://support.huaweicloud.com/devg-iothub/iot_02_2200.html

对于设备而言,一般会订阅平台下发消息给设备 这个主题。

设备想接收平台下发的消息,就需要订阅平台下发消息给设备 的主题,订阅后,平台下发消息给设备,设备就会收到消息。

果设备想要知道平台下发的消息,需要订阅上面图片里标注的主题。

以当前设备为例,最终订阅主题的格式下:
$oc/devices/{device_id}/sys/messages/down
    
最终的格式:
$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down

(4)主题发布格式

对于设备来说,主题发布表示向云平台上传数据,将最新的传感器数据,设备状态上传到云平台。

这个操作称为:属性上报。

帮助文档地址:https://support.huaweicloud.com/usermanual-iothub/iot_06_v5_3010.html

根据帮助文档的介绍, 当前设备发布主题,上报属性的格式总结下:

发布的主题格式:
$oc/devices/{device_id}/sys/properties/report
 
最终的格式:
$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report
发布主题时,需要上传数据,这个数据格式是JSON格式。

上传的JSON数据格式下:

{
  "services": [
    {
      "service_id": <填服务ID>,
      "properties": {
        "<填属性名称1>": <填属性值>,
        "<填属性名称2>": <填属性值>,
        ..........
      }
    }
  ]
}
根据JSON格式,一次可以上传多个属性字段。 这个JSON格式里的,服务ID,属性字段名称,属性值类型,在前面创建产品的时候就已经介绍了,不记得可以翻到前面去查看。

根据这个格式,组合一次上传的属性数据:
{"services": [{"service_id""stm32","properties":{"你的字段名字1":30,"你的字段名字2":10,"你的字段名字3":1,"你的字段名字4":0}}]}

3.6 MQTT三元组

MQTT协议登录需要填用户ID,设备ID,设备密码等信息,就像平时登录QQ,微信一样要输入账号密码才能登录。MQTT协议登录的这3个参数,一般称为MQTT三元组。

接下来介绍,华为云平台的MQTT三元组参数何得到。

(1)MQTT服务器地址

要登录MQTT服务器,首先记得先知道服务器的地址是多少,端口是多少。

帮助文档地址:https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-portal/home

MQTT协议的端口支持1883和8883,它们的区别是:8883 是加密端口更加安全。但是单片机上使用比较困难,所以当前的设备是采用1883端口进连接的。

根据上面的域名和端口号,得到下面的IP地址和端口号信息: 果设备支持填写域名可以直接填域名,不支持就直接填写IP地址。(IP地址就是域名解析得到的)

华为云的MQTT服务器地址:117.78.5.125
华为云的MQTT端口号:1883

何得到IP地址?何域名转IP?打开Windows的命令行输入以下命令。

ping  ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com

(2)生成MQTT三元组

华为云提供了一个在线工具,用来生成MQTT鉴权三元组:https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/

打开这个工具,填入设备的信息(也就是刚才创建完设备之后保存的信息),点击生成,就可以得到MQTT的登录信息了。

下面是打开的页面:

填入设备的信息: (上面两行就是设备创建完成之后保存得到的)

直接得到三元组信息。

得到三元组之后,设备端通过MQTT协议登录鉴权的时候,填入参数即可。

ClientId  663cb18871d845632a0912e7_dev1_0_0_2024050911
Username  663cb18871d845632a0912e7_dev1
Password  71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac237

3.7 模拟设备登录测试

经过上面的步骤介绍,已经创建了产品,设备,数据模型,得到MQTT登录信息。接下来就用MQTT客户端软件模拟真实的设备来登录平台。测试与服务器通信是否正常。

(1)填入登录信息

打开MQTT客户端软件,对号填入相关信息(就是上面的文本介绍)。然后,点击登录,订阅主题,发布主题。

(2)打开网页查看

完成上面的操作之后,打开华为云网页后台,可以看到设备已经在线了。

点击详情页面,可以看到上传的数据:

到此,云平台的部署已经完成,设备已经可以正常上传数据了。

(3)MQTT登录测试参数总结

MQTT服务器:  117.78.5.125
MQTT端口号:  183

//物联网服务器的设备信息
#define MQTT_ClientID "663cb18871d845632a0912e7_dev1_0_0_2024050911"
#define MQTT_UserName "663cb18871d845632a0912e7_dev1"
#define MQTT_PassWord "71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac237"

//订阅与发布的主题
#define SET_TOPIC  "$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down"  //订阅
#define POST_TOPIC "$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report"  //发布


发布的数据:
{"services": [{"service_id""stm32","properties":{"你的字段名字1":30,"你的字段名字2":10,"你的字段名字3":1,"你的字段名字4":0}}]}

3.8 创建IAM账户

创建一个IAM账户,因为接下来开发上位机,需要使用云平台的API接口,这些接口都需要token进行鉴权。简单来说,就是身份的认证。调用接口获取Token时,就需要填写IAM账号信息。所以,接下来演示一下过程。

地址: https://console.huaweicloud.com/iam/?region=cn-north-4#/iam/users

**【1】获取项目凭证 ** 点击左上角用户名,选择下拉菜单里的我的凭证

项目凭证:

28add376c01e4a61ac8b621c714bf459

【2】创建IAM用户

鼠标放在左上角头像上,在下拉菜单里选择统一身份认证

点击左上角创建用户

创建成功:

【3】创建完成

用户信息下:

主用户名  l19504562721
IAM用户  ds_abc
密码     DS12345678

3.9 获取影子数据

帮助文档:https://support.huaweicloud.com/api-iothub/iot_06_v5_0079.html

设备影子介绍:

设备影子是一个用于存储和检索设备当前状态信息的JSON文档。
每个设备有且只有一个设备影子,由设备ID唯一标识
设备影子仅保存最近一次设备的上报数据和预期数据
无论该设备是否在线,都可以通过该影子获取和设置设备的属性

简单来说:设备影子就是保存,设备最新上传的一次数据。

设计的软件里,果想要获取设备的最新状态信息,就采用设备影子接口。

果对接口不熟悉,可以先进行在线调试:https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=ShowDeviceShadow

在线调试接口,可以请求影子接口,了解请求,与返回的数据格式。

调试完成看右下角的响应体,就是返回的影子数据。

设备影子接口返回的数据下:

{
 "device_id""663cb18871d845632a0912e7_dev1",
 "shadow": [
  {
   "service_id""stm32",
   "desired": {
    "properties": null,
    "event_time": null
   },
   "reported": {
    "properties": {
     "data1"18,
     "data2"90,
     "data3"38,
     "data4"70
    },
    "event_time""20240509T113448Z"
   },
   "version"3
  }
 ]
}

调试成功之后,可以得到访问影子数据的真实链接,接下来的代码开发中,就采用Qt写代码访问此链接,获取影子数据,完成上位机开发。

链接下:

https://ad635970a1.st1.iotda-app.cn-north-4.myhuaweicloud.com:443/v5/iot/28add376c01e4a61ac8b621c714bf459/devices/663cb18871d845632a0912e7_dev1/shadow

3.10 访问接口的代码实现

(1)配置 Qt 项目

在 Qt 项目的 .pro 文件中,加入对 libcurl 的支持:

QT += core
CONFIG += console
CONFIG -= app_bundle

INCLUDEPATH += /usr/include/curl  # 根据你的系统设置 libcurl 的路径
LIBS += -lcurl  # 链接 libcurl 库

SOURCES += main.cpp

(2)代码实现

main.cpp 文件中实现代码如下:

#include <QCoreApplication>
#include <curl/curl.h>
#include <QDebug>
#include <QString>
#include <QByteArray>

// 回调函数,处理libcurl下载数据
size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t totalSize = size * nmemb;
    QByteArray *response = static_cast<QByteArray *>(userp);
    response->append(static_cast<char *>(contents), totalSize);
    return totalSize;
}

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    // 初始化libcurl
    CURL *curl;
    CURLcode res;
    QByteArray responseData;  // 用于存储响应数据

    curl_global_init(CURL_GLOBAL_DEFAULT);
    curl = curl_easy_init();
    if (curl) {
        // 设置访问URL
        const QString url = "https://ad635970a1.st1.iotda-app.cn-north-4.myhuaweicloud.com:443/v5/iot/28add376c01e4a61ac8b621c714bf459/devices/663cb18871d845632a0912e7_dev1/shadow";

        // 设置HTTP请求头
        struct curl_slist *headers = NULL;
        headers = curl_slist_append(headers, "Authorization: Bearer <Your_Access_Token>"); // 这里需要替换为你的实际 token

        curl_easy_setopt(curl, CURLOPT_URL, url.toStdString().c_str());
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);

        // 发起GET请求
        res = curl_easy_perform(curl);

        if (res != CURLE_OK) {
            qDebug() << "Curl request failed:" << curl_easy_strerror(res);
        } else {
            qDebug() << "Response data:" << responseData;
        }

        // 清理
        curl_easy_cleanup(curl);
        curl_slist_free_all(headers);
    }

    curl_global_cleanup();

    return a.exec();
}

3.11 数据解析代码

在 Qt 中使用 CJSON (一个用于解析 JSON 数据的轻量级 C 库) 来解析返回的 JSON 数据。

(1)配置 Qt 项目

在 Qt 项目的 .pro 文件中,确保包括了 CJSON 的头文件,并链接 CJSON 的源代码。

QT += core
CONFIG += console
CONFIG -= app_bundle

SOURCES += main.cpp \
           cJSON.c  # 将 cJSON.c 文件添加到你的项目中

INCLUDEPATH += path/to/cjson/  # 添加 CJSON 头文件的路径

LIBS += -lcurl  # 链接 libcurl 库

(2)解析 JSON 数据的完整代码

在 main.cpp 中,以下代码展示了如何解析你提供的 JSON 数据。

#include <QCoreApplication>
#include <curl/curl.h>
#include <QDebug>
#include <QString>
#include <QByteArray>
#include "cJSON.h"

// 回调函数,处理libcurl下载数据
size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) {
    size_t totalSize = size * nmemb;
    QByteArray *response = static_cast<QByteArray *>(userp);
    response->append(static_cast<char *>(contents), totalSize);
    return totalSize;
}

// 解析 JSON 数据
void parseJson(const QByteArray &data) {
    // 将 QByteArray 转换为 char*
    const char* jsonData = data.constData();

    // 解析 JSON
    cJSON *root = cJSON_Parse(jsonData);
    if (root == NULL) {
        qDebug() << "Error parsing JSON.";
        return;
    }

    // 解析 "device_id"
    cJSON *deviceId = cJSON_GetObjectItemCaseSensitive(root, "device_id");
    if (cJSON_IsString(deviceId) && (deviceId->valuestring != NULL)) {
        qDebug() << "Device ID:" << deviceId->valuestring;
    }

    // 解析 "shadow" 数组
    cJSON *shadow = cJSON_GetObjectItemCaseSensitive(root, "shadow");
    if (cJSON_IsArray(shadow)) {
        cJSON *shadowItem = NULL;
        cJSON_ArrayForEach(shadowItem, shadow) {
            // 解析每个 shadow 项目
            cJSON *serviceId = cJSON_GetObjectItemCaseSensitive(shadowItem, "service_id");
            if (cJSON_IsString(serviceId) && (serviceId->valuestring != NULL)) {
                qDebug() << "Service ID:" << serviceId->valuestring;
            }

            // 解析 "reported" 对象
            cJSON *reported = cJSON_GetObjectItemCaseSensitive(shadowItem, "reported");
            if (cJSON_IsObject(reported)) {
                // 解析 "properties" 对象
                cJSON *properties = cJSON_GetObjectItemCaseSensitive(reported, "properties");
                if (cJSON_IsObject(properties)) {
                    cJSON *data1 = cJSON_GetObjectItemCaseSensitive(properties, "data1");
                    if (cJSON_IsNumber(data1)) {
                        qDebug() << "data1:" << data1->valueint;
                    }
                    cJSON *data2 = cJSON_GetObjectItemCaseSensitive(properties, "data2");
                    if (cJSON_IsNumber(data2)) {
                        qDebug() << "data2:" << data2->valueint;
                    }
                    cJSON *data3 = cJSON_GetObjectItemCaseSensitive(properties, "data3");
                    if (cJSON_IsNumber(data3)) {
                        qDebug() << "data3:" << data3->valueint;
                    }
                    cJSON *data4 = cJSON_GetObjectItemCaseSensitive(properties, "data4");
                    if (cJSON_IsNumber(data4)) {
                        qDebug() << "data4:" << data4->valueint;
                    }
                }

                // 解析 "event_time"
                cJSON *eventTime = cJSON_GetObjectItemCaseSensitive(reported, "event_time");
                if (cJSON_IsString(eventTime) && (eventTime->valuestring != NULL)) {
                    qDebug() << "Event Time:" << eventTime->valuestring;
                }
            }

            // 解析 version
            cJSON *version = cJSON_GetObjectItemCaseSensitive(shadowItem, "version");
            if (cJSON_IsNumber(version)) {
                qDebug() << "Version:" << version->valueint;
            }
        }
    }

    // 释放 JSON 对象
    cJSON_Delete(root);
}

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    // 模拟获取到的 JSON 数据
    QByteArray jsonData = R"(
    {
        "device_id": "663cb18871d845632a0912e7_dev1",
        "shadow": [
            {
                "service_id": "stm32",
                "desired": {
                    "properties": null,
                    "event_time": null
                },
                "reported": {
                    "properties": {
                        "data1": 18,
                        "data2": 90,
                        "data3": 38,
                        "data4": 70
                    },
                    "event_time": "20240509T113448Z"
                },
                "version": 3
            }
        ]
    })"
;

    // 调用解析函数
    parseJson(jsonData);

    return a.exec();
}

四、STM32设备端代码设计

4.1 硬件连线

以下是各模块与STM32单片机之间的具体连线、引脚连接和电压要求的详细描述。

(1)STM32F103RCT6 主控芯片

STM32F103RCT6是本项目的核心控制单元,负责处理传感器数据、控制显示屏、发出报警信号、进行通信等。

以下是各模块与STM32F103RCT6的具体连接说明:

  • • 电源:STM32F103RCT6的VDD引脚连接至3.3V电源,GND引脚连接至地(0V)。该单片机支持3.3V的工作电压。

  • • I/O 引脚:STM32F103RCT6具有丰富的I/O接口,可以通过GPIO口、I2C、SPI、UART等与其他模块进行连接。

(2) MPU6050 陀螺仪模块

MPU6050通过I2C协议与STM32连接,用于获取运动数据(加速度、角速度)。模块与STM32的连接方式下:

  • • VCC:连接至3.3V(MPU6050支持3.3V供电)。

  • • GND:连接至地。

  • • SDA(数据线):连接至STM32的I2C1_SDA引脚(PB7)。

  • • SCL(时钟线):连接至STM32的I2C1_SCL引脚(PB6)。

  • • INT(中断线):可连接至STM32的某个GPIO引脚(例PA0),用于中断触发(可选)。

电压:MPU6050支持3.3V供电,连接时应确保供电电压与STM32相匹配。

(3)OLED显示屏(0.96寸 SPI 协议)

OLED显示屏通过SPI协议与STM32进行通信,连接方式下:

  • • VCC:连接至3.3V。

  • • GND:连接至地。

  • • SCK(时钟):连接至STM32的SPI1_SCK引脚(PA5)。

  • • MISO(主输入从输出,虽然OLED不使用此功能,但仍需连接):连接至STM32的SPI1_MISO引脚(PA6,空闲时不使用)。

  • • MOSI(主输出从输入):连接至STM32的SPI1_MOSI引脚(PA7)。

  • • CS(芯片选择):连接至STM32的某个GPIO引脚(PC1),用于选择该SPI设备。

  • • DC(数据/命令选择):连接至STM32的某个GPIO引脚(PC2),用于区分数据和命令。

  • • RST(复位):连接至STM32的某个GPIO引脚(PC3),用于控制OLED复位。

电压:OLED屏幕工作在3.3V电压下,必须确保提供的电压与STM32兼容。

(4)蜂鸣器(高电平触发的有源蜂鸣器)

蜂鸣器通过GPIO控制发出报警声音,连接方式下:

  • • VCC:连接至3.3V(或5V,根据蜂鸣器的工作电压)。

  • • GND:连接至地。

  • • 控制引脚:连接至STM32的某个GPIO引脚(PA8),通过设置该引脚为高电平来驱动蜂鸣器发出声音。

电压:蜂鸣器电压要求为3.3V或5V,具体根据蜂鸣器的型号选择适当的电压。

(5)ATGM336H-GPS模块

GPS模块通过UART与STM32通信,提供位置数据。连接方式下:

  • • VCC:连接至3.3V(部分GPS模块支持5V输入,但建议使用3.3V)。

  • • GND:连接至地。

  • • TX(发送数据):连接至STM32的USART1_RX引脚(PA10),用于接收GPS模块的数据。

  • • RX(接收数据):连接至STM32的USART1_TX引脚(PA9),用于发送数据给GPS模块。

电压:ATGM336H模块支持3.3V或5V电压,建议采用3.3V,避免超出STM32的电压范围。

(6) Air724-4G模块

Air724-4G模块通过UART与STM32通信,实现与云平台的连接。连接方式下:

  • • VCC:连接至3.3V(Air724模块可以支持5V,但为确保与STM32兼容,最好使用3.3V)。

  • • GND:连接至地。

  • • TX(发送数据):连接至STM32的USART2_RX引脚(PA3),用于接收4G模块的数据。

  • • RX(接收数据):连接至STM32的USART2_TX引脚(PA2),用于发送数据给4G模块。

电压:Air724-4G模块一般支持3.3V或5V电压,但要确保与STM32的电压兼容,建议使用3.3V。

(7)锂电池与电池管理模块

  • • 锂电池:一般使用3.7V的可充电锂电池作为电源,连接到电池管理模块。

    • • 电池管理模块(TP4056):负责充电和电池保护。模块输入端接3.7V锂电池,输出端提供3.3V电压给STM32单片机及其他模块。

    • • VCC(电池输出端):连接至STM32和其他模块的3.3V供电引脚。

    • • GND:连接至系统地。

    • • 电池模块有充电和电量指示灯,可以通过GPIO引脚进行监控(可选)。

(8)SOS按钮

SOS按钮通过GPIO引脚进行监控,当用户按下按钮时,触发系统的紧急求助功能。连接方式下:

  • • 一端:连接至STM32的某个GPIO引脚(PA0),用于检测按钮状态。

  • • 另一端:连接至地(GND)。

电压:通过STM32的输入引脚进行检测,不需要单独的电压供给。

4.2 项目代码

下面是项目的伪代码框架。展示整个项目的运行逻辑。

#include "stm32f1xx_hal.h"
#include "mpu6050.h"
#include "gps.h"
#include "oled.h"
#include "buzzer.h"
#include "sms.h"
#include "mqtt.h"
#include "time.h"
#include "air724.h"
#include "gpio.h"

// 全局变量
extern uint32_t step_count;  // 步数
extern GPS_Data gps_data;    // GPS数据
extern uint8_t gps_update_flag;  // GPS数据更新标志
extern uint32_t current_time;    // 当前时间(可能需要根据RTC或其他时间模块同步)

// 函数声明
void SystemClock_Config(void);
void MX_GPIO_Init(void);
void MX_I2C1_Init(void);
void MX_SPI1_Init(void);
void MX_USART1_UART_Init(void);
void MX_USART2_UART_Init(void);
void MX_TIM_Init(void);

// 系统初始化
void System_Init(void)
{
    // HAL库初始化
    HAL_Init();

    // 配置系统时钟
    SystemClock_Config();

    // 初始化GPIO
    MX_GPIO_Init();

    // 初始化I2C (用于MPU6050)
    MX_I2C1_Init();

    // 初始化SPI (用于OLED显示)
    MX_SPI1_Init();

    // 初始化UART (用于GPS和Air724通信)
    MX_USART1_UART_Init();
    MX_USART2_UART_Init();

    // 初始化定时器(如果需要)
    MX_TIM_Init();

    // 初始化其他外设,如蜂鸣器、LCD显示、4G模块等
    OLED_Init();
    Buzzer_Init();
    GPS_Init();
    Air724_Init();
}

// 主循环
int main(void)
{
    // 初始化硬件和外设
    System_Init();

    // 初始化时间(假设通过某种方式获取)
    Time_Init();
    
    // 初始化MQTT连接
    MQTT_Init();

    // 显示启动信息
    OLED_Display_Message("System Start");

    // 主循环
    while (1)
    {
        // 1. 读取运动传感器(MPU6050),更新步数和姿态
        Update_Step_Count();
        Update_Pose();

        // 2. 获取GPS数据
        if (gps_update_flag)
        {
            gps_update_flag = 0;  // 清除更新标志
            Update_GPS_Data();  // 处理GPS数据
        }

        // 3. 实时显示信息
        OLED_Clear();
        OLED_Display_Info(step_count, gps_data.latitude, gps_data.longitude, current_time);

        // 4. 电子围栏报警(如果超出指定区域)
        if (Check_Geofence(gps_data.latitude, gps_data.longitude))
        {
            // 触发报警(蜂鸣器和短信通知)
            Buzzer_On();
            SMS_Send("Warning! Out of Safe Zone!", gps_data.latitude, gps_data.longitude);
            HAL_Delay(3000);  // 蜂鸣器响3秒
            Buzzer_Off();
        }

        // 5. 检测SOS按钮
        if (Check_SOS_Button())
        {
            // 发送紧急求救短信
            SMS_Send("SOS! Help needed.", gps_data.latitude, gps_data.longitude);
            // 激活蜂鸣器报警
            Buzzer_On();
            HAL_Delay(3000);
            Buzzer_Off();
        }

        // 6. 上传数据到云平台(MQTT协议)
        MQTT_Publish("step_count", step_count);
        MQTT_Publish("gps_location", gps_data);

        // 7. 时间校准(根据外部指令校准时间)
        if (Time_Need_Sync())
        {
            Time_Sync(current_time);  // 校准时间
        }
    }
}

// 时钟配置函数
void SystemClock_Config(void)
{
    // 配置系统时钟(根据实际硬件需求设置)
    RCC_OscInitTypeDef RCC_OscInitStruct = {0};
    RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

    // 初始化HSE和PLL
    RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
    RCC_OscInitStruct.HSEState = RCC_HSE_ON;
    RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
    RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
    RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
    HAL_RCC_OscConfig(&RCC_OscInitStruct);

    // 配置系统时钟源
    RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
    RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
    RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
    RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
    RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
    HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2);
}

五、上位机开发

为了方便查看设备上传的数据,接下来利用Qt开发一款Android手机APP 和 Windows上位机。

使用华为云平台提供的API接口获取设备上传的数据,进行可视化显示,以及远程控制设备。

5.1 Qt开发环境安装

Qt的中文官网:https://www.qt.io/zh-cn/![image-20221207160550486](https://led-obs.obs.cn-north-1.myhuaweicloud.com/Blog/img/image-20221207160550486.png)

QT5.12.6的下载地址:https://download.qt.io/archive/qt/5.12/5.12.6

打开下载链接后选择下面的版本进行下载:

果下载不了,可以在网盘里找到安装包下载: https://pan.quark.cn/s/145a9b3f7f53

软件安装时断网安装,否则会提示输入账户。

安装的时候,第一个复选框里的编译器可以全选,直接点击下一步继续安装。

选择编译器:(一定要看清楚了)

前面2讲解了需要用的API接口,接下来就使用Qt设计上位机,设计界面,完成整体上位机的逻辑设计。

【1】新建工程

【2】设置项目的名称。

【3】选择编译系统

【4】选择默认继承的类

【5】选择编译器

【6】点击完成

【7】工程创建完成

5.3 切换编译器

在左下角是可以切换编译器的。可以选择用什么样的编译器编译程序。

目前新建工程的时候选择了2种编译器。一种是mingw32这个编译Windows下运行的程序。一种是Android编译器,可以生成Android手机APP。

不过要注意:Android的编译器需要配置一些环境才可以正常使用,这个大家可以看下面的教程配置一下就行了。

Android环境搭建的博客链接: https://blog.csdn.net/xiaolong1126626497/article/details/117254453

windows的编译器就没有这么麻烦,安装好Qt就可以编译使用。

下面我这里就选择的 mingw32这个编译器,编译Windows下运行的程序。

5.4 编译测试功能

创建完毕之后,编译测试一下功能是否OK。

点击左下角的绿色三角形按钮

正常运行就可以看到弹出一个白色的框框。这就表示工程环境没有问题了。接下来就可以放心的设计界面了。

5.5 设计UI界面与工程配置

【1】打开UI文件

打开默认的界面下:

【2】开始设计界面

根据自己需求设计界面。

5.5 编译Windows上位机

点击软件左下角的绿色三角形按钮进行编译运行。

5.6 配置Android环境

果想编译Android手机APP,必须要先自己配置好自己的Android环境。(搭建环境的过程可以自行百度搜索学习)

然后才可以进行下面的步骤。

【1】选择Android编译器

选择编译器。

切换编译器。

【2】创建Android配置文件

创建完成。

【3】配置Android图标与名称

【3】编译Android上位机

Qt本身是跨平台的,直接选择Android的编译器,就可以将程序编译到Android平台。

然后点击构建。

成功之后,在目录下可以看到生成的apk文件,也就是Android手机的安装包,电脑端使用QQ发送给手机QQ,手机登录QQ接收,就能直接安装。

生成的apk的目录在哪里呢?编译完成之后,在控制台会输出APK文件的路径。

知道目录在哪里之后,在Windows的文件资源管理器里,找到路径,具体看下图,找到生成的apk文件。

  -- File: D:/QtProject/build-265_AgritechIoTManager-Android_for_arm64_v8a_Clang_Qt_5_12_6_for_Android_ARM64_v8a-Release/android-build//build/outputs/apk/debug/android-build-debug.apk

六、总结

本文介绍了一种基于STM32微控制器设计的防丢手环电子围栏报警系统。该系统整合了多种传感器技术与无线通信手段,为用户提供全面的安全保障和个人健康管理方案。主要功能包括实时运动姿态检测与步数记录、通过0.96寸OLED显示屏显示相关信息(如时间、GPS状态)、紧急情况下通过SOS按键自动发送求助短信、支持手机APP远程时间校准及电子围栏设定等功能。此外,系统还利用4G模块和MQTT协议将数据上传至华为云IoT平台,并通过百度地图API实现电子围栏的可视化展示。整体设计方案注重用户体验,力求在健康管理与安全保障之间找到最佳平衡点。


DS小龙哥 嵌入式技术资讯
不定时更新STM32、物联网、linux驱动、QT等技术文章;打造嵌入式开发相关知识分享、技术交流平台
 最新文章