• 方案介绍
  • 附件下载
  • 相关推荐
申请入驻 产业图谱

基于STM32单片机设计的土壤质量监测系统

06/12 10:18
1358
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

更多详细资料请联系.docx

共1个文件

一、前言

1.1 项目介绍

【1】项目开发背景

随着现代农业的快速发展,传统依赖经验的耕作方式已逐渐无法满足精细化、智能化种植的需求。农业生产中土壤作为植物生长的基础,其质量直接关系到作物的产量与品质。因此,对土壤质量的实时监测和分析成为农业现代化管理中的关键环节。尤其是在温室种植、精准农业以及设施农业等场景中,对土壤湿度、温度、PH值以及氮磷钾等化学元素的含量进行有效监测,有助于科学施肥与灌溉,从而实现水肥资源的优化配置,提高农业产出效率,降低环境污染。

近年来,随着物联网传感器技术嵌入式系统以及无线通信的不断发展,将这些先进技术与农业环境监测相结合,为农业信息化建设提供了新的手段。尤其是STM32单片机以其高性能、低功耗、丰富的外设接口等特点,成为农业智能设备开发的理想平台。通过集成多种传感器模块,实现对土壤温湿度、PH值、氮磷钾等关键参数的综合采集,为农业决策提供科学依据。

在本项目中,系统基于STM32F103C8T6单片机设计,配备多功能土壤质量传感器、环境温湿度传感器光照强度检测模块、自动灌溉控制模块等关键硬件,实现对农业环境中土壤与气候条件的实时监测与管理。系统采用OLED显示屏进行本地信息展示,同时配置蜂鸣器对异常情况进行实时报警,便于现场运维人员及时干预。

此外,为实现远程数据查看与分析,系统集成了Air780e 4G通信模块,通过MQTT协议与华为云IoT物联网平台进行数据通信。平台可对来自多个终端的监测数据进行集中管理,实现不同种植区域设备的分布式部署与统一云端接入。用户可通过Android手机APP或Windows上位机软件远程查看实时参数和历史折线图,全面掌握各类环境变化趋势,提升管理的科学性与前瞻性。

为增强系统的实用性与可持续运行能力,设备采用太阳能供电方案,实现全天候不间断监测,适用于缺乏常规电力供应的田间地头或偏远农场。整体系统设计注重低功耗、高集成、易部署的原则,可广泛应用于农业科研试验、设施农业监控、精准农业种植等多个领域,为推动农业智能化转型提供坚实的技术支撑。

image-20250525104502312

image-20250525104426768

image-20250525104524935

【2】设计实现的功能

(1)土壤PH检测功能:通过485接口的多合一土壤质量传感器,实时检测当前土壤的PH值,评估土壤酸碱度,辅助判断土壤是否适合当前作物生长。

(2)土壤温度、湿度检测功能:传感器可同步检测土壤的温度和含水量,结合灌溉逻辑,实现精准水分管理,防止干旱或过湿。

(3)土壤氮磷钾含量检测功能:检测土壤中氮、磷、钾三种关键营养元素的含量,为科学施肥提供数据支持,避免营养过剩或不足。

(4)环境温度、湿度检测功能:采用DHT11传感器监测环境空气的温度和湿度,辅助综合分析种植环境对土壤和作物的影响。

(5)自动灌溉控制功能:系统根据土壤湿度值的实时变化自动判断是否启动灌溉,通过继电器控制5V抽水电机精准补水。

(6)环境光照强度检测功能:通过BH1750光照传感器采集当前环境光强数据,为作物生长光照管理和农业作业时间安排提供参考。

(7)数据上云功能:利用Air780e 4G模块,通过MQTT协议将土壤与环境数据上传至华为云IOT物联网服务器,实现远程数据集中管理。

(8)本地OLED显示功能:使用0.96寸IIC接口OLED显示屏,实时显示采集的土壤和环境参数,便于现场查看。

(9)异常报警功能:系统对PH值、湿度、氮磷钾等参数设定阈值,当监测数据异常时自动触发蜂鸣器报警,提醒用户注意环境变化。

(10)太阳能供电功能:通过太阳能充电板、锂电池及充电管理电路,实现全天候独立供电,适用于无市电或野外种植环境。

(11)多设备部署与独立运行功能:支持多个设备同时部署在不同区域,每个设备作为独立节点采集数据并上传至云端,互不干扰,随插随用。

