基于物联网设计的智能家居庭院绿化系统(STM32+华为云IOT)【玩转华为云】
一、前言
1.1 项目介绍
【1】项目开发背景
随着科技的飞速发展和人们生活水平的不断提高,智能家居已成为现代生活的重要组成部分,越来越多的家庭开始追求更加智能化、便捷化的居家生活方式。特别是在城市化进程加速的背景下,拥有私人庭院或阳台花园成为许多人的生活理想,而如何有效管理这些绿色空间,确保植物健康成长,成为了众多城市居民关注的焦点。
传统庭院绿化管理依赖人工观察和维护,不仅耗时耗力,且难以做到精细化管理,尤其是在快节奏的现代生活中,人们往往因工作繁忙、出差等原因无法及时照料植物,导致植物因缺水、光照不足或过度而受损甚至死亡。
开发一种基于STM32的智能家居庭院绿化系统显得尤为重要。该系统融合了物联网、自动控制及移动互联网技术,通过智能化手段实现对庭院绿化的全天候自动化监测与管理。它不仅能自动调节土壤湿度、光照条件,确保植物获得最适宜的生长环境,还能让用户通过手机APP远程监控和控制,无论身处何地都能轻松管理自家的绿色空间,大大提升了庭院绿化的效率和观赏价值。
本项目的开发不仅顺应了现代家庭对高品质居住环境的追求,也是对智慧城市、智慧家庭理念的具体实践,有助于推动智能家居技术在园艺领域的应用和发展,满足市场对高效、智能、环保庭院绿化管理解决方案的需求。
【2】设计实现的功能
(1)智能土壤湿度管理:通过高精度的土壤湿度传感器连接至STM32的ADC模拟量接口,实时监测土壤湿度水平。当检测到土壤湿度低于预设阈值时,系统自动触发继电器控制5V抽水电机工作,进行精准灌溉,保证植物获得足够的水分。
(2)自动光照调节:采用BH1750光照传感器监测环境光照强度,根据光照强度的实时数据,系统自动控制白色LED补光灯的开关,确保植物在不同时间段内均能接收到适宜的光照,促进其健康成长。
(3)环境数据监测与上传:集成DHT11温湿度传感器,全面监控庭院微环境。所有采集到的数据(包括土壤湿度、光照强度、环境温度和湿度)通过ESP8266-WiFi模块连接至华为云IoT物联网平台,实现云端存储与分析,便于长期跟踪和优化庭院绿化条件。
(4)远程控制与监控:利用Qt框架开发的Android手机APP,用户可以不受地域限制地远程控制和监测系统。用户能够自定义浇水时间、调整补光灯的亮度与工作时段,并实时查看庭院绿化区的各项环境参数,实现便捷高效的远程管理。
(5)直观数据显示:系统配备0.96寸OLED显示屏,采用SPI通信协议,直接显示当前的土壤湿度、光照强度、温度和湿度等关键信息,现场人员可快速了解庭院绿化状态。
(6)异常报警提示:内置蜂鸣器作为声音报警装置,当系统检测到极端环境条件(如极度缺水或光照过强)时,会自动发出警报,提醒用户及时采取措施,保护植物免受损害。
【3】项目硬件模块组成
(1)主控制器模块:采用STM32F103RCT6微控制器作为核心处理单元,负责系统协调控制、数据处理及逻辑判断。
(2)土壤湿度检测模块:包括一个土壤湿度传感器,通过ADC接口连接至STM32,用于实时监测土壤的湿度状况。
(3)环境光照强度检测模块:采用BH1750光照强度传感器,监测环境光照强度,为自动补光提供依据。
(4)温湿度检测模块:使用DHT11温湿度传感器,监测环境温度和湿度,确保全面掌握庭院微环境状况。
(5)OLED显示模块:配置一块0.96英寸SPI接口的OLED显示屏,用于直观展示系统运行状态、土壤湿度、光照强度、温湿度等实时数据。
(6)自动灌溉控制模块:包含继电器模块和5V抽水电机,当STM32检测到土壤湿度低于设定值时,控制继电器闭合,启动电机进行自动灌溉。
(7)补光灯控制模块:由若干白色LED灯组成,通过STM32控制其开关及亮度,根据光照强度传感器的反馈自动调节或手动通过APP控制,以补充自然光照。
(8)网络通讯模块:使用ESP8266 WiFi模块,实现STM32与华为云IoT物联网平台之间的无线数据传输,支持设备远程管理和数据上传。
(9)声音报警模块:集成一个蜂鸣器,当系统检测到异常环境条件时,由STM32触发蜂鸣器报警。
(10)电源模块:采用5V 2A稳压电源,为整个系统提供稳定的工作电压,保障各模块正常运行。
【4】摘要
本项目介绍了一种基于STM32微控制器设计的智能家居庭院绿化系统,该系统集成了土壤湿度监测、环境光照强度控制、自动灌溉、远程监控与管理等功能于一体,提高庭院绿植养护的自动化与智能化水平。系统通过搭载多种传感器(包括土壤湿度传感器、光照强度传感器、温湿度传感器)精确感知环境参数,并利用ESP8266 WiFi模块与华为云IoT平台实现数据的远程传输与分析。结合定制开发的Android手机APP,用户能够远程调控灌溉计划、光照条件,以及实时监测系统采集的各项数据,极大地提升了庭院绿化的管理效率与便利性。此外,系统还具备异常情况下的声音报警功能,确保了植物生长环境的持续优化与保护。
关键词:STM32、智能家居、庭院绿化、自动灌溉、光照控制、华为云IoT、ESP8266、远程监控、Qt框架、Android APP。
1.2 设计思路
(1)需求分析与系统规划:首先明确项目目标,即设计一个能够自动监测并调控庭院绿化环境的智能系统,以满足用户对庭院植物健康生长的需求。具体包括土壤湿度管理、光照调节、远程监控与控制等核心功能。
(2)模块化设计:将系统分为几个关键模块进行设计,包括环境监测模块(土壤湿度、光照强度、温湿度)、自动控制模块(灌溉、补光)、数据处理与上传模块、远程控制模块(手机APP)、报警提示模块及电源管理模块,每个模块独立设计,确保系统的灵活性与可维护性。
(3)核心硬件选型:基于性能、成本及兼容性考虑,选择STM32F103RCT6作为主控芯片,以其强大的处理能力和丰富的外设接口支撑整个系统运行。同时,挑选适合的传感器(如BH1750、DHT11)确保数据采集的准确性和可靠性。
(4)物联网集成:通过ESP8266-WiFi模块,将系统接入华为云IoT平台,实现数据的云端存储与分析,这不仅提高了数据的安全性,也为远程管理和大数据分析提供了基础。
(5)软件开发:开发基于Qt框架的Android手机APP,作为用户与系统交互的主要界面,提供友好、直观的操作体验。APP需支持远程监控各项环境参数,调整灌溉和补光策略,以及接收系统报警通知。
(6)异常处理与安全机制:设计合理的错误处理流程,如在网络中断时的数据缓存机制,以及传感器异常时的系统响应策略,确保系统稳定运行。同时,考虑到设备操作安全性,实施必要的软件与硬件安全措施。
(7)人机交互界面:在硬件端,通过OLED显示屏显示关键信息,便于现场快速查看;在软件端,APP界面设计简洁明了,确保用户能迅速理解和操作。
(8)测试与优化:完成硬件组装与软件开发后,进行全面的系统测试,包括功能验证、稳定性测试、用户体验测试等,根据测试反馈不断调整优化,确保系统达到预期的设计目标。
1.3 系统功能总结
功能分类 | 具体功能 | 实现方式 |
---|---|---|
环境监测 | 土壤湿度检测 | 土壤湿度传感器 + STM32 ADC采集 |
环境光照强度检测 | BH1750光照传感器 + STM32控制 | |
温湿度监测 | DHT11温湿度传感器 + STM32通信 | |
自动控制 | 自动灌溉 | 土壤湿度阈值判断 + 继电器控制水泵 |
光照自动调节 | 光照强度判断 + STM32控制LED补光灯 | |
数据管理与上传 | 本地数据收集 | 各传感器数据整合至STM32 |
云平台数据上传 | ESP8266-WiFi模块 + 华为云IoT平台 | |
远程控制与监控 | 手机APP控制 | Qt框架开发Android APP |
实时数据查看 | APP远程访问云端数据 | |
报警提示 | 异常情况报警 | 环境条件偏离阈值 + 蜂鸣器报警 |
用户界面 | 数据显示 | 0.96寸OLED显示屏(SPI) |
硬件架构 | 主控制器 | STM32F103RCT6 |
通讯模块 | ESP8266 WiFi模块 | |
电源供应 | 5V 2A稳压电源 |
1.4 开发工具的选择
【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)和应用程序。它功能强大且结构紧凑,拥有直观的工具和库。
二、硬件选型
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 PCB板
2.3 USB下载线
2.4 ESP8266 WIFI
■模块采用串口(LVTTL) 与MCU (或其他串口设备) 通信,内置TCP/IP协议栈,能够实现串口与WIFI之间的转换 ■模块支持LVTTL串口, 兼容3..3V和5V单片机系统 ■模块支持串 口转WIFI STA、串口转AP和WIFI STA+WIFI AP的模式,从而快速构建串口-WIFI数据传输方案 ■模块小巧(19mm*29mm), 通过6个2.54mm间距排针与外部连接
2.5 杜邦线(2排)
2.6 稳压模块
2.7 电源插头
2.8 OLED显示屏
选择7针SPI接口的0.96寸OLED显示屏。
特点:
OLED是有机发光二极管又称为有机激光显示、OLED显示技术具有自发光的特性、采用非常薄的有机材料涂层、和玻璃基板、当有电流通过时、这些有机材料就会发光、而且OLED显示屏幕可视角大、功耗低、OLED由于同时具备自发光、不需背光源(只是供电不会亮的、驱动程序和接线正确才会点亮)对比度高、厚度薄视角广、反应速度快、可用于挠曲面板、使用温度范围广、结构及制程等优异之特性、先接触的1286屏都是LCD的、需要背光、功耗较高、而OLED的功耗低、更加适合小系统、由于两者发光材料的不同、在不同的环境中、OLED的显示效果好、模块供电可以是3.3v也可以是5V、不需要修改模块电路、OLED屏具有多个控制指令、可以控制oLED的亮度、对比度、开关升压电路等指令、操作方便、功能丰富、可显示汉字、ASCH、图案等、同时为了方便应用在产品上、预留4个M3固定孔、方便用户固在机壳上。
2.9 蜂鸣器模块
2.10 DHT11温湿度传感器
DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有可靠性与卓越的长期稳定性,成本低、相对湿度和温度测量、快响应、抗干扰能力强、信号传输距离长、数字信号输出、精确校准。传感器包括一个电容式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。可用于暖通空调、除湿器、测试及检测设备、消费品、汽车、自动控制、数据记录器、气象站、家电、湿度调节器、医疗、其他相关湿度检测控制。
特点如下:
1、可以检测周围环境的湿度
2、可以检测周围环境的温度
3、湿度测量范围:20%-95%(0度-50度范围)湿度测量误差:+-5%4、温度测量范围:o度-50度温度测量误差:+-2度
4、工作电压3.3V-5V
5、输出形式数字输出
2.11 LED白色补光灯模块
2.12 BH1750光敏传感器
链接:https://detail.tmall.com/item.htm?abbucket=3&id=543135220776&ns=1&spm=a230r.1.14.16.d7597d40XRn0Ec
2.13 土壤湿度传感器
土壤湿度检测模块买两个备用。
2.14 抽水马达
再买一根水管。
2.15 继电器模块
三、部署华为云物联网平台
华为云官网: 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)
接入地址:ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com
**根据域名地址得到IP地址信息: **
打开Windows电脑的命令行控制台终端,使用ping
命令。ping
一下即可。
Microsoft Windows [版本 10.0.19045.4170]
(c) Microsoft Corporation。保留所有权利。
C:\Users\11266>ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com
正在 Ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com [117.78.5.125] 具有 32 字节的数据:
来自 117.78.5.125 的回复: 字节=32 时间=35ms TTL=93
来自 117.78.5.125 的回复: 字节=32 时间=36ms TTL=93
来自 117.78.5.125 的回复: 字节=32 时间=36ms TTL=93
来自 117.78.5.125 的回复: 字节=32 时间=39ms TTL=93
117.78.5.125 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 35ms,最长 = 39ms,平均 = 36ms
C:\Users\11266>
MQTT协议接入端口号有两个,1883是非加密端口,8883是证书加密端口,单片机无法加载证书,所以使用1883端口比较合适。 接下来的ESP8266就采用1883端口连接华为云物联网平台。
3.3 创建产品
(1)创建产品
(2)填写产品信息
根据自己产品名字填写,下面的设备类型选择自定义类型。
(3)产品创建成功
创建完成之后点击查看详情。
(4)添加自定义模型
产品创建完成之后,点击进入产品详情页面,翻到最下面可以看到模型定义。
模型简单来说: 就是存放设备上传到云平台的数据。
你可以根据自己的产品进行创建。
比如:
IOT创建的设备属性。
环境温度 DHT11_T 整型
环境湿度 DHT11_H 整型
环境光照强度 BH1750 整型
补光灯开关 LED_SW Bool类型
土壤湿度 SOIL 整型
抽水电机开关 MOTOR_SW Bool类型
运行模式 mode_type Bool类型
温度阀值 DHT11_T_MAX 温度最大值(超出本地蜂鸣器报警)
湿度阀值 DHT11_H_MAX 湿度最大值(超出本地蜂鸣器报警)
土壤湿度阀值 SOIL_MIN 土壤湿度最小值(低于此阀值启动电机进行浇水)
先点击自定义模型。
再创建一个服务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":{"DHT11_T":30,"DHT11_H":10,"BH1750":1,"MQ135":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":{"DHT11_T":30,"DHT11_H":10,"BH1750":1,"MQ135":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": {
"DHT11_T": 18,
"DHT11_H": 90,
"BH1750": 38,
"MQ135": 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
四、STM32设备端代码设计
4.1 ESP8266-WIFI配置代码
#include "ESP8266.h"
#include "usart.h"
#include "delay.h"
void ESP8266_Init(void)
{
//====================================================实现设备在线==================================================
//【1】复位ESP8266
printf("AT+RST\r\n");//第一步
delay_ms(2000);
//【2】设置为STA模式
printf("AT+CWMODE=1\r\n");//第二步
delay_ms(1500);
//【3】设置连接的WIFI热点
// 格式: AT+CWJAP="填写wifi名称","填写WiFi密码"
printf("AT+CWJAP=\"123\",\"12345678\"\r\n");//第四步
delay_ms(1500);
//【4】设置MQTT的登录名和密码
// 格式: AT+MQTTUSERCFG=0,1,"NULL","填写用户名","填写密码",0,0,""
printf("AT+MQTTUSERCFG=0,1,\"NULL\",\"65620a943668046d0e31568c_room1\",\"a83d06a34631b72d1b35bae5ef5e23c7ea723952c33796faa47410b107e7f4b7\",0,0,\"\"\r\n");//第五步
delay_ms(1500);
//【5】设置MQTT的ClientID
// 格式: AT+MQTTCLIENTID=0,"填写ClientID"
printf("AT+MQTTCLIENTID=0,\"65620a943668046d0e31568c_room1_0_0_2023112515\"\r\n");//第6步 客户端ID
delay_ms(1500);
// 【6】设置MQTT接入地址
// 格式: AT+MQTTCONN=0,"填写MQTT接入的地址",1883,1
printf("AT+MQTTCONN=0,\"124.70.218.131\",1883,1\r\n");//第7步
delay_ms(2000);
}
void ESP8266_data_publish(char *att)
{
// char publish_command[256];
printf("%s",att);//第2步
//printf("AT+MQTTPUB=0,\"$oc/devices/65620a943668046d0e31568c_room1/sys/properties/report\",\"{\\\"services\\\":[{\\\"service_id\\\":\\\"stm32\\\",\\\"properties\\\":{\\\"%s\\\":%d}}]}\",0,0\r\n", att, data);
// printf("%s", publish_command);
}
4.2 定时器代码封装
#include "timer.h"
#include "led.h"
//通用定时器3中断初始化
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); ///使能TIM3时钟
TIM_TimeBaseInitStructure.TIM_Period = arr; //自动重装载值
TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //定时器分频
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断
TIM_Cmd(TIM3,ENABLE); //使能定时器3
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
int tnk = 0;
int timeSend = 0;
//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //溢出中断
{
LED1=!LED1;//DS1翻转
tnk++;
if(tnk>10)
{
timeSend=1;
tnk = 0;
}
}
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
}
4.3 串口配置代码
#include "sys.h"
#include "usart.h"
u8 AtRxBuffer[512],Rxcouter;
//////////////////////////////////////////////////////////////////
//加入以下代码,支持printf函数,而不需要选择use MicroLIB
#if 1
#pragma import(__use_no_semihosting)
//标准库需要的支持函数
struct __FILE
{
int handle;
};
FILE __stdout;
//定义_sys_exit()以避免使用半主机模式
void _sys_exit(int x)
{
x = x;
}
//重定义fputc函数
int fputc(int ch, FILE *f)
{
while((USART1->SR&0X40)==0);//循环发送,直到发送完毕
USART1->DR = (u8) ch;
return ch;
}
#endif
#if EN_USART1_RX //如果使能了接收
//串口1中断服务程序
//注意,读取USARTx->SR能避免莫名其妙的错误
u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节.
//接收状态
//bit15, 接收完成标志
//bit14, 接收到0x0d
//bit13~0, 接收到的有效字节数目
u16 USART_RX_STA=0; //接收状态标记
//初始化IO 串口1
//bound:波特率
void uart_init(u32 bound){
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟
//串口1对应引脚复用映射
GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1
GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1
//USART1端口配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA9,PA10
//USART1 初始化设置
USART_InitStructure.USART_BaudRate = bound;//波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_Cmd(USART1, ENABLE); //使能串口1
USART_ClearFlag(USART1, USART_FLAG_TC);
#if EN_USART1_RX
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;//串口1中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、
#endif
}
void uart2_init(u32 bound)
{
//GPIO端口设置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟
//串口1对应引脚复用映射
GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2); //GPIOA2复用为USART2
GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2); //GPIOA3复用为USART2
//USART1端口配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; //GPIOA2与GPIOA3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //速度50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PA2,PA3
//USART1 初始化设置
USART_InitStructure.USART_BaudRate = bound;//波特率设置
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART2, &USART_InitStructure); //初始化串口2
USART_Cmd(USART2, ENABLE); //使能串口2
USART_ClearFlag(USART2, USART_FLAG_TC);
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启相关中断
//Usart2 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;//串口2中断通道
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级1
NVIC_InitStructure.NVIC_IRQChannelSubPriority =3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、
}
//配置来对串口2波特率进行修改 和模块通信
void USART_Config(uint32_t baud)
{
USART_InitTypeDef USART_InitStructure;
USART_Cmd(USART2, DISABLE);
USART_InitStructure.USART_BaudRate =baud;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_No;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_Init(USART2, &USART_InitStructure);
USART_Cmd(USART2, ENABLE);
}
//串口1接收中断
void USART1_IRQHandler(void) //串口1中断服务程序
{
u8 Res;
Res=Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
{
Res =USART_ReceiveData(USART1);//(USART1->DR); //读取接收到的数据
}
}
//串口2的接收中断函数
void USART2_IRQHandler(void) //串口2中断服务程序
{
u8 Res;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中断
{
Res =USART_ReceiveData(USART2);//(USART1->DR); //读取接收到的数据
AtRxBuffer[Rxcouter++]=Res;//
}
}
void UART2_send_byte(char data)
{
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
USART_SendData(USART2, data);
}
/*-------------------------------------------------*/
/*函数名:串口2 发送数组 */
/*参 数:bound:波特率 */
/*返回值:无 */
/*-------------------------------------------------*/
void USART2_Send(char *Data,uint16_t Len)
{
uint16_t i;
for(i=0; i<Len; i++)
{
UART2_send_byte(Data[i]);
}
}
//串口2的发送函数
void Uart2_SendStr(char*SendBuf) //串口2打印数据
{
while(*SendBuf)
{
while((USART2->SR&0X40)==0);//等待发送完成
USART2->DR = (u8) *SendBuf;
SendBuf++;
}
}
#endif
五、上位机开发
为了方便查看设备上传的数据,接下来利用Qt开发一款Android手机APP 和 Windows上位机。
使用华为云平台提供的API接口获取设备上传的数据,进行可视化显示,以及远程控制设备。
5.1 Qt开发环境安装
QT5.12.6的下载地址:https://download.qt.io/archive/qt/5.12/5.12.6
打开下载链接后选择下面的版本进行下载:
qt-opensource-windows-x86-5.12.6.exe 13-Nov-2019 07:28 3.7G Details
软件安装时断网安装,否则会提示输入账户。
安装的时候,第一个复选框里勾选一个mingw 32
编译器即可,其他的不管默认就行,直接点击下一步继续安装。
选择MinGW 32-bit 编译器: (一定要看清楚了)
说明: 我这里只是介绍PC端,也就是Windows系统下的Qt环境搭建。 Android的开发环境比较麻烦,如果想学习Android开发,想编译Android程序的APP,需要自己去搭建Android环境。
也可以看下面这篇文章,不过这个文章是在Qt开发专栏里付费的,需要订阅专栏才可以看。 如果不想付费看,也可以自行找其他教程,自己搭建好必须的环境就行了
Android环境搭建的博客链接: https://blog.csdn.net/xiaolong1126626497/article/details/117254453
5.2 新建上位机工程
前面2讲解了需要用的API接口,接下来就使用Qt设计上位机,设计界面,完成整体上位机的逻辑设计。
【1】新建工程
【2】设置项目的名称。
【3】选择编译系统
【4】选择默认继承的类
【5】选择编译器
【6】点击完成
【7】工程创建完成
5.3 设计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文件。
D:/linux-share-dir/QT/build-app_Huawei_Eco_tracking-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设计的智能家居庭院绿化系统项目,成功地将现代电子技术、物联网技术和移动应用融为一体,为庭院绿化管理带来了革命性的改变。通过精准的环境监测、智能的自动控制以及便捷的远程管理功能,该系统不仅确保了植物能在理想的条件下茁壮成长,还极大地提升了用户的参与度和便利性,使繁忙的现代人在享受绿色生活的同时,无需为植物的日常护理担忧。
项目采用的高性价比硬件组合,如STM32微控制器、各类环境传感器、ESP8266 WiFi模块等,不仅保证了系统性能的高效稳定,也兼顾了成本效益,具有较强的市场竞争力和普及潜力。而华为云IoT平台的集成,则进一步强化了系统的数据处理能力与云端服务,为未来可能的智能化升级和服务扩展预留了广阔空间。
Qt框架开发的Android手机APP,不仅界面友好、操作简便,更是实现了用户与庭院绿化系统的无缝对接,使得远程监控与控制变得触手可及,真正意义上实现了“掌上花园”的概念。
本项目不仅是一项技术创新,更是一种绿色、智能生活方式的倡导。它不仅解决了现代城市家庭庭院绿化管理的实际难题,还展示了科技与自然和谐共存的美好愿景,对促进智能家居技术在环境保护和生态建设方面的应用具有积极的示范意义。随着技术的不断进步和市场需求的增长,此类智能家居绿化系统有望成为未来智能家居生态系统中的重要组成部分。
- 点赞
- 收藏
- 关注作者
评论(0)