(12)远程查看与趋势分析功能:通过Android手机APP和Windows上位机软件,用户可远程查看各项实时数据,并可查看温湿度、PH值、氮磷钾含量等参数的历史折线图,辅助分析种植环境变化趋势。

【3】项目硬件模块组成

(1)主控模块(STM32F103C8T6):负责系统各传感器数据的采集、逻辑控制、显示驱动、通信管理等核心处理功能。

(2)土壤质量检测模块(485接口传感器):用于检测土壤的PH值、温度、湿度以及氮、磷、钾三种化学元素的含量,通过RS-485接口与主控进行数据通信。

(3)环境温湿度检测模块(DHT11):用于实时监测空气中的温度和湿度,数据通过单总线接口输入主控芯片

(4)环境光照检测模块(BH1750):采用IIC接口光照强度传感器,检测当前环境的光照强度,为环境分析提供数据支持。

(5)自动灌溉控制模块(继电器+抽水电机):根据土壤湿度自动控制继电器通断,驱动5V抽水电机进行灌溉。

(6)OLED显示模块(0.96寸 IIC OLED):用于显示土壤温湿度、PH值、氮磷钾含量、环境温湿度、光照强度等各项数据。

(7)报警模块(有源蜂鸣器:当检测到环境参数异常(如PH值、湿度等超出设定阈值)时,蜂鸣器自动响起进行本地报警提示。

(8)通信模块(Air780e 4G模块):通过串口与主控连接,使用MQTT协议将采集数据上传至华为云IOT物联网平台,同时支持远程控制指令下发。

(9)电源管理与供电模块(太阳能板+锂电池+充电管理板):太阳能板为锂电池充电,锂电池为系统供电,实现野外无市电情况下的独立供电。

(10)RS-485通信转换模块(TTL转485模块):用于主控STM32与土壤传感器之间的RS-485信号通信转换,确保稳定可靠的数据传输

1.2 设计思路

本系统以STM32F103C8T6单片机作为核心控制器,围绕土壤质量监测与智能管理展开,结合多种传感器模块和通信技术,实现对农业种植环境的全面感知与远程管理。系统设计注重功能的集成性、数据的实用性和部署的灵活性,适用于农业种植中的精准监测需求。

系统采用集成式土壤质量传感器,通过RS-485接口实时采集土壤的PH值、温度、湿度以及氮、磷、钾三种主要养分的含量。这些关键参数为农作物的种植提供科学依据,帮助农户及时掌握土壤肥力和酸碱度等信息,优化施肥和耕种策略。

为了获取更全面的环境信息,系统还集成了DHT11环境温湿度传感器和BH1750光照传感器,分别用于监测空气温湿度和光照强度,进一步辅助分析种植区域的气候条件。这些数据与土壤信息共同构成了完整的环境监测体系。

在执行控制方面,系统依据采集到的土壤湿度值,通过继电器控制抽水电机自动进行灌溉,实现智能补水功能。这一设计不仅提升了灌溉的效率与精准性,也避免了人为误操作和资源浪费。

系统通信模块采用Air780e 4G模块作为数据传输媒介,利用MQTT协议将采集到的各项数据实时上传至华为云IOT物联网服务器,保障数据传输的实时性与可靠性。云平台作为数据中心,支持历史数据存储、趋势分析和远程指令下发。

用户可通过Android手机APP或Windows上位机软件,实时查看土壤和环境的当前数据及历史变化曲线,全面掌握种植区域的情况,实现远程可视化管理。同时,每个设备为独立节点,可部署于不同区域,随插随用,方便扩展。

系统还配备OLED本地显示模块和蜂鸣器报警模块,实现数据的现场可视和异常告警,增强现场运维的直观性和安全性。此外,系统采用太阳能供电,结合锂电池与充电管理电路,确保设备在野外环境下长时间稳定运行。整体设计充分考虑了农业现场的实用性、稳定性与可扩展性。

1.3 系统功能总结

序号 功能名称 功能描述
1 土壤PH值检测 实时监测土壤的酸碱度,通过RS-485接口采集PH值数据。
2 土壤温湿度检测 监测土壤的温度和湿度,反映土壤环境条件,指导灌溉与管理。
3 土壤氮磷钾检测 检测土壤中氮、磷、钾三种营养元素的含量,辅助判断土壤肥力。
4 环境温湿度检测 通过DHT11传感器采集空气中的温度与湿度,了解外部环境变化。
5 自动灌溉控制 根据土壤湿度自动控制继电器开关,启动/关闭抽水电机进行灌溉。
6 环境光照检测 通过BH1750光敏传感器检测环境光照强度,为植物生长和数据分析提供依据。
7 数据本地显示 采用0.96寸OLED显示屏实时显示当前各项土壤和环境数据。
8 异常蜂鸣器报警 当某些检测参数异常(如湿度过低、PH异常)时触发蜂鸣器发出警报提示。
9 数据上传至云平台 利用Air780e模块通过MQTT协议上传数据至华为云IOT物联网平台。
10 手机APP远程查看 用户可通过Android APP实时查看当前数据与历史变化趋势。
11 电脑上位机查看 支持Windows平台Qt上位机软件,查看实时数据与历史曲线,远程控制设备。
12 独立设备部署支持 每个设备独立运行,支持多区域部署,随插随用,灵活采集不同区域数据。
13 太阳能供电 使用太阳能板为锂电池充电,实现系统离网独立供电,适用于野外场景。

1.4 开发工具的选择

【1】设备端开发

硬件设备端的开发主要依赖于C语言,利用该语言直接操作硬件寄存器,确保系统运行的高效性和低延迟。C语言在嵌入式开发中具有广泛的应用,它能够直接访问硬件,满足对资源消耗和响应速度的严格要求。为了编写高效、稳定的代码,开发工具选择了Keil uVision 5作为主要的开发环境。Keil是一个专业的嵌入式开发工具,广泛应用于基于ARM架构微控制器(如STM32)开发。Keil提供了完善的调试、编译和仿真支持,能够帮助在软件开发过程中高效地进行调试、单步执行以及断点设置,确保开发的稳定性和高效性。
STM32F103RCT6是项目中使用的主控芯片,它基于ARM Cortex-M3架构,拥有强大的计算能力和丰富的外设接口。在硬件编程中,寄存器级编程是常用的方式,这要求开发者对芯片的硬件寄存器有深入的理解。在Keil环境中,通过STM32的寄存器直接控制GPIOADCI2CSPI等硬件接口,以满足各个硬件模块(如传感器、执行器、显示屏等)与主控芯片的交互。使用寄存器编程能够提供更高效、精确的控制,避免了外部库的开销,同时也能深入调控硬件特性,提升系统性能。

【2】上位机开发

本项目的上位机开发基于Qt 5框架,使用**C++**作为主要编程语言。Qt是一个跨平台的应用开发框架,广泛用于开发GUI应用程序。Qt提供了丰富的GUI组件和工具,能够高效地实现图形界面的设计与开发。C++则作为Qt的底层语言,具有高效的性能和良好的控制力,非常适合用于处理设备与系统之间的数据交互、通信协议的实现和复杂的计算任务。在项目中,Qt被用于开发Windows平台的桌面应用程序以及Android平台的手机APP。Qt框架的跨平台特性使得开发者能够使用同一套代码在不同操作系统上进行构建和部署,大大提高了开发效率。

为了方便开发和调试,上位机的开发采用了Qt Creator作为主要的集成开发环境(IDE)。Qt Creator是一款由Qt官方提供的开发工具,专为Qt应用程序开发设计,支持C++、QML和JavaScript等语言。Qt Creator提供了丰富的功能,如代码编辑、调试、构建、版本控制集成等,能够显著提升开发者的生产力。在本项目中,Qt Creator为开发者提供了自动化构建、界面设计工具(如Qt Designer)和调试工具(如QDebug和QML调试工具),使得开发过程更加高效和流畅。
上位机与硬件设备端的通信采用了基于TCP/IP协议的数据传输方式。为了实现这一功能,Qt提供了丰富的网络编程支持,尤其是QTcpSocketQTcpServer类,使得上位机能够轻松地与硬件设备建立TCP连接,进行数据收发。上位机通过WIFI连接ESP8266-WIFI模块,ESP8266模块创建TCP服务器,上位机应用则作为客户端连接到服务器,进行实时的数据传输与控制命令的下发。
为了满足不同用户的需求,本项目需要支持Windows平台的桌面应用和Android平台的移动APP。Qt的跨平台特性使得开发人员能够在一个代码库下完成多平台应用的开发和移植。开发者仅需要编写一次应用逻辑和用户界面,就可以通过Qt的跨平台构建工具生成Windows和Android两个平台的可执行文件。此外,Qt提供了丰富的文档和社区支持,帮助开发者解决平台差异和兼容性问题,确保应用在不同平台上都能稳定运行。

总体而言,上位机开发环境采用了Qt 5框架和C++语言,结合Qt Creator集成开发环境,提供了一个高效、稳定、跨平台的开发工具链。通过Qt强大的GUI设计、网络通信、多线程支持以及数据库管理功能,开发者能够轻松实现与硬件设备的交互、控制设备、处理传感器数据,并为用户提供直观、流畅的操作体验。

1.9 模块的技术详情介绍

【1】Aair780模块

Air780E是合宙科技(Luat合宙)推出的一款低功耗、高性能的4G全网通通信模块,广泛应用于物联网设备的数据传输场景中。该模块基于紫光展锐芯片平台,具备优异的通信性能、丰富的外围接口和可靠的运行环境,适用于智慧农业、环境监测、车载设备、工业控制等多种应用领域。

Air780E支持4G LTE Cat.1网络制式,兼容移动、联通、电信三大运营商的网络,具备全国广覆盖、低延迟、高速率的特点,能够满足物联网设备在各种环境下的数据上传与下发需求。对于物联网中的远程控制、云平台数据交互等需求,该模块提供了稳定的蜂窝网络通信保障。

该模块内置Luat OS系统,支持Lua脚本开发,也可以通过AT指令控制,开发灵活便捷,开发者可以快速构建通信逻辑、MQTT协议栈、HTTP请求、TCP/UDP通信等功能。Air780E天然支持MQTT协议,可轻松对接华为云、阿里云、腾讯云等主流物联网平台。

在接口方面,Air780E提供了UART串口通信接口,方便与STM32等主控芯片通信连接。同时模块还支持GPIO、ADC、PWM等常用接口资源,拓展能力强。它的工作电压范围通常为3.4V~4.2V,待机功耗极低,适合太阳能、锂电池等低功耗供电场景。

Air780E是一个功能全面、开发简单、适配性强的4G模块,非常适合用于STM32等嵌入式系统中,用作数据上传、远程通信的核心通信模块。它在土壤质量监测系统中的应用,可以有效实现数据的实时远程上传,提升系统的智能化水平和管理效率。

【2】BH1750模块

BH1750是一款广泛应用于环境光照强度检测的数字光照传感器模块。它采用I²C通信协议,能够方便地与各种微控制器(如STM32)进行数据交换,适合用于智能家居、农业监测、手机屏幕亮度调节等多种应用场景。

该模块内部集成了高灵敏度的光敏传感器和模数转换器,可以直接输出光照强度的数字值,单位为勒克斯(Lux),测量范围通常在1到65535 Lux之间,覆盖从微弱环境光到强烈阳光的广泛光照条件。BH1750的高精度和高分辨率使其能够准确反映环境的光照变化。

BH1750模块的I²C接口简化了硬件连接,仅需两根线(SCL和SDA)即可实现数据通信,支持多主多从通信模式,且通讯速度最高可达400kHz(快速模式),这为系统设计提供了很大便利。模块的工作电压一般为3.3V或5V,功耗较低,适合电池供电的便携设备。

在实际使用中,BH1750能够快速响应环境光线的变化,且具有良好的线性输出特性,使得它能够为光照控制系统、自动调光系统等提供可靠的数据支持。在农业领域,BH1750可以帮助监测光照强度,辅助判断作物的生长环境,从而指导补光设备的启停和调节。

BH1750模块结构简单、精度高、易于集成,是实现环境光照检测的理想选择,能够为土壤质量监测系统提供重要的光照数据支持,帮助系统更全面地感知种植环境。

【3】DHT11模块

DHT11是一款常用的数字温湿度传感器模块,广泛应用于环境监测、智能家居、农业种植等领域。它集成了温度和湿度传感器芯片,并内置了专用的数字信号处理器,能够直接输出经过校准的数字信号,方便微控制器进行读取和处理。

该模块采用单总线数字通信接口,通过一个数据线即可实现与STM32等主控芯片的数据交换,硬件连接简单,软件驱动也较为容易实现。DHT11测量范围适合一般环境需求,温度测量范围为050℃,湿度测量范围为20%90%相对湿度,精度分别为±2℃和±5%RH,满足一般农业环境监测的基本需求。

DHT11响应速度较快,能够实时反映环境温湿度的变化。其内部带有防干扰设计,使得数据传输较为稳定。模块工作电压为3.3V到5V,功耗较低,适合电池供电的嵌入式系统。

虽然DHT11的测量精度和范围相较于高端传感器略有不足,但其成本低廉、体积小巧、使用方便,使其成为许多中低端环境监测项目的首选传感器。在土壤质量监测系统中,DHT11用于检测环境空气的温度和湿度,为系统提供辅助环境数据,帮助实现更全面的环境感知与智能控制。

DHT11模块是一款性价比高、易于集成的温湿度传感器,非常适合用于需要基础环境监测的嵌入式系统。

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

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

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

  1. STM32F103C8T6单片机开发板 —— 作为主控芯片,负责整个系统的控制与数据处理。
  2. 0.96寸IIC接口OLED显示屏 —— 实时显示土壤及环境参数。
  3. Air780E 4G通信模块 —— 用于通过MQTT协议连接华为云IOT服务器,实现远程数据上传和控制。
  4. 土壤质量检测传感器(支持RS485接口) —— 用于检测土壤的温度、湿度、氮磷钾含量和PH值。
  5. DHT11温湿度传感器 —— 用于监测环境空气的温度和湿度。
  6. 继电器模块 —— 用于控制5V抽水电机,实现自动灌溉。
  7. 抽水电机 —— 用于土壤的自动灌溉。
  8. BH1750光照强度传感器模块 —— 用于环境光照强度检测。
  9. 太阳能充电板 —— 太阳能供电系统中的光伏板,为锂电池充电。
  10. 充电管理板(充电控制器) —— 负责太阳能电池板给锂电池充电的管理与保护。
  11. 锂电池组 —— 储存太阳能电能,为系统供电。
  12. 电源管理电路 —— 稳压与保护电路,确保系统稳定运行。
  13. 电源连接线和接口 —— 连接太阳能板、锂电池和系统主板的导线和接口。
  14. RS485通信接口转换模块 —— 用于土壤传感器与STM32单片机之间的通信。
  15. PCB板或实验板 —— 用于硬件电路的焊接和组装。
  16. 蜂鸣器模块 —— 用于异常报警提示。

基于STM32的土壤质量监测系统,上传到华为云IoT平台的数据字段包括以下内容,覆盖系统监测的全部核心参数和状态信息:

  1. soil_pH —— 土壤的pH值
  2. soil_temperature —— 土壤温度(单位:℃)
  3. soil_humidity —— 土壤湿度(单位:%)
  4. soil_nitrogen —— 土壤中氮元素含量(单位:ppm或mg/kg,根据传感器规格)
  5. soil_phosphorus —— 土壤中磷元素含量(单位:ppm或mg/kg)
  6. soil_potassium —— 土壤中钾元素含量(单位:ppm或mg/kg)
  7. environment_temperature —— 环境空气温度(单位:℃)
  8. environment_humidity —— 环境空气湿度(单位:%)
  9. light_intensity —— 环境光照强度(单位:Lux)
  10. water_pump_status —— 自动灌溉状态(如0表示关闭,1表示开启)
  11. device_id —— 设备唯一标识,用于区分多个设备上传的数据

这些字段基本涵盖了系统所有关键监测点和控制状态,上传后可以通过云平台实现远程监控、历史数据分析及设备管理。

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

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

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

image-20221204193824815

3.1 物联网平台介绍

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

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

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

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

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

img

3.2 开通物联网服务

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

image-20241028135834377

开通免费单元。

image-20241028135935457

点击立即创建

image-20240117134653452

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

image-20241028140048811

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

image-20241028140129102

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

image-20241028140229696

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

image-20241028140331523

image-20241028140428663

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

image-20241028140511105

总结:

端口号:   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:UsersLenovo>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:UsersLenovo>

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)创建产品

image-20241028141601305

(2)填写产品信息

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

image-20240612094809689

(3)产品创建成功

image-20240612095148945

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

image-20240612095134263

(4)添加自定义模型

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

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

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

比如:

soil_pH —— 土壤的pH值

soil_temperature —— 土壤温度(单位:℃)

soil_humidity —— 土壤湿度(单位:%)

soil_nitrogen —— 土壤中氮元素含量(单位:ppm或mg/kg,根据传感器规格)

soil_phosphorus —— 土壤中磷元素含量(单位:ppm或mg/kg)

soil_potassium —— 土壤中钾元素含量(单位:ppm或mg/kg)

environment_temperature —— 环境空气温度(单位:℃)

environment_humidity —— 环境空气湿度(单位:%)

light_intensity —— 环境光照强度(单位:Lux)

water_pump_status —— 自动灌溉状态(如0表示关闭,1表示开启)

device_id —— 设备唯一标识,用于区分多个设备上传的数据

先点击自定义模型。

image-20240612095517900

再创建一个服务ID。

image-20240612095542749

接着点击新增属性。

image-20240612095648815

image-20240612095711898

3.4 添加设备

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

(1)注册设备

image-20240425181935561

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

image-20240612100115167

(3)保存设备信息

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

image-20240612100128061

(4)设备创建完成

image-20240612100147232

(5)设备详情

image-20240612100202960

image-20240612100217236

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

img

业务流程:

img

(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

image-20221207153310037

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

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

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

以当前设备为例,最终订阅主题的格式如下:
$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

image-20221207153637391

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

发布的主题格式:
$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

image-20240509193207359

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

image-20240425182610048

(2)生成MQTT三元组

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

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

下面是打开的页面:

image-20240425183025893

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

直接得到三元组信息。

image-20240509193310020

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

ClientId  663cb18871d845632a0912e7_dev1_0_0_2024050911
Username  663cb18871d845632a0912e7_dev1
Password  71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac237

3.7 模拟设备登录测试

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

MQTT软件下载地址【免费】: https://download.csdn.net/download/xiaolong1126626497/89928772

(1)填入登录信息

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

image-20240509193457358

(2)打开网页查看

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

image-20240612100508790

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

image-20240612100529581

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

(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】获取项目凭证 ** 点击左上角用户名,选择下拉菜单里的我的凭证

image-20240509193646253

image-20240509193701262

项目凭证:

28add376c01e4a61ac8b621c714bf459

【2】创建IAM用户

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

image-20240509193729078

点击左上角创建用户

image-20240509193744287

image-20240314153208692

image-20240314153228359

image-20240314153258229

创建成功:

image-20240314153315444

【3】创建完成

image-20240509193828289

用户信息如下:

主用户名  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

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

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

image-20240509194152229

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

{
 "device_id": "663cb18871d845632a0912e7_dev1",
 "shadow": [
  {
   "service_id": "stm32",
   "desired": {
    "properties": null,
    "event_time": null
   },
   "reported": {
    "properties": {
     "DHT11_T": 18,
     "DHT11_H": 90,
     "BH1750": 38,
     "MQ135": 70
    },
    "event_time": "20240509T113448Z"
   },
   "version": 3
  }
 ]
}

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

image-20240509194214716

链接如下:

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设备端代码设计

设计思路概述

系统启动后,先初始化各个硬件模块(OLED、传感器接口、4G模块、继电器、蜂鸣器等)。主循环中周期性读取各传感器数据:土壤PH、温湿度、氮磷钾含量、环境温湿度、光照强度。

根据读取的土壤湿度,判断是否启动灌溉继电器进行补水。同时检测数据是否超出异常阈值,异常时触发蜂鸣器报警。

实时数据在OLED屏上显示,并将数据组包,通过MQTT协议经Air780e 4G模块上传至华为云IoT平台。

系统支持多设备独立运行,设备ID需唯一。

main.c示例代码

#include "stm32f10x.h"
#include "oled.h"
#include "bh1750.h"
#include "dht11.h"
#include "soil_sensor.h"      // 土壤485传感器读取相关函数
#include "air780e_mqtt.h"     // 4G模块MQTT通信函数
#include "relay.h"
#include "buzzer.h"
#include "delay.h"
#include <stdio.h>

// 设备ID定义
#define DEVICE_ID "soil_monitor_001"

// 土壤湿度阈值,低于该值启动灌溉
#define SOIL_HUMIDITY_THRESHOLD 40  

// 报警阈值(示例,实际需调试确认)
#define PH_LOW_THRESHOLD 5.5
#define PH_HIGH_THRESHOLD 7.5
#define NITROGEN_HIGH_THRESHOLD 1500
#define PHOSPHORUS_HIGH_THRESHOLD 1000
#define POTASSIUM_HIGH_THRESHOLD 1200

// 定时读取间隔(ms)
#define READ_INTERVAL 5000  

// 数据结构
typedef struct {
    float soil_pH;
    float soil_temperature;
    float soil_humidity;
    float soil_nitrogen;
    float soil_phosphorus;
    float soil_potassium;
    float env_temperature;
    float env_humidity;
    uint16_t light_intensity;
} SoilData;

SoilData soilData;

// 函数声明
void System_Init(void);
void Read_Sensors(SoilData* data);
void Display_Data(const SoilData* data);
void Control_Watering(float soil_humidity);
void Check_Alarm(const SoilData* data);
void Upload_Data_MQTT(const SoilData* data);

int main(void)
{
    System_Init();

    while(1)
    {
        Read_Sensors(&soilData);

        Display_Data(&soilData);

        Control_Watering(soilData.soil_humidity);

        Check_Alarm(&soilData);

        Upload_Data_MQTT(&soilData);

        Delay_ms(READ_INTERVAL);
    }
}

// 系统初始化
void System_Init(void)
{
    // 初始化时钟系统
    SystemInit();

    // 初始化延时函数
    Delay_Init();

    // 初始化OLED显示
    OLED_Init();

    // 初始化土壤传感器485接口
    SoilSensor_Init();

    // 初始化DHT11环境温湿度传感器
    DHT11_Init();

    // 初始化BH1750光照传感器
    BH1750_Init();

    // 初始化继电器(控制水泵)
    Relay_Init();

    // 初始化蜂鸣器
    Buzzer_Init();

    // 初始化4G模块MQTT
    Air780e_MQTT_Init(DEVICE_ID);

    OLED_Clear();
    OLED_ShowString(0,0,(uint8_t *)"Soil Monitor Init",16);
    Delay_ms(1000);
}

// 读取所有传感器数据
void Read_Sensors(SoilData* data)
{
    // 读取土壤485传感器,获取PH、温度、湿度、氮磷钾
    SoilSensor_Read(&data->soil_pH, &data->soil_temperature, &data->soil_humidity,
                    &data->soil_nitrogen, &data->soil_phosphorus, &data->soil_potassium);

    // 读取环境温湿度DHT11
    DHT11_Read(&data->env_temperature, &data->env_humidity);

    // 读取光照强度BH1750
    data->light_intensity = BH1750_ReadLightIntensity();
}

// OLED显示数据
void Display_Data(const SoilData* data)
{
    char buf[32];

    OLED_Clear();
    sprintf(buf, "pH: %.2f", data->soil_pH);
    OLED_ShowString(0,0,(uint8_t*)buf,16);

    sprintf(buf, "Soil T: %.1fC", data->soil_temperature);
    OLED_ShowString(0,16,(uint8_t*)buf,16);

    sprintf(buf, "Soil H: %.1f%%", data->soil_humidity);
    OLED_ShowString(0,32,(uint8_t*)buf,16);

    sprintf(buf, "N:%d P:%d K:%d", (int)data->soil_nitrogen, (int)data->soil_phosphorus, (int)data->soil_potassium);
    OLED_ShowString(0,48,(uint8_t*)buf,16);

    // 根据需要,循环显示环境数据等
}

// 根据土壤湿度控制灌溉继电器
void Control_Watering(float soil_humidity)
{
    if(soil_humidity < SOIL_HUMIDITY_THRESHOLD)
    {
        Relay_On();  // 打开水泵灌溉
    }
    else
    {
        Relay_Off(); // 关闭水泵
    }
}

// 异常情况报警检测
void Check_Alarm(const SoilData* data)
{
    uint8_t alarm_flag = 0;

    if(data->soil_pH < PH_LOW_THRESHOLD || data->soil_pH > PH_HIGH_THRESHOLD)
        alarm_flag = 1;
    if(data->soil_nitrogen > NITROGEN_HIGH_THRESHOLD)
        alarm_flag = 1;
    if(data->soil_phosphorus > PHOSPHORUS_HIGH_THRESHOLD)
        alarm_flag = 1;
    if(data->soil_potassium > POTASSIUM_HIGH_THRESHOLD)
        alarm_flag = 1;

    if(alarm_flag)
    {
        Buzzer_On();
    }
    else
    {
        Buzzer_Off();
    }
}

// 数据上传至云端(通过MQTT协议)
void Upload_Data_MQTT(const SoilData* data)
{
    // 构造JSON格式字符串上传
    char json_data[256];
    sprintf(json_data,
            "{"device_id":"%s","
            ""soil_pH":%.2f,"
            ""soil_temperature":%.2f,"
            ""soil_humidity":%.2f,"
            ""soil_nitrogen":%.2f,"
            ""soil_phosphorus":%.2f,"
            ""soil_potassium":%.2f,"
            ""environment_temperature":%.2f,"
            ""environment_humidity":%.2f,"
            ""light_intensity":%d}",
            DEVICE_ID,
            data->soil_pH,
            data->soil_temperature,
            data->soil_humidity,
            data->soil_nitrogen,
            data->soil_phosphorus,
            data->soil_potassium,
            data->env_temperature,
            data->env_humidity,
            data->light_intensity);

    Air780e_MQTT_Publish("soil_monitor/topic", json_data);
}

代码说明

  • System_Init()函数负责初始化所有硬件模块。
  • Read_Sensors()周期性读取土壤传感器、DHT11和BH1750数据。
  • Display_Data()负责在OLED屏幕上实时显示关键数据。
  • Control_Watering()根据土壤湿度自动控制继电器驱动抽水电机灌溉。
  • Check_Alarm()根据预设阈值判断是否异常,触发蜂鸣器报警。
  • Upload_Data_MQTT()将传感器数据封装成JSON字符串,通过Air780e的MQTT协议上传至华为云IoT平台。

这个main.c结构清晰,模块职责分明,方便维护和扩展。大家可根据实际驱动库函数名和具体硬件接口,调整调用细节。这样可以保证整体系统逻辑完整、数据及时准确上传,并且本地交互友好。

五、上位机开发

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

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

5.1 Qt开发环境安装

Qt的中文官网: https://www.qt.io/zh-cn/image-20221207160550486

image-20221207160606892

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

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

如果下载不了,可以在网盘里找到安装包下载: https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink

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

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

image-20221203151742653

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

image-20241028152725134

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

【1】新建工程

image-20240117144052547

【2】设置项目的名称。

image-20241112142627805

【3】选择编译系统

image-20240117144239681

【4】选择默认继承的类

image-20240117144302275

【5】选择编译器

image-20241028153603487

【6】点击完成

image-20240117144354252

【7】工程创建完成

image-20241112142836874

5.3 切换编译器

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

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

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

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

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

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

image-20241112142912481

5.4 编译测试功能

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

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

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

image-20241112142939735

5.5 设计UI界面与工程配置

【1】打开UI文件

image-20241112143019233

打开默认的界面如下:

image-20240425194845233

【2】开始设计界面

根据自己需求设计界面。

5.5 编译Windows上位机

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

image-20241112153656462

5.6 配置Android环境

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

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

【1】选择Android编译器

选择编译器。

image-20240425232651515

切换编译器。

image-20241112153812833

【2】创建Android配置文件

image-20240117144604025

image-20240117144635052

image-20240117144652014

创建完成。

image-20241112153851571

【3】配置Android图标与名称

image-20241113114730689

【3】编译Android上位机

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

然后点击构建。

image-20241112154026342

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

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

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

image-20241112154142209

  -- 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单片机的土壤质量监测系统的设计与实现。系统通过多种传感器对土壤的PH值、温湿度、氮磷钾含量以及环境的温湿度和光照强度进行实时监测,并结合自动灌溉功能,有效提升了土壤管理的智能化水平。采用Air780e 4G模块实现了数据的远程上传与云端管理,配合OLED本地显示和蜂鸣器报警,确保系统具备良好的交互性和实时响应能力。此外,系统支持太阳能供电,提升了设备的适用环境范围和续航能力。通过本项目的开发,验证了嵌入式技术物联网技术在现代农业环境监测中的应用价值,为智慧农业的发展提供了有力的技术支持和实践参考。

  • 更多详细资料请联系.docx
    下载

相关推荐