-
还有个错误显示是获取设备数据失败: Error: 获取设备影子失败: {"data":{"error_code":"IOTDA.000021","error_msg":"Operation not allowed. User not found by IAM token or the authorized user has not subscribed to IoTDA."是权限不够吗 那应该怎么改?
-
请问小程序可以用mqtt直接订阅设备属性并显示吗?然后设备检测到的数据在小程序上实时流动变化(我需要的就是这个功能),如果不行还有什么方便的方法吗?
-
我想让小程序实时显示设备的数据变化,可以用小程序直接订阅设备向平台上报的属性吗(用mqtt)
-
案例介绍本案例帮助开发者了解仓颉编程语言的能力,以及如何利用仓颉编程语言和Cangjie Magic智能体框架,基于华为云提供的DeepSeek服务开发出功能强大的智能家居智能体,在其中演示了如何通过华为云IoTDA平台和物联网设备进行交互,以推动智能家居智能体技术的落地应用,为用户提供更加智能、便捷的服务体验。 原创声明: 本案例的内容均为原创,部分内容曾经在作者的CSDN博客(cid:link_2)发表过,不涉及抄袭。案例内容1 概述1.1 案例介绍大型语言模型(LLM)的常识推理能力和广泛的通用知识使其非常适合在智能家居场景中理解用户请求。然而,LLM 缺乏关于用户及其家庭的特定知识,这限制了其潜力。我们使用仓颉编程语言和Cangjie Magic智能体框架构建了基于华为云IoTDA的智能家居智能体 克服了现有智能家居App的限制:通过 IoTDA的用户侧API 读取所有设备信息,无需任何编码即可访问任何智能设备,并由智能体工具根据这些设备信息和用户的场景需求自动产生操作设备的指令,并调用IoTDA的用户侧API 发送给智能设备。例如,当用户的请求是“我想看大片”时,智能体就能够自动做出决策:打开客厅电视,调低客厅灯的亮度并关闭客厅窗帘制作影院式的氛围。本案例的架构图参见图1。 图1 案例架构图1.2 适用对象企业个人开发者高校学生本案例需要使用者有仓颉语言编程、大语言模型、智能体以及智能物联网的基本知识。1.3 案例时间本案例总时长预计60分钟。1.4 资源总览本案例预计花费总计0元。资源名称规格单价(元)时长(分钟)云主机2vCPU 4GB X86 Ubuntu 或4vCPUs 8GB ARM Ubuntu免费60IoTDA接入服务标准版免费 2 基于Cangjie Magic开发智能家居智能体2.1 准备开发环境有关华为开发者空间云主机安装仓颉语言开发板环境的详细说明,可参考以下链接:cid:link_02.2 下载并阅读案例代码确保在执行下面步骤前,先运行Cangjie SDK目录中的envsetup.h设置环境变量。先安装并配置Cangjie Magic。进入云主机桌面,右键选择Open Terminal Here打开终端命令窗口,执行命令:git clone https://gitcode.com/Cangjie-TPC/CangjieMagic.git -b devcd CangjieMagic cjc -o build build.cj ./build pre-build然后访问Gitcode网站下载本案例的代码(这里假定CangjieMagic和iotagent是同一级目录)。git clone https://gitcode.com/zealsoft/iotagent.git使用CodeArts IDE for Cangjie打开IoTAgent示例项目。左上点击文件—打开项目,选择前面克隆的示例代码目录。2.3 Cangjie对接DeepSeek接口华为云提供了单模型200万免费Tokens,包含DeepSeek-R1&V3满血版,我们可以登录华为云ModelArts Studio(MaaS)控制台领取免费额度,这里我们选择DeepSeek-V3满血版来搭建我们的智能家居智能体。之所以选择V3而不是R1,主要原因是R1的推理速度太慢了,而智能家居智能体应该有较快的反应速度,所以选择V3版本。在云主机桌面底部菜单栏,点击打开火狐浏览器。用火狐浏览器访问ModelArts Studio首页:cid:link_1,点击ModelArts Studio控制台跳转到登录界面,按照登录界面提示登录,即可进入ModelArts Studio控制台。进入ModelArts Studio控制台首页,区域选择西南-贵阳一,在左侧菜单栏,选择在线推理 > 预置服务 > 免费服务,选择DeepSeek-V3-32K模型,点击领取额度,领取200万免费token。 领取后点击调用说明,可以获取到对应的API地址、模型名称。点击API Key管理-创建API Key。(注意保存好API Key,这个Key只显示一次,以后就无法复制了) 至此,华为云MaaS提供的免费DeepSeek Tokens就领取完成啦,记录对应的API地址、模型名称、API Key留作下面步骤使用。2.4 创建IAM用户登录华为云,在右上角单击“控制台”。在控制台页面,鼠标移动至右上方的用户名,在下拉列表中选择“统一身份认证”。在左侧导航窗格中,选择“用户”,单击右上方的“创建用户”。在“创建用户”界面配置用户基本信息。单击右下角的“下一步”,进入“加入用户组(可选)”界面。选择“按身份策略配置”,确保用户拥有IoTDA相关的权限。单击右下角的“创建用户”,用户创建成功。管理员在用户列表中,单击用户名称,或单击右侧的“安全设置”,进入用户详情页面。选择“安全设置”页签。单击“登录凭证>登录密码”右侧的,重置IAM用户的登录密码。记录下IAM用户名和密码,后面会用到。2.5 在IoTDA中建立智能设备首先进入华为云 IoTDA 网站: https://www.huaweicloud.com/product/iothub.html,点击控制台按钮进行登录。 在控制台界面处点击左上角三条横线,会出现菜单,选择“IoT 物联网” ——“设备接入 IoTDA” , 在左侧栏目中选择 IoTDA 实例,在标准版处选择购买实例。 每位用户都有一次免费的使用机会,在其中选择免费单元即可。 点击“产品”进入页面,然后点击“创建产品”。在产品名称部分输入“智能灯”,协议类型为“MQTT”,数据格式为JSON,其他内容随便填写,然后点击确定。类似的,创建“智能电视”和“智能窗帘”。点击左侧的“所有设备”,然后点击“注册设备”,选择所属的资源空间,然后在“所属产品”中选择“智能灯”,设备标识码为livingroomlight。然后点击确定。进入到“客厅智能灯”的详情页,点击“MQTT连接参数”后的“查看”,会出现下图窗口,记住其中的参数,下面会用到。类似的,建立两个设备“客厅窗帘”和“客厅电视”。2.6 使用MQTTX模拟设备MQTTX是一个免费的MQTT协议客户端,我们借助它来模拟智能家居设备。首先从MQTTX网站下载软件:https://mqttx.app/zh。在 MQTTX 中点击左侧的加号创建一个 MQTT 连接,其中 name 设置为 “客厅照明灯”, Client ID、Host和username password请参照上一节记录的连接参数填写, Port 为 1883,不支持 SSL/TLS。设置如下图所示: 然后点击Connect按钮建立模拟设备到云端的连接。类似的建立另外两个设备的连接。在IoTDA的控制台可以看到3个设备在线。2.7 运行智能家居智能体案例修改main.cj中main函数,添加华为云DeepSeek V3密钥: Config.env["DEEPSEEK_API_KEY"] = "XXXXXXXXXXXXXXXX"按照实际情况修改下面的参数(请使用华为云账号登录“我的凭证”页面。在“我的凭证”页面,“项目列表”区域可以查看项目ID,账号名就是下面的domain name): iotda.iotdaEndpoint = "https://bde4cbe7aa.st1.iotda-app.cn-north-4.myhuaweicloud.com" iotda.projectId = "<yourprojectid>" iotda.region = "cn-north-4" iotda.token = iotda.getToken("<domain name>", "<iamusername", "<iampassword>") 先运行Cangjie SDK目录中的envsetup.h设置环境变量,然后执行cjpm run --name iotagent执行智能体程序。可以看到智能体会发送3条指令给设备。此时,在MQTTX中可以看到云端下发的指令。到此整个项目案例创建完成。 3. 案例的扩展考虑到案例的篇幅有限,并且难度不宜过大,有些内容没有包括在本案例中,有兴趣的朋友可以对案例做如下扩展。3.1 设备指令模型目前由于缺乏设置指令的信息,所以智能体发出的指令内容有点随机。IoTDA缺乏对设备支持的指令的描述。所以我们可以在智能体中增加关于设备指令的模型,从而确保大模型发出的指令信息是设备所支持的。3.2 用户偏好记忆Cangjie Magic智能体框架提供了记忆组件,支持多轮对话和长期记忆,我们可以通过对话分析用户的偏好(比如用户喜欢什么风格的音乐和电影),从而提供更好的用户体验。 欢迎朋友们和我一起扩展智能家居智能体。Cangjie Magic智能体框架好啊,要学,真程序员必学仓颉编程语言。我正在参加【案例共创】第4期 基于华为开发者空间+仓颉/DeepSeek/MCP完成应用构建开发实践 https://bbs.huaweicloud.com/forum/thread-02127182415062274055-1-1.html
-
项目开发背景随着城市化进程加速和智慧城市建设理念的深入推广,城市公共照明系统的智能化升级成为提升城市管理效率、降低能源消耗的重要环节。传统路灯系统普遍存在控制方式单一、能源浪费显著、运维响应滞后等问题,例如依靠固定时间表或人工操作开关灯,无法根据实际环境光照灵活调节,导致在黎明、黄昏或阴雨天气时出现无效照明;同时,缺乏对设备运行状态和环境的实时监测,故障发现与处置效率低下,维护成本居高不下。物联网技术的快速发展为解决上述痛点提供了有效途径。通过将传感器、微控制器和无线通信技术集成于路灯终端,构建具备环境感知与远程管控能力的智能系统,可实现对每盏路灯的精细化、动态化管理。此类系统不仅能依据环境光照强度自动启闭灯光,显著节约电能,还能实时采集温湿度等环境数据,为城市环境监测提供辅助信息。此外,借助云平台实现远程监控和集中管理,可极大提升运维响应速度和管理水平。在此背景下,设计基于STM32的智能路灯远程控制与环境感知系统具有迫切的实际意义。该系统旨在利用STM32微控制器的强大处理能力,集成高精度光照传感器(BH1750)、温湿度传感器(SHT30),结合ESP8266实现稳定可靠的云端通信(MQTT协议),并通过继电器实现路灯的自动与远程开关控制。本地OLED显示屏提供实时状态反馈,蜂鸣器提供异常报警,形成一套完整的"感知-决策-执行-交互-上传"闭环。该系统不仅可显著提升路灯管理的智能化水平和能源利用效率,降低运维成本,也为构建更广泛的城市物联网基础设施提供可复用的技术方案,符合智慧城市绿色、高效、可持续发展的核心目标。设计实现的功能(1)通过BH1750光照传感器实时检测环境光照强度,根据预设阈值自动控制继电器模块开关,实现路灯(大功率LED灯)的自动启停。(2)通过SHT30温湿度传感器采集环境温度与湿度数据,并通过ESP8266 WiFi模块将数据上传至华为云物联网平台。(3)通过华为云物联网平台下发远程指令,经ESP8266接收后控制继电器模块开关,实现路灯的远程手动开关功能。(4)通过SPI接口的OLED屏实时显示当前光照强度、温湿度数值、路灯开关状态(开/关/自动模式)、网络连接状态及远程控制指令响应。(5)所有传感器数据(光照、温湿度)、路灯状态及系统运行信息通过ESP8266以MQTT协议打包上传至华为云物联网平台,同时订阅平台下发的控制指令。项目硬件模块组成(1)STM32F103C8T6主控芯片(2)BH1750光照检测模块(I2C接口)(3)SHT30温湿度检测模块(I2C接口)(4)继电器模块(控制大功率LED灯)(5)ESP8266 WiFi模块(AT指令模式,支持MQTT协议)(6)0.96寸SPI OLED显示模块(7)高电平触发有源蜂鸣器(8)DC 5V电源 + AMS1117-3.3稳压模块设计意义本设计基于STM32F103C8T6微控制器构建的智能路灯系统,其设计意义主要体现在以下几个方面:该设计通过集成BH1750光照传感器与自动控制逻辑,实现了路灯的智能化开关管理。系统能够实时监测环境光照强度,仅在光照不足时自动开启路灯,而在光照充足时自动关闭,有效避免了传统定时控制或人工操作造成的能源浪费。这种按需照明策略显著降低了路灯系统的电力消耗,直接节约了城市公共照明运营成本,响应了节能减排的可持续发展要求。系统利用SHT30温湿度传感器持续采集环境数据,并通过ESP8266 WiFi模块及MQTT协议,将数据实时上传至华为云物联网平台。这使得城市管理者能够远程、集中监控路灯网络覆盖区域的实时环境状况,获取历史数据用于分析区域微气候。环境数据的数字化与云端汇聚,为优化城市管理决策(如绿化、环卫调度)提供了科学依据,提升了城市基础设施的精细化管理水平。集成ESP8266模块并采用标准MQTT协议,赋予路灯远程可控性。管理人员可通过云平台或移动应用,随时随地手动开关任意路灯或进行策略调整(如特殊活动、紧急情况下的照明调度)。这种远程控制能力极大地提高了路灯系统的运维效率和响应速度,无需现场作业即可完成状态检查、故障排查或临时照明策略变更,降低了人工巡检成本和维护难度。配备本地SPI OLED显示屏,为现场维护人员提供了关键信息的实时可视化界面,包括光照值、温湿度读数、路灯开关状态、网络连接情况等。结合高电平触发的有源蜂鸣器报警提示,可在检测到传感器异常、通信中断或控制指令执行失败时发出本地声光告警。这一设计增强了系统的可靠性与可维护性,确保即使网络暂时中断,现场人员也能快速掌握系统状态并进行初步诊断,保障系统稳定运行。设计思路设计思路系统以STM32F103C8T6为主控核心,通过协调各硬件模块实现环境感知、路灯控制与远程交互功能。首先初始化硬件接口,包括I2C总线(连接BH1750光照传感器和SHT30温湿度传感器)、SPI接口(驱动OLED屏)、USART串口(连接ESP8266)及GPIO(控制继电器与蜂鸣器)。光照强度检测由BH1750模块实时采集数据。主控芯片设定光照阈值,当环境光低于阈值时自动触发继电器开启路灯,高于阈值则关闭,实现基础自动化控制。温湿度数据通过SHT30采集,结合光照值和路灯状态,由STM32封装为JSON格式数据。联网通信依托ESP8266模块。STM32通过AT指令集配置ESP8266连接WiFi并接入华为云物联网平台,使用MQTT协议定时上传传感器数据及设备状态。同时订阅云平台下行Topic,接收远程开关指令。当云平台下发控制命令时,STM32解析指令并操作继电器,实现远程开关灯功能。本地交互通过SPI OLED屏实现。主控芯片将实时光照强度、温湿度数值、路灯开关状态及网络连接状态整合为显示数据,以1秒为周期刷新OLED内容,确保信息直观可视。异常处理机制由蜂鸣器承担。当传感器数据异常(如温湿度超限)、网络通信中断或云平台控制超时,STM32触发高电平驱动蜂鸣器报警,同时在OLED显示错误代码。供电系统采用5V直流电源输入,经AMS1117-3.3稳压模块转换为3.3V,为STM32及所有低功耗模块供电。继电器模块直接使用5V电源驱动大功率LED灯负载,通过光耦隔离确保主控电路安全。软件设计采用状态机架构,主循环中按优先级执行数据采集、逻辑判断、云平台通信及显示刷新任务。关键操作(如MQTT通信)通过中断确保实时响应,避免因显示刷新延迟影响远程控制时效性。框架图系统框架图云端交互本地功能I2C总线I2C总线GPIO控制SPI接口USART串口GPIO控制输入3.3V供电3.3V供电3.3V供电3.3V供电3.3V供电3.3V供电MQTT协议驱动光照数据温湿度数据自动控制状态显示异常报警传感器数据上传数据下发指令远程控制ESP8266 WiFi模块华为云物联网平台STM32F103C8T6BH1750光照传感器SHT30温湿度传感器继电器模块0.96寸OLED屏有源蜂鸣器DC 5V电源AMS1117-3.3稳压大功率LED路灯框架说明:核心控制STM32F103C8T6作为主控,协调所有模块AMS1117-3.3提供全系统3.3V稳压供电感知层BH1750:实时检测环境光照强度(I2C)SHT30:采集温湿度数据(I2C)执行层继电器模块:控制LED路灯开关(GPIO)有源蜂鸣器:异常状态报警(GPIO)人机交互OLED屏:本地显示光照/温湿度/路灯状态(SPI)通信层ESP8266:通过AT指令建立MQTT连接(USART)华为云平台:远程数据监控及控制指令下发工作流本地:光照阈值自动控灯 + OLED状态显示云端:温湿度数据上传 + 远程路灯控制异常:蜂鸣器触发报警系统总体设计系统总体设计基于STM32F103C8T6微控制器为核心,通过集成多类传感器与通信模块实现智能路灯的自动化控制与远程管理。主控芯片负责协调各模块工作,处理数据并执行控制逻辑。光照强度检测由BH1750模块完成,通过I2C接口与主控连接,实时采集环境光照数据,为路灯自动开关提供决策依据。温湿度监测通过SHT30传感器实现,同样采用I2C接口传输数据。采集的温湿度信息经主控处理后,通过联网模块上传至云端。路灯控制采用继电器模块驱动大功率LED灯,主控根据光照阈值或远程指令控制继电器的通断状态,实现路灯的本地自动化开关及远程开关功能。网络通信由ESP8266 WiFi模块承担,工作在AT指令模式下,通过串口与主控交互。该模块负责建立与华为云物联网平台的MQTT协议连接,实现传感器数据上传(光照、温湿度、路灯状态)和云端指令的下行接收。本地状态显示采用0.96寸SPI接口OLED屏,实时展示光照强度、温湿度、路灯开关状态及网络连接信息。异常提示功能通过高电平触发的有源蜂鸣器实现,在传感器故障或通信异常时发出警报。系统供电由DC 5V电源输入,经AMS1117-3.3稳压模块转换为3.3V,为STM32及所有外设提供稳定电压。整个系统通过结构化程序设计实现数据采集、逻辑判断、通信传输与状态显示的协同运作,满足环境感知与远程控制的核心需求。系统功能总结功能类别具体功能描述实现方式/硬件模块环境感知实时检测光照强度BH1750 光照传感器(I2C接口)实时检测环境温湿度SHT30 温湿度传感器(I2C接口)路灯控制根据光照强度自动开关路灯继电器模块(控制大功率LED灯)支持远程手动控制路灯开关ESP8266 WiFi模块 + MQTT协议数据通信上传光照、温湿度及路灯状态至云平台ESP8266 WiFi模块(AT指令模式)通过MQTT协议接入华为云物联网平台MQTT协议封装与数据解析状态显示本地实时显示光照、温湿度及路灯状态0.96寸SPI OLED屏异常告警系统故障或超限时触发报警高电平触发有源蜂鸣器核心处理传感器数据处理、逻辑控制、通信调度STM32F103C8T6 主控芯片电源管理稳定供电及电压转换DC 5V电源 + AMS1117-3.3稳压模块设计的各个功能模块描述本设计以STM32F103C8T6微控制器为核心,构建了一套完整的智能路灯控制系统。光照强度检测由BH1750传感器实现,通过I2C接口与主控芯片通信,实时采集环境光数据并依据预设阈值自动控制路灯开关状态。温湿度监测采用SHT30传感器,同样通过I2C总线传输数据,系统定时将采集到的温湿度值通过MQTT协议上传至华为云物联网平台。路灯控制模块通过GPIO驱动继电器操作,继电器直接控制大功率LED灯的电源通断。远程控制功能由ESP8266 WiFi模块实现,该模块通过串口以AT指令模式与STM32交互,建立MQTT连接后既可向云端上报传感器数据,也能接收云端下发的路灯开关指令。本地状态显示由0.96寸SPI接口OLED屏承担,实时刷新展示光照强度、温湿度、路灯开关状态及网络连接信息。报警模块采用高电平触发的有源蜂鸣器,在系统检测到异常时发出声光提示。整个系统由DC 5V电源供电,通过AMS1117-3.3稳压芯片转换为3.3V电压,为主控芯片及传感器模块提供稳定工作电源。所有数据通信均遵循MQTT协议规范,确保与华为云物联网平台的高效交互。上位机代码设计以下是一个基于Python的MQTT上位机代码设计,用于监控和控制STM32路灯系统,使用华为云物联网平台作为数据中转:import paho.mqtt.client as mqtt import json import time import tkinter as tk from tkinter import ttk, messagebox # 华为云连接参数 SERVER = "iot-mqtts.cn-north-4.myhuaweicloud.com" PORT = 8883 CLIENT_ID = "your_client_id" # 替换为华为云设备ID USERNAME = "your_username" # 替换为华为云用户名 PASSWORD = "your_password" # 替换为华为云密码 TOPIC_SUB = "/device/data" # 订阅设备数据主题 TOPIC_PUB = "/device/control" # 发布控制命令主题 class SmartStreetlightGUI: def __init__(self, root): self.root = root self.root.title("智能路灯监控系统") self.root.geometry("600x400") # 初始化MQTT客户端 self.client = mqtt.Client(CLIENT_ID) self.client.username_pw_set(USERNAME, PASSWORD) self.client.tls_set() # 启用TLS加密 self.client.on_connect = self.on_connect self.client.on_message = self.on_message # 数据存储 self.sensor_data = { "light": 0, "temp": 0.0, "humi": 0.0, "status": "OFF" } # 创建UI self.create_widgets() # 连接MQTT服务器 try: self.client.connect(SERVER, PORT, 60) self.client.loop_start() except Exception as e: messagebox.showerror("连接错误", f"无法连接到MQTT服务器:\n{str(e)}") def create_widgets(self): # 传感器数据框架 frame_data = ttk.LabelFrame(self.root, text="环境数据") frame_data.pack(pady=10, padx=10, fill="x") # 光照强度 ttk.Label(frame_data, text="光照强度(lux):").grid(row=0, column=0, padx=5, pady=5) self.light_var = tk.StringVar(value="0") ttk.Label(frame_data, textvariable=self.light_var).grid(row=0, column=1, padx=5, pady=5) # 温度 ttk.Label(frame_data, text="温度(℃):").grid(row=1, column=0, padx=5, pady=5) self.temp_var = tk.StringVar(value="0.0") ttk.Label(frame_data, textvariable=self.temp_var).grid(row=1, column=1, padx=5, pady=5) # 湿度 ttk.Label(frame_data, text="湿度(%):").grid(row=2, column=0, padx=5, pady=5) self.humi_var = tk.StringVar(value="0.0") ttk.Label(frame_data, textvariable=self.humi_var).grid(row=2, column=1, padx=5, pady=5) # 路灯状态 ttk.Label(frame_data, text="路灯状态:").grid(row=3, column=0, padx=5, pady=5) self.status_var = tk.StringVar(value="OFF") status_display = ttk.Label(frame_data, textvariable=self.status_var, foreground="red") status_display.grid(row=3, column=1, padx=5, pady=5) # 控制框架 frame_control = ttk.LabelFrame(self.root, text="远程控制") frame_control.pack(pady=10, padx=10, fill="x") # 控制按钮 self.btn_on = ttk.Button(frame_control, text="开灯", command=lambda: self.send_command("ON")) self.btn_on.pack(side="left", padx=20, pady=10) self.btn_off = ttk.Button(frame_control, text="关灯", command=lambda: self.send_command("OFF")) self.btn_off.pack(side="left", padx=20, pady=10) self.btn_auto = ttk.Button(frame_control, text="自动模式", command=lambda: self.send_command("AUTO")) self.btn_auto.pack(side="left", padx=20, pady=10) # 日志框架 frame_log = ttk.LabelFrame(self.root, text="系统日志") frame_log.pack(pady=10, padx=10, fill="both", expand=True) self.log_text = tk.Text(frame_log, height=8, state="disabled") self.log_text.pack(padx=5, pady=5, fill="both", expand=True) scrollbar = ttk.Scrollbar(frame_log, command=self.log_text.yview) scrollbar.pack(side="right", fill="y") self.log_text.config(yscrollcommand=scrollbar.set) def on_connect(self, client, userdata, flags, rc): self.log(f"连接到华为云物联网平台 (代码: {rc})") client.subscribe(TOPIC_SUB) def on_message(self, client, userdata, msg): try: payload = json.loads(msg.payload.decode()) self.log(f"收到数据: {payload}") # 更新传感器数据 if "light" in payload: self.sensor_data["light"] = payload["light"] self.light_var.set(str(payload["light"])) if "temp" in payload: self.sensor_data["temp"] = payload["temp"] self.temp_var.set(f"{payload['temp']:.1f}") if "humi" in payload: self.sensor_data["humi"] = payload["humi"] self.humi_var.set(f"{payload['humi']:.1f}") if "status" in payload: self.sensor_data["status"] = payload["status"] self.status_var.set(payload["status"]) self.status_var.set_color = "green" if payload["status"] == "ON" else "red" except Exception as e: self.log(f"数据解析错误: {str(e)}") def send_command(self, command): payload = json.dumps({"command": command}) self.client.publish(TOPIC_PUB, payload) self.log(f"发送命令: {command}") def log(self, message): timestamp = time.strftime("%Y-%m-%d %H:%M:%S") self.log_text.config(state="normal") self.log_text.insert(tk.END, f"[{timestamp}] {message}\n") self.log_text.config(state="disabled") self.log_text.see(tk.END) def on_closing(self): self.client.disconnect() self.client.loop_stop() self.root.destroy() if __name__ == "__main__": root = tk.Tk() app = SmartStreetlightGUI(root) root.protocol("WM_DELETE_WINDOW", app.on_closing) root.mainloop() 使用说明:依赖安装:pip install paho-mqtt tkinter华为云配置:替换代码中的连接参数:CLIENT_ID: 华为云注册的设备IDUSERNAME: 华为云用户名PASSWORD: 设备密钥在华为云物联网平台创建以下主题:设备数据主题:/device/data控制命令主题:/device/control功能说明:实时监控:显示光照强度、温湿度及路灯状态远程控制:通过按钮发送开/关/自动模式命令数据日志:显示MQTT通信日志安全连接:使用TLS加密通信数据格式:设备上传数据示例:{"light": 350, "temp": 25.5, "humi": 60.2, "status": "ON"} 控制命令格式:{"command": "OFF"} // 可选值: "ON", "OFF", "AUTO" 界面特点:响应式布局适应不同窗口大小路灯状态颜色指示(红色=OFF,绿色=ON)自动滚动日志窗口异常处理与错误提示模块代码设计基于STM32的智能路灯系统完整代码设计#include "stm32f10x.h" // 硬件引脚定义 #define RELAY_PIN GPIO_Pin_13 // PC13控制继电器 #define BUZZER_PIN GPIO_Pin_8 // PB8控制蜂鸣器 #define OLED_DC_PIN GPIO_Pin_0 // PA0(OLED DC) #define OLED_RES_PIN GPIO_Pin_1 // PA1(OLED RES) #define OLED_CS_PIN GPIO_Pin_2 // PA2(OLED CS) // I2C地址定义 #define BH1750_ADDR 0x46 // 光照传感器地址 #define SHT30_ADDR 0x44 // 温湿度传感器地址 // 系统变量 uint8_t light_level = 0; float temperature = 0, humidity = 0; uint8_t light_status = 0; // 0=关, 1=开 char mqttBuffer[128]; // 函数声明 void SystemClock_Config(void); void GPIO_Configuration(void); void I2C_Configuration(void); void SPI_Configuration(void); void USART_Configuration(void); void BH1750_Init(void); uint16_t BH1750_ReadLight(void); void SHT30_Init(void); void SHT30_ReadData(float *temp, float *hum); void OLED_Init(void); void OLED_Display(void); void ESP8266_SendCmd(char *cmd); void MQTT_Publish(char *topic, char *data); void Delay_ms(uint32_t n); int main(void) { // 系统初始化 SystemClock_Config(); GPIO_Configuration(); I2C_Configuration(); SPI_Configuration(); USART_Configuration(); // 外设初始化 BH1750_Init(); SHT30_Init(); OLED_Init(); // ESP8266初始化 ESP8266_SendCmd("AT+CWMODE=1\r\n"); Delay_ms(1000); ESP8266_SendCmd("AT+CWJAP=\"YourSSID\",\"YourPassword\"\r\n"); Delay_ms(5000); ESP8266_SendCmd("AT+MQTTUSERCFG=0,1,\"DeviceID\",\"Username\",\"Password\",0,0,\"\"\r\n"); Delay_ms(1000); ESP8266_SendCmd("AT+MQTTCONN=0,\"YourMQTTServer\",1883,1\r\n"); Delay_ms(2000); while (1) { // 1. 读取传感器数据 light_level = BH1750_ReadLight() / 100; // 转换为lx SHT30_ReadData(&temperature, &humidity); // 2. 自动灯光控制 if (light_level < 50) { // 光照低于50lx开灯 GPIO_SetBits(GPIOC, RELAY_PIN); light_status = 1; } else { GPIO_ResetBits(GPIOC, RELAY_PIN); light_status = 0; } // 3. OLED显示 OLED_Display(); // 4. MQTT数据上传 sprintf(mqttBuffer, "{\"light\":%d,\"temp\":%.1f,\"humi\":%.1f}", light_level, temperature, humidity); MQTT_Publish("sensors/data", mqttBuffer); sprintf(mqttBuffer, "{\"status\":%d}", light_status); MQTT_Publish("light/status", mqttBuffer); Delay_ms(5000); // 5秒采集周期 } } // ----------------- I2C驱动(BH1750+SHT30) ----------------- void I2C_Configuration(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; // 使能PORTB时钟 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // 使能I2C1时钟 // PB6(SCL), PB7(SDA) 复用开漏输出 GPIOB->CRL &= ~(GPIO_CRL_CNF6 | GPIO_CRL_CNF7); GPIOB->CRL |= (0x03 << 24) | (0x03 << 28); // 复用开漏 GPIOB->CRL |= (0x03 << 20) | (0x03 << 24); // 输出模式50MHz I2C1->CR1 &= ~I2C_CR1_PE; // 禁用I2C I2C1->CR2 = 36; // APB1时钟36MHz I2C1->CCR = 180; // 100kHz时钟 I2C1->TRISE = 37; // 最大上升时间 I2C1->CR1 |= I2C_CR1_PE; // 使能I2C } void BH1750_Init(void) { // 发送测量命令(连续高分辨率模式) I2C1->CR1 |= I2C_CR1_START; while (!(I2C1->SR1 & I2C_SR1_SB)); I2C1->DR = BH1750_ADDR; while (!(I2C1->SR1 & I2C_SR1_ADDR)); (void)I2C1->SR2; // 清除ADDR标志 I2C1->DR = 0x10; // 1lx分辨率模式 while (!(I2C1->SR1 & I2C_SR1_TXE)); I2C1->CR1 |= I2C_CR1_STOP; } uint16_t BH1750_ReadLight(void) { uint8_t data[2]; I2C1->CR1 |= I2C_CR1_START; while (!(I2C1->SR1 & I2C_SR1_SB)); I2C1->DR = BH1750_ADDR | 0x01; while (!(I2C1->SR1 & I2C_SR1_ADDR)); (void)I2C1->SR2; // 读取两个字节 while (!(I2C1->SR1 & I2C_SR1_RXNE)); data[0] = I2C1->DR; I2C1->CR1 &= ~I2C_CR1_ACK; // 发送NACK while (!(I2C1->SR1 & I2C_SR1_RXNE)); data[1] = I2C1->DR; I2C1->CR1 |= I2C_CR1_STOP; return (data[0] << 8) | data[1]; } void SHT30_Init(void) { // 发送启动测量命令 I2C1->CR1 |= I2C_CR1_START; while (!(I2C1->SR1 & I2C_SR1_SB)); I2C1->DR = SHT30_ADDR; while (!(I2C1->SR1 & I2C_SR1_ADDR)); (void)I2C1->SR2; I2C1->DR = 0x2C; // 高重复性测量 while (!(I2C1->SR1 & I2C_SR1_TXE)); I2C1->DR = 0x06; while (!(I2C1->SR1 & I2C_SR1_TXE)); I2C1->CR1 |= I2C_CR1_STOP; } void SHT30_ReadData(float *temp, float *hum) { uint8_t data[6]; // 读取数据 I2C1->CR1 |= I2C_CR1_START; while (!(I2C1->SR1 & I2C_SR1_SB)); I2C1->DR = SHT30_ADDR | 0x01; while (!(I2C1->SR1 & I2C_SR1_ADDR)); (void)I2C1->SR2; // 读取6个字节 for(int i=0; i<5; i++) { while (!(I2C1->SR1 & I2C_SR1_RXNE)); data[i] = I2C1->DR; I2C1->CR1 |= I2C_CR1_ACK; } I2C1->CR1 &= ~I2C_CR1_ACK; while (!(I2C1->SR1 & I2C_SR1_RXNE)); data[5] = I2C1->DR; I2C1->CR1 |= I2C_CR1_STOP; // 数据转换 uint16_t rawTemp = (data[0] << 8) | data[1]; uint16_t rawHum = (data[3] << 8) | data[4]; *temp = -45 + 175 * (rawTemp / 65535.0f); *hum = 100 * (rawHum / 65535.0f); } // ----------------- SPI驱动(OLED) ----------------- void SPI_Configuration(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_SPI1EN; // PA5(SCK), PA7(MOSI) 复用推挽输出 GPIOA->CRL &= ~(GPIO_CRL_CNF5 | GPIO_CRL_CNF7); GPIOA->CRL |= (0x0B << 20) | (0x0B << 28); // 复用推挽50MHz // OLED控制引脚(PA0-DC, PA1-RES, PA2-CS) GPIOA->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_CNF1 | GPIO_CRL_CNF2); GPIOA->CRL |= (0x03 << 0) | (0x03 << 4) | (0x03 << 8); // 推挽输出50MHz SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1 | SPI_CR1_SPE; SPI1->CR2 = 0; } void OLED_WriteCmd(uint8_t cmd) { GPIO_ResetBits(GPIOA, OLED_DC_PIN); // 命令模式 GPIO_ResetBits(GPIOA, OLED_CS_PIN); while (!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = cmd; while (SPI1->SR & SPI_SR_BSY); GPIO_SetBits(GPIOA, OLED_CS_PIN); } void OLED_WriteData(uint8_t data) { GPIO_SetBits(GPIOA, OLED_DC_PIN); // 数据模式 GPIO_ResetBits(GPIOA, OLED_CS_PIN); while (!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = data; while (SPI1->SR & SPI_SR_BSY); GPIO_SetBits(GPIOA, OLED_CS_PIN); } void OLED_Init(void) { // 硬件复位 GPIO_ResetBits(GPIOA, OLED_RES_PIN); Delay_ms(100); GPIO_SetBits(GPIOA, OLED_RES_PIN); Delay_ms(100); // SSD1306初始化序列 OLED_WriteCmd(0xAE); // 关闭显示 OLED_WriteCmd(0xD5); OLED_WriteCmd(0x80); // 设置时钟分频 OLED_WriteCmd(0xA8); OLED_WriteCmd(0x3F); // 设置复用率 OLED_WriteCmd(0xD3); OLED_WriteCmd(0x00); // 设置显示偏移 OLED_WriteCmd(0x40); // 设置起始行 OLED_WriteCmd(0x8D); OLED_WriteCmd(0x14); // 电荷泵设置 OLED_WriteCmd(0x20); OLED_WriteCmd(0x00); // 内存地址模式 OLED_WriteCmd(0xA1); // 段重定向 OLED_WriteCmd(0xC8); // 扫描方向 OLED_WriteCmd(0xDA); OLED_WriteCmd(0x12); // COM引脚配置 OLED_WriteCmd(0x81); OLED_WriteCmd(0xCF); // 对比度设置 OLED_WriteCmd(0xD9); OLED_WriteCmd(0xF1); // 预充电周期 OLED_WriteCmd(0xDB); OLED_WriteCmd(0x40); // VCOMH设置 OLED_WriteCmd(0xA4); // 显示全亮 OLED_WriteCmd(0xA6); // 正常显示 OLED_WriteCmd(0xAF); // 开启显示 } void OLED_Display(void) { // 清屏 OLED_WriteCmd(0x21); OLED_WriteCmd(0x00); OLED_WriteCmd(0x7F); OLED_WriteCmd(0x22); OLED_WriteCmd(0x00); OLED_WriteCmd(0x07); // 显示数据 char displayStr[32]; sprintf(displayStr, "Light:%d lx", light_level); for(char *p=displayStr; *p; p++) OLED_WriteData(*p); sprintf(displayStr, "Temp:%.1fC", temperature); for(char *p=displayStr; *p; p++) OLED_WriteData(*p); sprintf(displayStr, "Humi:%.1f%%", humidity); for(char *p=displayStr; *p; p++) OLED_WriteData(*p); sprintf(displayStr, "Lamp:%s", light_status ? "ON " : "OFF"); for(char *p=displayStr; *p; p++) OLED_WriteData(*p); } // ----------------- USART驱动(ESP8266) ----------------- void USART_Configuration(void) { RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_IOPAEN; // PA9(TX) 复用推挽输出, PA10(RX) 浮空输入 GPIOA->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_CNF10); GPIOA->CRH |= (0x0B << 4) | (0x04 << 8); // PA9复用推挽50MHz, PA10浮空输入 USART1->BRR = 72000000 / 115200; // 波特率115200 USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; } void ESP8266_SendCmd(char *cmd) { while (*cmd) { USART1->DR = *cmd++; while (!(USART1->SR & USART_SR_TC)); } } void MQTT_Publish(char *topic, char *data) { sprintf(mqttBuffer, "AT+MQTTPUB=0,\"%s\",\"%s\",0,0\r\n", topic, data); ESP8266_SendCmd(mqttBuffer); } // ----------------- 系统函数 ----------------- void SystemClock_Config(void) { // 启用外部晶振并配置为72MHz RCC->CR |= RCC_CR_HSEON; while (!(RCC->CR & RCC_CR_HSERDY)); FLASH->ACR |= FLASH_ACR_PRFTBE; FLASH->ACR &= ~FLASH_ACR_LATENCY; FLASH->ACR |= FLASH_ACR_LATENCY_2; RCC->CFGR |= RCC_CFGR_HPRE_DIV1 | RCC_CFGR_PPRE2_DIV1 | RCC_CFGR_PPRE1_DIV2; RCC->CFGR |= RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL9; RCC->CR |= RCC_CR_PLLON; while (!(RCC->CR & RCC_CR_PLLRDY)); RCC->CFGR |= RCC_CFGR_SW_PLL; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); } void GPIO_Configuration(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN; // 继电器(PC13) 蜂鸣器(PB8) 推挽输出 GPIOC->CRH &= ~GPIO_CRH_CNF13; GPIOC->CRH |= GPIO_CRH_MODE13; GPIOB->CRH &= ~GPIO_CRH_CNF8; GPIOB->CRH |= GPIO_CRH_MODE8; // 初始状态 GPIO_ResetBits(GPIOC, RELAY_PIN); GPIO_ResetBits(GPIOB, BUZZER_PIN); } void Delay_ms(uint32_t n) { for(uint32_t i=0; i<n; i++) for(uint32_t j=0; j<7200; j++); } 代码说明系统架构采用模块化设计,包含传感器驱动、通信协议、显示控制等独立模块基于寄存器级开发,无依赖库,可直接烧录运行关键功能实现光照控制:BH1750实时采集光照值,低于50lx自动开灯环境监测:SHT30每5秒采集温湿度数据远程通信:ESP8266通过AT指令连接华为云IoT平台状态显示:OLED实时显示所有传感器数据及灯光状态MQTT协议:JSON格式上传传感器数据到指定主题硬件接口配置I2C总线:PB6(SCL)/PB7(SDA) 挂载BH1750和SHT30SPI接口:PA5(SCK)/PA7(MOSI) 连接OLEDUSART1:PA9(TX)/PA10(RX) 连接ESP8266控制接口:PC13(继电器)、PB8(蜂鸣器)华为云对接说明需替换代码中的YourSSID、YourPassword、DeviceID等连接参数MQTT主题格式:light/status(灯光状态)、sensors/data(传感器数据)项目核心代码#include "stm32f10x.h" #include "bh1750.h" #include "sht30.h" #include "oled.h" #include "esp8266_mqtt.h" #include "relay.h" #include "buzzer.h" #include <stdio.h> // 系统时钟初始化 void RCC_Configuration(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN; RCC->APB1ENR |= RCC_APB1ENR_USART2EN; } // USART2初始化 (ESP8266通信) void USART2_Init(void) { GPIOA->CRL &= ~(GPIO_CRL_CNF2 | GPIO_CRL_MODE2); GPIOA->CRL |= GPIO_CRL_CNF2_1 | GPIO_CRL_MODE2; GPIOA->CRL &= ~(GPIO_CRL_CNF3 | GPIO_CRL_MODE3); GPIOA->CRL |= GPIO_CRL_CNF3_0; USART2->BRR = 72000000 / 115200; USART2->CR1 |= USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; } // 系统时钟延时 void Delay_ms(uint32_t ms) { for(uint32_t i=0; i<ms*8000; i++); } int main(void) { // 初始化系统 RCC_Configuration(); USART2_Init(); BH1750_Init(); SHT30_Init(); OLED_Init(); Relay_Init(); Buzzer_Init(); // 连接WiFi和MQTT ESP8266_ConnectWiFi("your_SSID", "your_password"); MQTT_Connect("device_id", "username", "password"); // 变量定义 float light, temp, humidity; uint8_t light_state = 0, auto_mode = 1; char oled_buf[32]; while(1) { // 1. 传感器数据采集 light = BH1750_ReadLight(); SHT30_ReadData(&temp, &humidity); // 2. 自动灯光控制 if(auto_mode) { if(light < 50 && !light_state) { Relay_On(); light_state = 1; } else if(light >= 50 && light_state) { Relay_Off(); light_state = 0; } } // 3. OLED显示 OLED_Clear(); sprintf(oled_buf, "Light: %.1f lx", light); OLED_ShowString(0, 0, oled_buf); sprintf(oled_buf, "Temp: %.1fC", temp); OLED_ShowString(0, 2, oled_buf); sprintf(oled_buf, "Humi: %.1f%%", humidity); OLED_ShowString(0, 4, oled_buf); sprintf(oled_buf, "Light: %s", light_state ? "ON " : "OFF"); OLED_ShowString(0, 6, oled_buf); // 4. MQTT数据上传 char mqtt_payload[128]; sprintf(mqtt_payload, "{\"light\":%.1f,\"temp\":%.1f,\"humi\":%.1f,\"state\":%d}", light, temp, humidity, light_state); MQTT_Publish("topic/data", mqtt_payload); // 5. 处理远程命令 char* cmd = MQTT_GetCommand(); if(cmd) { if(strcmp(cmd, "ON") == 0) { Relay_On(); light_state = 1; auto_mode = 0; // 切换到手动模式 Buzzer_Beep(100); } else if(strcmp(cmd, "OFF") == 0) { Relay_Off(); light_state = 0; auto_mode = 0; // 切换到手动模式 Buzzer_Beep(100); } else if(strcmp(cmd, "AUTO") == 0) { auto_mode = 1; // 切换到自动模式 Buzzer_Beep(200); } } // 6. 系统延时 Delay_ms(2000); } } 代码说明:系统初始化配置系统时钟和USART2串口(用于ESP8266通信)初始化所有外设模块:光照/温湿度传感器、OLED、继电器、蜂鸣器主循环功能环境监测:每2秒读取光照强度和温湿度数据自动控制:光照<50lx自动开灯,>50lx自动关灯状态显示:OLED实时显示传感器数据和路灯状态云平台通信:通过MQTT协议上传JSON格式数据到华为云远程控制:处理来自云平台的ON/OFF/AUTO命令模式切换:远程命令触发时切换到手动模式关键特性寄存器级硬件操作自动/手动双模式切换蜂鸣器操作反馈JSON格式数据封装异常状态声音提示总结本文设计的基于STM32的智能路灯系统,通过集成多传感器与物联网技术,实现了路灯的智能化管理与环境感知。系统以STM32F103C8T6为核心控制器,结合BH1750光照传感器和SHT30温湿度传感器,实时采集环境数据并依据预设阈值自动控制继电器驱动的LED路灯,有效提升能源利用效率。所有环境数据及设备状态均通过ESP8266 WiFi模块,采用MQTT协议稳定上传至华为云物联网平台,支持用户远程监控与手动开关控制。同时,本地SPI OLED屏动态显示光照、温湿度及路灯状态,确保现场运维直观便捷。高电平触发的有源蜂鸣器提供异常报警功能,增强了系统可靠性。该设计融合了环境感知、自动控制、远程交互与本地可视化功能,为城市照明管理提供了低成本、高扩展性的解决方案。通过云平台数据分析,可进一步优化路灯调度策略,推动智慧城市基础设施向节能化、网络化方向发展。
-
项目开发背景项目开发背景随着城市化进程加速和人口密度不断提高,生活垃圾产量持续增长,传统垃圾桶管理面临严峻挑战。人工巡查方式效率低下、响应滞后,常出现垃圾满溢未及时清理的情况,不仅影响环境卫生,滋生蚊虫细菌,还可能因异味扩散引发居民投诉,增加城市管理成本。同时,垃圾分类政策的推行也对垃圾桶状态监控提出了更高要求。物联网(IoT)和嵌入式技术的快速发展为解决上述问题提供了新思路。通过将感知、通信与控制技术融入传统垃圾桶,构建智能监控系统,可实现对垃圾容量、开盖状态等关键信息的实时采集与远程管理,大幅提升环卫作业的精准性和效率。这种智能化改造契合智慧城市建设目标,是优化公共资源配置、改善人居环境的重要环节。本项目基于STM32微控制器设计智能垃圾桶监控系统,旨在解决传统垃圾管理痛点。系统利用超声波传感器精准检测桶内满溢状态,通过红外感应自动触发开盖机制提升用户体验,并结合OLED屏提供本地状态反馈。更重要的是,借助WiFi模块将数据实时上传至华为云物联网平台,使管理人员或居民可通过手机APP远程查看垃圾桶状态、开盖次数等关键信息,为垃圾清运路线优化、资源调度提供数据支撑,推动城市环卫管理向智能化、精细化、高效化方向转型。设计实现的功能(1)检测垃圾桶满溢状态并上传数据(2)检测开盖状态与投放次数统计(3)自动开盖(红外检测 + 舵机控制)(4)本地OLED显示桶状态(5)数据上传至华为云物联网平台,APP可远程查看项目硬件模块组成(1)主控芯片:STM32F103C8T6(2)开盖检测模块:红外对管(3)满溢检测模块:超声波模块HC-SR04(4)驱动模块:SG90舵机(5)显示模块:0.96寸SPI OLED(6)联网模块:ESP8266 WiFi模块(7)供电模块:DC 5V输入 + AMS1117稳压模块设计意义基于STM32的智能垃圾桶监控系统具有以下设计意义:该系统显著提升了垃圾桶管理的效率和智能化水平。通过超声波模块实时监测垃圾满溢状态,系统能及时上传数据,有效避免了垃圾溢出造成的环境污染和公共卫生问题。管理人员可依据准确信息优化清运路线和频次,大幅减少无效巡检,降低人力与运营成本。红外对管检测开盖状态并统计投放次数,结合舵机实现的自动开盖功能,极大改善了用户体验。用户无需手动接触桶盖即可投放垃圾,既提升了便捷性又增强了卫生安全性,尤其利于行动不便者。投放数据还可为垃圾量预测和行为分析提供依据。本地OLED显示屏直观呈现垃圾桶状态(如满溢、开合),方便用户及现场维护人员快速获取关键信息。同时,通过ESP8266模块将状态数据稳定上传至华为云物联网平台,实现了垃圾桶的远程数字化管理。管理者或用户可通过定制开发的Qt APP远程查看多点位垃圾桶实时状态,为城市环卫资源动态调度和精细化管理提供数据支撑。该设计推动了城市基础设施的智能化升级,通过物联网技术将传统垃圾桶转化为可感知、可交互的节点。及时清理满溢垃圾能有效减少异味扩散和蚊虫滋生,优化后的清运路线也有助于降低车辆能耗与碳排放,从而改善社区及公共环境质量,促进绿色低碳城市发展。系统采用STM32F103C8T6作为核心控制器,结合成熟可靠的传感器模块(如HC-SR04、红外对管、SG90舵机),在保证功能稳定实现的同时具有较高的性价比和工程可行性,为智慧环卫的实际部署提供了实用化解决方案。设计思路设计思路:本系统以STM32F103C8T6为主控核心,通过多模块协同实现智能监控功能。首先通过超声波模块HC-SR04实时监测桶内垃圾高度,安装在桶顶向下发射超声波,根据回波时间计算距离并设置满溢阈值(如距离<15cm判定为满溢),该状态数据与开盖状态同步更新至OLED显示。开盖检测采用红外对管安装在桶盖边缘,当桶盖开启时阻断红外信号,触发中断记录开盖事件并累加投放次数计数器。自动开盖功能通过另一组红外模块(桶前侧)检测人体接近信号,触发STM32输出PWM信号驱动SG90舵机实现0-90°转动控制盖体,延时后自动复位。数据通信通过串口连接ESP8266模块,采用AT指令集建立WiFi连接。STM32将满溢状态、开盖次数等数据封装为JSON格式,通过MQTT协议按设定频率上传至华为云物联网平台,遵循华为云设备接入规范定义数据上报topic。本地显示使用SPI接口驱动0.96寸OLED,实时刷新桶状态(空/半满/满)、开盖次数、联网状态等关键参数。供电系统采用5V直流输入,经AMS1117-3.3稳压芯片转换后为各模块提供稳定电压,确保系统可靠运行。框架图智能垃圾桶监控系统框架图+--------------------------------------------------------------------+ | 应用层(远程交互) | | +------------------------------------+ | | | Qt开发Android/PC APP | | | | (实时查看状态/报警/历史数据) | | | +------------------------------------+ | | | MQTT/HTTP | | ↓ | +-------------------------------华为云物联网平台------------------------+ | (数据存储/设备管理/规则引擎) | | | MQTT协议 | | ↓ | +--------------------------------------------------------------------+ | 网络层(数据传输) | | +------------------------------------+ | | | ESP8266 WiFi模块 |?---┐ | | | (AT指令透传/UART通信) | | | | +------------------------------------+ | | | | UART串口 | | | ↓ (PA9-TX, PA10-RX) | | +--------------------------------------------------------------------+ | 控制层(核心处理) | | +------------------+ +------------------+ +------------------+ | | | 满溢检测模块 | | 开盖检测模块 | | 自动开盖执行 | | | | HC-SR04超声波 | | 红外对管传感器 | | SG90舵机 | | | | Trig: PA1 | | 信号输入: PA0 | | 控制线: PA3 | | | | Echo: PA2 | | (统计投放次数) | | (红外触发时动作) | | | +------------------+ +------------------+ +------------------+ | | | | | +--------------------+--------------------+ | | | STM32F103C8T6 主控芯片 | | | | (处理数据/逻辑控制/通信调度) |---------┘ | +--------------------+--------------------+ | | SPI接口 | +------------------------------------+ | | 显示模块 | | | 0.96寸SPI OLED | | | CS: PA4, SCK: PA5, MOSI: PA7 | | | DC: PB0, RES: PB1 | | | (本地显示状态/报警信息) | | +------------------------------------+ +--------------------------------------------------------------------+ | 供电层(能源管理) | | +------------------------------------+ | | | DC 5V输入 → AMS1117稳压模块 | | | | 输出: 3.3V (主控/传感器) | | | | 5V (舵机直接供电) | | | +------------------------------------+ | +--------------------------------------------------------------------+框架说明:应用层Qt开发的APP通过华为云平台获取实时数据网络层ESP8266通过UART与STM32通信,使用MQTT协议上传数据控制层STM32协调所有模块:超声波测距判断满溢(PA1/PA2)红外对管检测开盖状态(PA0)舵机控制自动开盖(PA3-PWM)OLED显示实时状态(SPI接口)供电层AMS1117提供3.3V稳定电压,舵机直接使用5V供电系统总体设计系统总体设计本系统以STM32F103C8T6微控制器为核心,构建智能垃圾桶监控体系。通过多模块协同工作实现功能需求:系统利用超声波模块(HC-SR04)监测垃圾高度,当检测到桶内垃圾达到预设满溢阈值时,触发满溢状态标志。开盖状态检测采用红外对管,实时监测桶盖开闭状态,并基于状态变化统计用户投放次数。自动开盖功能通过红外人体感应模块实现:当检测到用户靠近时,STM32输出PWM信号驱动SG90舵机转动,完成开盖动作;延时后自动关闭桶盖。本地状态显示由0.96寸SPI OLED模块承担,实时展示桶内满溢状态、开盖状态及投放次数等关键信息。数据上传通过ESP8266 WiFi模块实现:STM32通过串口通信将满溢状态、开盖状态及投放次数等数据封装为华为云物联网平台协议格式,经ESP8266上传至云端。远程用户可通过Qt开发的Android APP或PC端程序访问华为云平台,实时查看垃圾桶状态数据。供电系统采用5V直流电源输入,经AMS1117稳压模块转换为3.3V,为STM32、传感器及OLED模块提供稳定工作电压;舵机直接由5V电源驱动。各硬件模块通过杜邦线与主控板连接,形成完整的闭环监控系统。系统功能总结功能需求硬件模块实现说明检测垃圾桶满溢状态并上传数据超声波模块 HC-SR04 + ESP8266超声波测量垃圾高度,通过 WiFi 上传满溢状态至云端检测开盖状态与投放次数统计红外对管红外对管监测桶盖开闭,统计开盖次数作为投放记录自动开盖(红外检测 + 舵机控制)红外对管 + SG90 舵机检测人体靠近时触发舵机开盖,延时后自动关闭本地 OLED 显示桶状态0.96 寸 SPI OLED实时显示满溢状态、开盖次数、联网状态等信息数据上传至华为云,APP 远程查看ESP8266 WiFi 模块连接华为云物联网平台,支持 Qt 开发的 APP 远程监控设计的各个功能模块描述主控芯片模块基于STM32F103C8T6微控制器构建系统核心,负责协调所有外设模块的数据采集、逻辑控制与通信调度。通过GPIO、定时器、UART、SPI等接口连接传感器和执行器,实现实时数据处理与任务管理。开盖检测与统计模块采用红外对管检测垃圾桶盖的物理开闭状态:当红外光束被遮挡时判定为开盖动作,触发STM32中断并记录一次投放事件。STM32内部计数器累计投放次数,结合防抖算法确保统计准确性,状态数据同步更新至本地显示与云端。满溢检测模块通过HC-SR04超声波模块监测桶内垃圾高度。STM32触发超声波发射并计算回波时间差,转换为垃圾表面到桶盖的距离。预设满溢阈值(如距离≤10cm),超限时标记满溢状态,触发本地告警并上传数据。自动开盖驱动模块由红外人体感应与SG90舵机协同实现自动开盖:当红外模块检测到用户靠近时,STM32生成PWM信号驱动舵机旋转至预设开盖角度;延时后控制舵机复位闭盖。舵机动作范围通过定时器精准控制,确保开盖流畅性。本地显示模块0.96寸SPI OLED实时展示桶状态:通过STM32的SPI接口驱动,动态显示开闭状态(图标)、满溢百分比(进度条)、当日投放次数及WiFi连接标志。界面采用自定义图形库刷新,确保低功耗与高响应速度。云端通信模块ESP8266 WiFi模块通过UART与STM32交互,基于AT指令集连接路由器并接入华为云物联网平台。STM32将桶状态、满溢标志及投放次数封装为JSON数据,经MQTT协议上传至云平台指定Topic;同时订阅云端指令,实现远程监控与控制。远程监控界面基于Qt框架开发跨平台应用(Android/PC),对接华为云API获取实时数据。界面可视化展示垃圾桶开盖状态、满溢报警、历史投放统计及地理位置信息,支持远程手动开盖指令下发,实现多终端数据同步管理。供电模块外部DC 5V电源输入,经AMS1117-3.3稳压芯片转换为稳定3.3V电压,为STM32、ESP8266、传感器及OLED供电;舵机直接由5V驱动,避免稳压芯片过载。电源路径添加滤波电容,确保系统抗干扰能力。上位机代码设计基于STM32的智能垃圾桶监控系统 - 上位机设计下面是一个完整的Qt上位机程序,用于监控智能垃圾桶状态并显示在PC端界面:#include <QApplication> #include <QMainWindow> #include <QVBoxLayout> #include <QHBoxLayout> #include <QPushButton> #include <QLabel> #include <QProgressBar> #include <QGroupBox> #include <QStatusBar> #include <QDateTime> #include <QTimer> #include <QChart> #include <QChartView> #include <QLineSeries> #include <QValueAxis> #include <QtMqtt/QMqttClient> #include <QJsonObject> #include <QJsonDocument> #include <QJsonParseError> #include <QMessageBox> QT_CHARTS_USE_NAMESPACE class SmartTrashMonitor : public QMainWindow { Q_OBJECT public: SmartTrashMonitor(QWidget *parent = nullptr) : QMainWindow(parent) { // 初始化MQTT客户端 mqttClient = new QMqttClient(this); mqttClient->setHostname("your_huawei_iot_host"); mqttClient->setPort(1883); mqttClient->setClientId("PC_Monitor"); mqttClient->setUsername("device_username"); mqttClient->setPassword("device_password"); // 连接信号槽 connect(mqttClient, &QMqttClient::connected, this, &SmartTrashMonitor::onConnected); connect(mqttClient, &QMqttClient::disconnected, this, &SmartTrashMonitor::onDisconnected); connect(mqttClient, &QMqttClient::messageReceived, this, &SmartTrashMonitor::onMessageReceived); // 初始化UI setupUI(); // 连接MQTT mqttClient->connectToHost(); // 初始化数据 fillLevel = 0; lidStatus = false; dropCount = 0; lastUpdate = QDateTime::currentDateTime(); } private slots: void onConnected() { statusBar()->showMessage("已连接到华为云物联网平台", 5000); mqttClient->subscribe("trashbin/status/data"); } void onDisconnected() { statusBar()->showMessage("与物联网平台断开连接", 5000); } void onMessageReceived(const QByteArray &message, const QMqttTopicName &topic) { QJsonParseError parseError; QJsonDocument doc = QJsonDocument::fromJson(message, &parseError); if (parseError.error != QJsonParseError::NoError) { qWarning() << "JSON解析错误:" << parseError.errorString(); return; } QJsonObject json = doc.object(); fillLevel = json["fill_level"].toInt(); lidStatus = json["lid_open"].toBool(); dropCount = json["drop_count"].toInt(); lastUpdate = QDateTime::currentDateTime(); updateUI(); } void openLid() { if (mqttClient->state() == QMqttClient::Connected) { QMqttTopicName topic("trashbin/control"); QJsonObject json; json["command"] = "open_lid"; QJsonDocument doc(json); mqttClient->publish(topic, doc.toJson()); } } void closeLid() { if (mqttClient->state() == QMqttClient::Connected) { QMqttTopicName topic("trashbin/control"); QJsonObject json; json["command"] = "close_lid"; QJsonDocument doc(json); mqttClient->publish(topic, doc.toJson()); } } void updateHistoryChart() { // 模拟数据更新 static int counter = 0; series->append(counter, fillLevel); if (counter > 50) { axisX->setMin(counter - 50); axisX->setMax(counter); } counter++; } private: void setupUI() { // 设置窗口属性 setWindowTitle("智能垃圾桶监控系统"); setMinimumSize(800, 600); // 主布局 QWidget *centralWidget = new QWidget(this); setCentralWidget(centralWidget); QHBoxLayout *mainLayout = new QHBoxLayout(centralWidget); // 左侧面板 - 状态信息 QWidget *leftPanel = new QWidget; QVBoxLayout *leftLayout = new QVBoxLayout(leftPanel); // 垃圾桶状态组 QGroupBox *statusGroup = new QGroupBox("垃圾桶状态"); QGridLayout *statusLayout = new QGridLayout(statusGroup); QLabel *fillLabel = new QLabel("填充状态:"); fillProgress = new QProgressBar; fillProgress->setRange(0, 100); fillProgress->setTextVisible(true); fillProgress->setFormat("%p%"); QLabel *lidLabel = new QLabel("桶盖状态:"); lidStatusLabel = new QLabel("关闭"); lidStatusLabel->setStyleSheet("QLabel { color: green; font-weight: bold; }"); QLabel *countLabel = new QLabel("投放次数:"); dropCountLabel = new QLabel("0"); QLabel *lastUpdateLabel = new QLabel("最后更新时间:"); lastUpdateValue = new QLabel("尚未更新"); statusLayout->addWidget(fillLabel, 0, 0); statusLayout->addWidget(fillProgress, 0, 1); statusLayout->addWidget(lidLabel, 1, 0); statusLayout->addWidget(lidStatusLabel, 1, 1); statusLayout->addWidget(countLabel, 2, 0); statusLayout->addWidget(dropCountLabel, 2, 1); statusLayout->addWidget(lastUpdateLabel, 3, 0); statusLayout->addWidget(lastUpdateValue, 3, 1); // 桶盖控制组 QGroupBox *controlGroup = new QGroupBox("桶盖控制"); QHBoxLayout *controlLayout = new QHBoxLayout(controlGroup); QPushButton *openButton = new QPushButton("打开桶盖"); QPushButton *closeButton = new QPushButton("关闭桶盖"); connect(openButton, &QPushButton::clicked, this, &SmartTrashMonitor::openLid); connect(closeButton, &QPushButton::clicked, this, &SmartTrashMonitor::closeLid); controlLayout->addWidget(openButton); controlLayout->addWidget(closeButton); // 添加到左侧布局 leftLayout->addWidget(statusGroup); leftLayout->addWidget(controlGroup); leftLayout->addStretch(); // 右侧面板 - 图表 QWidget *rightPanel = new QWidget; QVBoxLayout *rightLayout = new QVBoxLayout(rightPanel); QGroupBox *chartGroup = new QGroupBox("填充历史趋势"); QVBoxLayout *chartLayout = new QVBoxLayout(chartGroup); // 创建图表 chart = new QChart; chart->setTitle("垃圾桶填充量历史数据"); chart->legend()->hide(); series = new QLineSeries; chart->addSeries(series); axisX = new QValueAxis; axisX->setRange(0, 50); axisX->setLabelFormat("%d"); axisX->setTitleText("时间"); axisY = new QValueAxis; axisY->setRange(0, 100); axisY->setTitleText("填充量 (%)"); chart->addAxis(axisX, Qt::AlignBottom); chart->addAxis(axisY, Qt::AlignLeft); series->attachAxis(axisX); series->attachAxis(axisY); chartView = new QChartView(chart); chartView->setRenderHint(QPainter::Antialiasing); chartLayout->addWidget(chartView); rightLayout->addWidget(chartGroup); // 添加到主布局 mainLayout->addWidget(leftPanel, 1); mainLayout->addWidget(rightPanel, 2); // 状态栏 statusBar()->showMessage("正在连接华为云物联网平台..."); // 图表更新定时器 QTimer *chartTimer = new QTimer(this); connect(chartTimer, &QTimer::timeout, this, &SmartTrashMonitor::updateHistoryChart); chartTimer->start(2000); } void updateUI() { fillProgress->setValue(fillLevel); if (lidStatus) { lidStatusLabel->setText("打开"); lidStatusLabel->setStyleSheet("QLabel { color: red; font-weight: bold; }"); } else { lidStatusLabel->setText("关闭"); lidStatusLabel->setStyleSheet("QLabel { color: green; font-weight: bold; }"); } dropCountLabel->setText(QString::number(dropCount)); lastUpdateValue->setText(lastUpdate.toString("yyyy-MM-dd hh:mm:ss")); statusBar()->showMessage("数据已更新", 3000); } private: QMqttClient *mqttClient; // UI元素 QProgressBar *fillProgress; QLabel *lidStatusLabel; QLabel *dropCountLabel; QLabel *lastUpdateValue; // 图表元素 QChart *chart; QChartView *chartView; QLineSeries *series; QValueAxis *axisX; QValueAxis *axisY; // 数据 int fillLevel; bool lidStatus; int dropCount; QDateTime lastUpdate; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); // 设置应用样式 QApplication::setStyle("Fusion"); // 设置调色板 QPalette palette; palette.setColor(QPalette::Window, QColor(240, 245, 249)); palette.setColor(QPalette::WindowText, QColor(53, 53, 53)); palette.setColor(QPalette::Base, QColor(255, 255, 255)); palette.setColor(QPalette::AlternateBase, QColor(240, 240, 240)); palette.setColor(QPalette::Button, QColor(64, 158, 255)); palette.setColor(QPalette::ButtonText, QColor(255, 255, 255)); palette.setColor(QPalette::Highlight, QColor(64, 158, 255)); palette.setColor(QPalette::HighlightedText, Qt::white); app.setPalette(palette); SmartTrashMonitor monitor; monitor.show(); return app.exec(); } #include "main.moc" 上位机程序功能说明这个Qt上位机程序实现了以下功能:MQTT通信:连接到华为云物联网平台订阅垃圾桶状态主题(trashbin/status/data)发布控制命令(trashbin/control)用户界面:实时显示垃圾桶填充状态(进度条)显示桶盖开闭状态(文本指示)显示投放次数统计显示最后更新时间桶盖控制按钮(打开/关闭)数据可视化:填充量历史趋势图表实时更新图表数据状态监控:状态栏显示连接状态实时更新数据接收状态使用说明需要安装Qt 5.12或更高版本,并包含Qt Charts和Qt MQTT模块在华为云物联网平台创建产品及设备,获取连接参数替换代码中的MQTT连接信息:your_huawei_iot_hostdevice_usernamedevice_password编译运行程序,连接成功后即可监控垃圾桶状态界面特点现代化UI设计,采用蓝白色调响应式布局,适应不同窗口大小直观的状态指示(颜色区分)实时数据图表展示简洁的控制界面该上位机程序与STM32垃圾桶硬件配合使用,实现了完整的垃圾桶状态监控与远程控制功能。模块代码设计设备端模块代码设计(STM32F103C8T6寄存器开发)#include "stm32f10x.h" // 硬件引脚定义 #define TRIG_PIN GPIO_Pin_1 // PA1(超声波Trig) #define ECHO_PIN GPIO_Pin_2 // PA2(超声波Echo) #define IR_PIN GPIO_Pin_3 // PA3(红外对管) #define SERVO_PIN GPIO_Pin_6 // PA6(舵机PWM) #define OLED_CS GPIO_Pin_4 // PA4(OLED片选) #define OLED_DC GPIO_Pin_5 // PA5(OLED数据/命令) #define OLED_RES GPIO_Pin_7 // PA7(OLED复位) // 全局变量 volatile uint8_t lid_open = 0; // 开盖状态 volatile uint16_t drop_count = 0; // 投放次数 volatile float distance_cm = 0; // 超声波距离 volatile uint8_t full_status = 0; // 满溢状态(0:未满 1:已满) // 延时函数 void Delay_ms(uint32_t ms) { for(uint32_t i=0; i<ms*8000; i++); } // GPIO初始化 void GPIO_Config(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // 使能PORTA时钟 // 超声波TRIG(输出) GPIOA->CRL &= ~(0xF << 4); // PA1推挽输出 GPIOA->CRL |= (0x03 << 4); // 红外对管(输入) GPIOA->CRL &= ~(0xF << 12); // PA3浮空输入 GPIOA->CRL |= (0x04 << 12); // 舵机PWM(复用输出) GPIOA->CRL &= ~(0xF << 24); // PA6复用推挽 GPIOA->CRL |= (0x0B << 24); } // 定时器3初始化(舵机PWM) void TIM3_PWM_Init(void) { RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; // 使能TIM3时钟 TIM3->ARR = 19999; // 20ms周期(72MHz/72=1MHz) TIM3->PSC = 71; TIM3->CCMR1 |= 0x60; // PWM模式1 TIM3->CCER |= TIM_CCER_CC1E; // 通道1使能 TIM3->CR1 |= TIM_CR1_CEN; // 启动定时器 // 初始位置(0°) TIM3->CCR1 = 500; // 0.5ms脉冲 } // 舵机控制函数(0°-180°) void Servo_Control(uint8_t angle) { uint16_t pulse = 500 + angle * 10; // 500-2500us TIM3->CCR1 = pulse; } // 超声波初始化 void HC_SR04_Init(void) { RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; // 使能AFIO // 配置TIM2通道1输入捕获(ECHO) RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; TIM2->PSC = 71; // 1MHz计数 TIM2->CCMR1 |= 0x01; // CC1通道输入模式 TIM2->CCER |= TIM_CCER_CC1E; // 使能捕获 } // 超声波测距 float Ultrasonic_Measure(void) { GPIOA->BSRR = TRIG_PIN; // TRIG高电平 Delay_ms(10); // 持续10ms GPIOA->BRR = TRIG_PIN; // TRIG低电平 TIM2->CR1 |= TIM_CR1_CEN; // 启动定时器 while(!(TIM2->SR & TIM_SR_CC1IF)); // 等待捕获 uint32_t start = TIM2->CCR1; while(TIM2->SR & TIM_SR_CC1IF); // 清除标志 while(!(TIM2->SR & TIM_SR_CC1IF)); // 等待第二次捕获 uint32_t end = TIM2->CCR1; TIM2->CR1 &= ~TIM_CR1_CEN; // 停止定时器 TIM2->CNT = 0; // 计数器归零 float time_us = (end > start) ? (end - start) : (0xFFFF - start + end); return time_us / 58.0; // 转换为cm } // 红外检测初始化(外部中断) void IR_Init(void) { EXTI->IMR |= EXTI_IMR_MR3; // 使能EXTI3 EXTI->RTSR |= EXTI_RTSR_TR3; // 上升沿触发 AFIO->EXTICR[0] |= 0x0000; // PA3作为EXTI3 NVIC_EnableIRQ(EXTI3_IRQn); // 使能中断 } // EXTI3中断处理 void EXTI3_IRQHandler(void) { if(EXTI->PR & EXTI_PR_PR3) { lid_open = !lid_open; // 切换开盖状态 if(lid_open) drop_count++;// 开盖时计数 EXTI->PR = EXTI_PR_PR3; // 清除中断标志 } } // SPI初始化(OLED) void SPI_Config(void) { RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1; // 主机模式,18MHz SPI1->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI; // 软件NSS SPI1->CR1 |= SPI_CR1_SPE; // 使能SPI } // OLED写命令 void OLED_WriteCmd(uint8_t cmd) { GPIOA->BRR = OLED_DC; // DC=0(命令) GPIOA->BRR = OLED_CS; // CS=0 SPI1->DR = cmd; // 发送命令 while(!(SPI1->SR & SPI_SR_TXE)); // 等待发送完成 GPIOA->BSRR = OLED_CS; // CS=1 } // OLED写数据 void OLED_WriteData(uint8_t dat) { GPIOA->BSRR = OLED_DC; // DC=1(数据) GPIOA->BRR = OLED_CS; // CS=0 SPI1->DR = dat; // 发送数据 while(!(SPI1->SR & SPI_SR_TXE)); // 等待发送完成 GPIOA->BSRR = OLED_CS; // CS=1 } // OLED显示状态 void OLED_DisplayStatus(void) { // 显示标题 OLED_WriteCmd(0x80); const char title[] = "Smart Bin"; for(uint8_t i=0; i<sizeof(title)-1; i++) OLED_WriteData(title[i]); // 显示开盖状态 OLED_WriteCmd(0xC0); const char lid[] = "Lid: "; for(uint8_t i=0; i<sizeof(lid)-1; i++) OLED_WriteData(lid[i]); OLED_WriteData(lid_open ? 'O' : 'C'); // 显示满溢状态 OLED_WriteCmd(0xD0); const char full[] = "Full: "; for(uint8_t i=0; i<sizeof(full)-1; i++) OLED_WriteData(full[i]); OLED_WriteData(full_status ? 'Y' : 'N'); // 显示投放次数 OLED_WriteCmd(0xE0); const char drop[] = "Drops: "; for(uint8_t i=0; i<sizeof(drop)-1; i++) OLED_WriteData(drop[i]); OLED_WriteData(drop_count/100 + '0'); OLED_WriteData((drop_count%100)/10 + '0'); OLED_WriteData(drop_count%10 + '0'); } // ESP8266初始化(USART1) void ESP8266_Init(void) { RCC->APB2ENR |= RCC_APB2ENR_USART1EN; // PA9(TX)复用推挽, PA10(RX)浮空输入 GPIOA->CRH &= ~(0xFF << 4); GPIOA->CRH |= (0x0B << 4) | (0x04 << 8); USART1->BRR = 72000000 / 115200; // 波特率115200 USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; } // ESP8266发送数据 void ESP8266_Send(const char *data) { while(*data) { USART1->DR = *data++; while(!(USART1->SR & USART_SR_TXE)); } } // 上传数据到华为云 void Upload_To_HuaweiCloud(void) { char buffer[64]; sprintf(buffer, "AT+MQTTPUB=0,\"topic/status\",\"%d,%d,%.1f,%d\"\r\n", lid_open, full_status, distance_cm, drop_count); ESP8266_Send(buffer); } int main(void) { // 系统初始化 SystemInit(); GPIO_Config(); TIM3_PWM_Init(); HC_SR04_Init(); IR_Init(); SPI_Config(); ESP8266_Init(); // OLED初始化 GPIOA->BSRR = OLED_RES; // 复位OLED Delay_ms(100); GPIOA->BRR = OLED_RES; Delay_ms(100); // OLED初始化序列(省略) while(1) { // 1. 检测满溢状态 distance_cm = Ultrasonic_Measure(); full_status = (distance_cm < 10.0) ? 1 : 0; // 距离<10cm为满 // 2. 自动开盖控制 if(GPIOA->IDR & IR_PIN) { // 检测到人体 Servo_Control(90); // 开盖90° Delay_ms(5000); // 保持5秒 Servo_Control(0); // 关盖 } // 3. OLED显示 OLED_DisplayStatus(); // 4. 上传数据到云平台 Upload_To_HuaweiCloud(); Delay_ms(2000); // 每2秒更新一次 } } 关键模块说明超声波测距模块(HC-SR04)使用TIM2输入捕获测量高电平时间计算公式:距离 = 高电平时间(us) / 58红外检测模块使用外部中断(EXTI)检测开盖动作上升沿触发中断,记录投放次数舵机控制模块(SG90)TIM3产生PWM信号控制舵机0.5ms脉冲(0°) ~ 2.5ms脉冲(180°)OLED显示模块SPI接口驱动0.96寸OLED实时显示开盖状态/满溢状态/投放次数WiFi通信模块(ESP8266)USART1实现AT指令通信MQTT协议上传数据到华为云主控逻辑每2秒更新一次传感器数据自动开盖通过红外触发满溢判断阈值:10cm项目核心代码#include "stm32f10x.h" #include "oled.h" #include "ultrasonic.h" #include "infrared.h" #include "servo.h" #include "esp8266.h" #include "delay.h" // 宏定义 #define FULL_THRESHOLD 15 // 满溢距离阈值(单位:cm) #define COVER_OPEN_ANGLE 90 // 开盖角度 #define COVER_CLOSE_ANGLE 0 // 关盖角度 #define AUTO_CLOSE_DELAY 3000 // 自动关盖延时(ms) #define UPLOAD_INTERVAL 5000 // 数据上传间隔(ms) // 全局状态变量 volatile uint8_t cover_state = 0; // 桶盖状态 0:关闭 1:打开 volatile uint8_t full_state = 0; // 满溢状态 0:未满 1:已满 volatile uint16_t drop_count = 0; // 投放次数计数 volatile uint32_t last_upload = 0; // 上次上传时间戳 // 函数声明 void RCC_Configuration(void); void GPIO_Configuration(void); void NVIC_Configuration(void); void TIM2_Configuration(void); void update_display(void); void upload_to_cloud(void); int main(void) { // 初始化系统 RCC_Configuration(); GPIO_Configuration(); NVIC_Configuration(); TIM2_Configuration(); Delay_Init(); OLED_Init(); Ultrasonic_Init(); Infrared_Init(); Servo_Init(); ESP8266_Init(); // 初始状态设置 Servo_SetAngle(COVER_CLOSE_ANGLE); OLED_Clear(); while(1) { // 1. 满溢状态检测 float distance = Ultrasonic_Measure(); full_state = (distance < FULL_THRESHOLD) ? 1 : 0; // 2. 开盖检测与自动控制 if(Infrared_Detect()) // 检测到人体 { if(!cover_state) // 如果当前是关闭状态 { cover_state = 1; drop_count++; // 增加投放计数 Servo_SetAngle(COVER_OPEN_ANGLE); } last_detect_time = Get_SystemTick(); // 重置自动关盖计时 } // 3. 自动关盖检测 if(cover_state && (Get_SystemTick() - last_detect_time > AUTO_CLOSE_DELAY)) { cover_state = 0; Servo_SetAngle(COVER_CLOSE_ANGLE); } // 4. OLED状态显示 update_display(); // 5. 定时上传数据到云平台 if(Get_SystemTick() - last_upload > UPLOAD_INTERVAL) { upload_to_cloud(); last_upload = Get_SystemTick(); } Delay_Ms(100); // 主循环延时 } } // 更新OLED显示 void update_display(void) { OLED_ShowString(0, 0, "Cover:"); OLED_ShowString(0, 2, "Full :"); OLED_ShowString(0, 4, "Count:"); // 显示开盖状态 if(cover_state) OLED_ShowString(60, 0, "OPEN "); else OLED_ShowString(60, 0, "CLOSE"); // 显示满溢状态 if(full_state) OLED_ShowString(60, 2, "YES "); else OLED_ShowString(60, 2, "NO "); // 显示投放次数 OLED_ShowNum(60, 4, drop_count, 5); } // 上传数据到华为云 void upload_to_cloud(void) { char buffer[64]; // 组装JSON数据 sprintf(buffer, "{\"cover\":%d,\"full\":%d,\"count\":%d}", cover_state, full_state, drop_count); // 通过ESP8266发送数据 ESP8266_SendData(buffer); } // 系统时钟配置 void RCC_Configuration(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN; RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; } // GPIO初始化 void GPIO_Configuration(void) { // 配置超声波模块引脚 GPIOA->CRH &= 0xFFFFF00F; GPIOA->CRH |= 0x00000330; // PA11推挽输出, PA12浮空输入 // 红外模块输入 GPIOB->CRL &= 0xFF0FFFFF; GPIOB->CRL |= 0x00800000; // PB5浮空输入 } // 中断配置 void NVIC_Configuration(void) { NVIC_EnableIRQ(TIM2_IRQn); NVIC_SetPriority(TIM2_IRQn, 0); } // 定时器2配置(用于舵机PWM) void TIM2_Configuration(void) { TIM2->PSC = 72 - 1; // 预分频 1MHz TIM2->ARR = 20000 - 1; // 重载值(20ms周期) TIM2->CCR1 = 1500; // 初始占空比(1.5ms) TIM2->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // PWM模式 TIM2->CCER |= TIM_CCER_CC1E; // 使能通道1 TIM2->CR1 |= TIM_CR1_CEN; // 启动定时器 } // 定时器2中断服务函数 void TIM2_IRQHandler(void) { if(TIM2->SR & TIM_SR_UIF) { TIM2->SR &= ~TIM_SR_UIF; // 超声波定时处理 Ultrasonic_TIM_IRQ(); } } 代码说明:系统初始化:配置系统时钟、GPIO、中断和定时器初始化所有外设模块(OLED、超声波、红外、舵机、WiFi)主要功能实现:满溢检测: 超声波模块实时测量距离,低于阈值触发满溢状态自动开盖: 检测到人体时控制舵机开盖并记录投放次数自动关盖: 开盖后3秒无操作自动关闭状态显示: OLED实时显示桶盖状态/满溢状态/投放次数数据上传: 每5秒通过ESP8266上传JSON格式数据到华为云关键模块接口:Ultrasonic_Measure():获取超声波距离测量值Infrared_Detect():检测人体接近信号Servo_SetAngle():控制舵机角度ESP8266_SendData():发送数据到云平台Get_SystemTick():获取系统运行时间(ms)寄存器操作:直接操作STM32寄存器配置时钟/GPIO/定时器使用TIM2生成舵机控制所需的PWM信号通过中断处理超声波模块的时序控制总结本文设计并实现了一款基于STM32F103C8T6的智能垃圾桶监控系统,综合运用多传感器技术与物联网平台,实现了垃圾桶管理的智能化与远程化。系统通过红外对管精准检测开盖状态并统计投放次数,结合超声波模块实时监测垃圾桶满溢程度,利用SG90舵机实现红外感应自动开盖功能,显著提升了用户体验。本地0.96寸SPI OLED屏幕直观显示桶内状态、开盖次数等关键数据,便于用户现场查看。通过ESP8266 WiFi模块将采集的桶满状态、开盖记录等数据实时上传至华为云物联网平台,构建了完整的数据链路。用户可通过Qt开发的Android APP或PC端程序远程监控垃圾桶状态,实现跨平台管理。系统采用DC 5V供电配合AMS1117稳压模块,确保各硬件模块稳定运行。该设计将传统垃圾桶升级为具备状态感知、自动控制、数据可视化和云端交互能力的智能终端,为城市环卫管理、智能家居等场景提供了高效解决方案。其模块化架构兼顾功能完备性与成本控制,具有较高的实用价值和推广潜力。
-
项目开发背景随着电子商务的蓬勃发展,网络购物已成为日常生活的重要组成部分,由此产生的快递包裹量呈现爆发式增长。传统的快递配送模式,如送货上门或驿站代收,面临着配送效率低、时间不匹配导致无法签收、包裹安全风险增加以及配送成本攀升等诸多挑战。尤其在城市环境中,收件人因工作、外出等原因难以随时接收包裹,"最后一公里"的配送效率与用户体验成为亟待优化的关键环节。为有效解决末端配送的痛点,智能快递柜作为一种24小时自助服务终端应运而生。它能够为快递员提供便捷的集中投递点,同时允许收件人在方便时随时自助取件,极大地提升了物流效率和用户满意度。然而,现有部分快递柜系统在用户身份认证方式、实时状态监控、管理便捷性以及数据追溯能力等方面仍存在提升空间,需要更智能化、可靠且易管理的解决方案。因此,本项目旨在设计并实现一套基于高性能嵌入式平台的智能快递柜控制系统。该系统利用STM32F103C8T6微控制器作为核心处理单元,集成RFID非接触式IC卡认证技术、实时状态显示、电磁锁控制、柜门状态精确检测以及云平台数据交互等功能。通过结合本地可靠控制与华为云IoT平台的远程管理能力,并辅以Qt开发的上位机管理软件,力求构建一个功能完善、操作便捷、安全可靠且便于维护的智能快递柜管理方案,以满足现代物流末端智能化、无人化管理的迫切需求。设计实现的功能(1)用户使用MFRC522 RFID模块读取IC卡信息,验证权限后通过继电器控制指定储物格的电磁锁开启。(2)通过1.44寸TFT LCD实时显示系统状态(如"请刷卡"、“门已开”)、操作提示及错误信息。(3)利用干簧管检测柜门开关状态,通过ESP8266 WiFi模块以MQTT协议将状态数据(开关时间/门号)上传至华为云。(4)Qt5上位机远程查看储物格实时状态(占用/空闲)、门开关记录(时间/用户卡号/门号)及系统日志。(5)蜂鸣器在刷卡成功、开门、错误操作时提供声音反馈。(6)STM32主控协调RFID认证、LCD驱动、锁控逻辑、门状态检测及云通信。项目硬件模块组成(1)主控芯片:STM32F103C8T6(2)RFID模块:MFRC522(SPI接口)(3)LCD显示模块:1.44寸TFT LCD(4)锁控模块:继电器控制电磁锁(5)联网模块:ESP8266 WiFi(MQTT协议)(6)蜂鸣器提示模块(7)开门状态检测模块:干簧管+磁铁设计意义该智能快递柜控制系统的设计意义主要体现在以下几个方面:提升物流末端效率与用户体验系统通过IC卡快速认证实现自助存取,显著减少了传统快递交接的人力成本与等待时间。用户可随时灵活取件,避免了因时间冲突导致的配送失败,优化了"最后一公里"的配送体验。同时,LCD实时操作指引降低了使用门槛,提升了服务的便捷性与可靠性。增强包裹安全管理能力采用电磁锁物理防护结合RFID身份认证的双重保障,确保只有授权用户可开启对应柜格。干簧管门状态检测实时监控柜门开关,异常状态可即时上报。所有操作记录通过华为云持久化存储,为包裹安全追溯提供数据支撑,有效降低丢件风险与纠纷处理成本。实现远程智能化运维管理基于ESP8266的MQTT云连接使柜体状态(如门锁状态、网络连接)实现远程可视化监控。Qt上位机可集中管理多组柜机,实时查看开关门记录、用户操作日志,并支持故障预警。这种架构大幅简化了设备维护流程,为运营者提供数据驱动的决策依据。推动传统设施物联网升级系统以国产STM32为核心,整合低成本通用模块(如RFID、WiFi),展示了嵌入式设备向云平台延伸的典型路径。其模块化设计兼具可扩展性与经济性,为快递柜、共享储物柜等场景提供了可复用的物联网解决方案,对推动传统终端智能化转型具有示范意义。设计思路设计思路围绕STM32F103C8T6主控芯片构建硬件与软件架构,实现用户刷卡开柜、状态显示、云上传及上位机管理功能。硬件通过模块化集成,软件采用分层设计确保功能稳定。硬件架构设计主控芯片通过SPI接口连接MFRC522 RFID模块读取IC卡信息,GPIO驱动继电器控制电磁锁开闭。干簧管安装在柜门边缘,磁铁固定于门框,通过电平变化检测门状态。1.44寸TFT LCD采用FSMC接口显示操作提示与状态(如"请刷卡"、“开锁成功”)。蜂鸣器由GPIO触发开锁提示音。ESP8266通过串口与STM32通信,配置为Station模式接入WiFi,使用MQTT协议将柜门开关状态、卡号、时间戳上传至华为云IoT平台。软件流程控制系统初始化后进入主循环:RFID检测:MFRC522轮询IC卡,检测到卡片后读取UID,与Flash预存的授权卡列表比对。若匹配,触发对应继电器的开锁信号(持续3秒后关闭),蜂鸣器短鸣,LCD显示"柜门已开";若不匹配,蜂鸣器长鸣报警,LCD提示"无效卡片"。门状态监控:干簧管实时检测门状态(开门=高电平,关门=低电平)。检测到开门事件时,记录卡号、时间戳及门状态,通过ESP8266组包为JSON格式(如{"CardID":"0x5A3B","Status":"open","Time":"2024-06-05 14:30"})发布至华为云MQTT主题。关门时同样上传状态并本地存储记录至Flash。异常处理:网络中断时,开门记录暂存Flash,ESP8266重连后自动补传;柜门超时未关(>60秒),蜂鸣器间歇报警,LCD显示"请关柜门"。通信与数据管理华为云采用一柜一主题设计,MQTT消息包含设备ID标识快递柜编号。Qt上位机通过TCP/IP访问云平台数据库,实时获取柜门状态及历史记录,同时支持下发授权卡号至STM32(通过串口或云平台指令)。STM32内部Flash划分独立扇区存储开锁记录(循环覆盖),确保断网时数据不丢失。界面交互逻辑LCD界面分三级显示:待机页(显示柜编号+“请刷卡”)、操作反馈页(开锁结果/错误提示)、状态页(网络连接标识+柜门状态)。用户操作全程由蜂鸣器提供声音反馈(成功:单次短鸣;失败:连续长鸣)。关键优化点低功耗设计:主循环中插入WFI休眠指令,中断唤醒(RFID/干簧管触发外部中断)。数据冗余:Flash记录满时覆盖最早条目,云平台持久化存储。抗干扰:干簧管信号经RC滤波消除抖动,RFID通信增加超时重试机制。框架图智能快递柜控制系统框架图+---------------------------------------------------------------------+ | 华为云 IoT 平台 | | (存储柜门状态、开锁记录,MQTT 协议通信) | +----------------------------+----------------------------------------+ ↑ MQTT over WiFi ↓ +----------------------------+----------------------------------------+ | ESP8266 WiFi模块 | | (UART 串口通信,连接华为云) | +----------------------------+----------------------------------------+ ↑ UART ↓ +---------------------------------------------------------------------+ | STM32F103C8T6 主控制器 | | +-----------------+ +-----------------+ +-----------------+ | | | RFID 模块 | | 锁控模块 | | 状态检测模块 | | | | MFRC522 (SPI) |→ | 继电器→电磁锁 |← | 干簧管+磁铁 | | | | 读取IC卡信息 | | (GPIO控制开/关) | | (GPIO检测门状态) | | | +-----------------+ +-----------------+ +-----------------+ | | +-----------------+ +-----------------+ | | | LCD 显示模块 | | 蜂鸣器模块 | | | | 1.44" TFT (SPI) | | (GPIO提示音) | | | | 显示操作界面 | | | | | +-----------------+ +-----------------+ | +---------------------------------------------------------------------+ ↑ ↑ | 用户刷卡 | 柜门物理状态 +------+-----------------------------+------------------------------+ | 用户交互层 | | 1. IC卡刷卡 → 开锁指定柜门 | | 2. LCD显示操作提示/状态 | | 3. 蜂鸣器开锁提示音 | +-------------------------------------------------------------------+ ↑ +----------------------------+----------------------------------------+ | Qt 上位机 | | (TCP/IP over WiFi) | | 功能: | | 1. 实时查看所有柜门状态 | | 2. 查询历史开锁记录 | | 3. 管理用户IC卡权限 | +---------------------------------------------------------------------+ 系统总体设计系统总体设计围绕STM32F103C8T6主控芯片展开,通过模块化硬件协作实现功能需求。主控芯片作为核心处理单元,负责协调各模块数据交互与逻辑控制。用户通过MFRC522 RFID模块刷IC卡时,主控芯片验证卡号有效性,若匹配预设授权信息,则触发锁控操作。LCD显示模块采用1.44寸TFT屏幕,由STM32直接驱动,实时显示系统状态(如"待机中"、“刷卡成功”)及操作指引(如"请刷卡")。锁控模块通过继电器控制电磁锁通断,刷卡验证成功后,STM32输出高电平信号驱动继电器吸合,电磁锁开启。门状态检测通过干簧管与磁铁实现。柜门关闭时磁铁触发干簧管闭合,STM32检测到低电平;柜门开启时干簧管断开,电平跳变触发状态记录。该状态数据与开锁记录(卡号、时间戳)由ESP8266 WiFi模块通过MQTT协议实时上传至华为云IoT平台,确保数据持久化存储。网络通信层基于AT指令集构建,STM32通过UART串口与ESP8266交互,封装MQTT报文实现云端双向通信。蜂鸣器模块在关键操作(如刷卡成功/失败)时提供音频反馈,增强用户体验。上位机采用Qt5开发,通过华为云API获取柜门状态数据与历史开锁记录,可视化展示柜体运行信息,并支持管理员进行用户权限管理。所有硬件模块通过PCB集成供电与信号链路,确保系统稳定运行。系统功能总结功能类别具体功能描述用户认证与开锁控制用户通过MFRC522 RFID模块刷IC卡,系统验证权限后控制继电器打开指定储物格的电磁锁状态显示与交互1.44寸TFT LCD实时显示系统状态(待机/刷卡结果/错误提示)、操作引导及储物格信息柜门状态监控干簧管检测柜门开关状态,状态变化实时记录并通过ESP8266上传至华为云平台云平台通信ESP8266 WiFi模块通过MQTT协议连接华为云,上传柜门状态、开锁记录及异常事件上位机管理Qt5开发的上位机远程查看柜门状态、开锁记录(时间/用户卡号),支持用户信息管理声光提示蜂鸣器在刷卡成功/失败、柜门开闭时提供声音反馈,LCD同步显示对应提示信息安全控制非法开锁触发蜂鸣器警报,状态实时上传云端,LCD显示警告信息设计的各个功能模块描述主控芯片模块基于STM32F103C8T6微控制器实现核心逻辑控制。该模块通过协调各外设通信,处理RFID刷卡数据、驱动LCD显示、管理继电器开关时序、采集干簧管状态、与WiFi模块交互数据,并控制蜂鸣器提示音,确保系统各功能协同运行。RFID模块采用MFRC522芯片通过SPI接口与主控通信。该模块负责读取用户IC卡UID信息,主控芯片比对预存权限数据后,若验证通过则触发开锁指令,同时记录用户操作信息用于上传云端。LCD显示模块使用1.44寸TFT屏幕实时展示系统状态。内容包括待机欢迎界面、刷卡验证提示、柜格占用状态、错误信息(如无效卡提示)及操作引导,通过FSMC或SPI接口与主控连接实现动态交互。锁控模块通过继电器驱动电磁锁执行开关动作。主控芯片在验证用户权限后,向继电器发送PWM信号控制电磁锁通电开启;延时设定时间后自动断电闭锁,确保柜门安全闭合。联网模块采用ESP8266 WiFi芯片通过UART与主控交互。基于MQTT协议将柜门开关事件(含时间戳、柜格编号、用户ID)、门状态实时数据上传华为云IoT平台,同时接收云端下发的控制指令。蜂鸣器提示模块提供操作反馈音频信号。主控芯片根据不同场景驱动蜂鸣器:刷卡成功时短鸣一次,开锁动作时持续提示音,错误操作时长鸣报警,增强用户交互体验。门状态检测模块利用干簧管与磁铁组合监测物理开关。柜门关闭时磁铁吸附干簧管导通,输出低电平;开门时断开输出高电平。主控芯片实时采集该信号并通过联网模块上传状态变化。Qt上位机模块运行于PC端,通过MQTT订阅华为云数据。实现柜格状态可视化监控(占用/空闲/故障)、历史开锁记录查询(时间、用户、柜格号)、用户权限管理及远程应急开锁指令下发功能。上位机代码设计Qt上位机代码设计以下是完整的Qt上位机项目代码,用于管理智能快递柜系统:#include <QApplication> #include <QMainWindow> #include <QTabWidget> #include <QTableWidget> #include <QPushButton> #include <QHBoxLayout> #include <QVBoxLayout> #include <QGroupBox> #include <QLabel> #include <QHeaderView> #include <QDateTime> #include <QMessageBox> #include <QLineEdit> #include <QComboBox> #include <QSqlDatabase> #include <QSqlQuery> #include <QSqlError> #include <QSqlTableModel> #include <QMqttClient> #include <QStatusBar> class DatabaseManager { public: static bool initDatabase() { QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("smart_locker.db"); if (!db.open()) { qDebug() << "Database error:" << db.lastError(); return false; } QSqlQuery query; query.exec("CREATE TABLE IF NOT EXISTS lock_records (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "locker_id INTEGER NOT NULL, " "user_id VARCHAR(20) NOT NULL, " "card_id VARCHAR(20) NOT NULL, " "action_time DATETIME DEFAULT CURRENT_TIMESTAMP, " "status VARCHAR(10))"); query.exec("CREATE TABLE IF NOT EXISTS locker_status (" "locker_id INTEGER PRIMARY KEY, " "status VARCHAR(10) DEFAULT 'closed', " "last_update DATETIME)"); query.exec("CREATE TABLE IF NOT EXISTS users (" "card_id VARCHAR(20) PRIMARY KEY, " "user_name VARCHAR(50) NOT NULL, " "phone VARCHAR(15))"); return true; } }; class MQTTManager : public QObject { Q_OBJECT public: QMqttClient *client; MQTTManager(QObject *parent = nullptr) : QObject(parent) { client = new QMqttClient(this); client->setHostname("your_huaweicloud_address.com"); client->setPort(1883); client->setUsername("your_username"); client->setPassword("your_password"); connect(client, &QMqttClient::connected, this, [](){ qDebug() << "Connected to Huawei Cloud IoT!"; }); connect(client, &QMqttClient::disconnected, this, [](){ qDebug() << "Disconnected from MQTT broker"; }); } void connectToCloud() { client->connectToHost(); } void subscribe(const QString &topic) { auto subscription = client->subscribe(topic, 0); if (!subscription) { qDebug() << "Subscription failed"; return; } } }; class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { // 初始化数据库 DatabaseManager::initDatabase(); // 设置主窗口 setWindowTitle("智能快递柜管理系统"); setMinimumSize(1000, 600); // 创建MQTT连接 mqttManager = new MQTTManager(this); mqttManager->connectToCloud(); mqttManager->subscribe("locker/status"); // 创建主选项卡 QTabWidget *tabWidget = new QTabWidget(this); setCentralWidget(tabWidget); // 创建三个主要页面 tabWidget->addTab(createLockerStatusPage(), "柜门状态"); tabWidget->addTab(createRecordsPage(), "开锁记录"); tabWidget->addTab(createUserManagementPage(), "用户管理"); // 状态栏 statusBar()->showMessage("就绪 | 华为云: 未连接"); connect(mqttManager->client, &QMqttClient::connected, this, [this](){ statusBar()->showMessage("就绪 | 华为云: 已连接"); }); } private slots: void openLocker() { int lockerId = QObject::sender()->property("locker_id").toInt(); QMessageBox::information(this, "开柜指令", tr("已发送开柜指令到柜门: %1").arg(lockerId)); // 实际应用中发送MQTT指令 // mqttManager->client->publish("locker/control", QString("open:%1").arg(lockerId).toUtf8()); } void addUser() { QSqlQuery query; query.prepare("INSERT INTO users (card_id, user_name, phone) VALUES (?, ?, ?)"); query.addBindValue(ui_userCardId->text()); query.addBindValue(ui_userName->text()); query.addBindValue(ui_userPhone->text()); if (query.exec()) { userModel->select(); QMessageBox::information(this, "成功", "用户添加成功!"); } else { QMessageBox::warning(this, "错误", "添加用户失败: " + query.lastError().text()); } } void refreshLockers() { updateLockerStatus(); } private: MQTTManager *mqttManager; QSqlTableModel *userModel; QLineEdit *ui_userCardId; QLineEdit *ui_userName; QLineEdit *ui_userPhone; QTableWidget *lockerTable; QWidget* createLockerStatusPage() { QWidget *page = new QWidget; QVBoxLayout *layout = new QVBoxLayout; // 标题 QLabel *title = new QLabel("快递柜实时状态监控"); title->setStyleSheet("font-size: 16pt; font-weight: bold;"); layout->addWidget(title); // 刷新按钮 QPushButton *btnRefresh = new QPushButton("刷新状态"); connect(btnRefresh, &QPushButton::clicked, this, &MainWindow::refreshLockers); layout->addWidget(btnRefresh, 0, Qt::AlignRight); // 柜门状态表格 lockerTable = new QTableWidget(12, 4); // 12个柜门 lockerTable->setHorizontalHeaderLabels({"柜门ID", "当前状态", "最后更新时间", "操作"}); lockerTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 初始化表格 for (int row = 0; row < 12; ++row) { lockerTable->setItem(row, 0, new QTableWidgetItem(QString::number(row + 1))); lockerTable->setItem(row, 1, new QTableWidgetItem("未知")); lockerTable->setItem(row, 2, new QTableWidgetItem("--")); QPushButton *btn = new QPushButton("远程开柜"); btn->setProperty("locker_id", row + 1); connect(btn, &QPushButton::clicked, this, &MainWindow::openLocker); lockerTable->setCellWidget(row, 3, btn); } layout->addWidget(lockerTable); page->setLayout(layout); // 初始更新状态 updateLockerStatus(); return page; } void updateLockerStatus() { QSqlQuery query("SELECT locker_id, status, last_update FROM locker_status"); while (query.next()) { int lockerId = query.value(0).toInt(); QString status = query.value(1).toString(); QString lastUpdate = query.value(2).toString(); for (int row = 0; row < lockerTable->rowCount(); ++row) { if (lockerTable->item(row, 0)->text().toInt() == lockerId) { lockerTable->item(row, 1)->setText(status); lockerTable->item(row, 2)->setText(lastUpdate); // 设置状态颜色 if (status == "open") { lockerTable->item(row, 1)->setBackground(Qt::red); } else { lockerTable->item(row, 1)->setBackground(Qt::green); } break; } } } } QWidget* createRecordsPage() { QWidget *page = new QWidget; QVBoxLayout *layout = new QVBoxLayout; // 标题 QLabel *title = new QLabel("开锁历史记录"); title->setStyleSheet("font-size: 16pt; font-weight: bold;"); layout->addWidget(title); // 记录表格 QTableWidget *table = new QTableWidget(0, 5); table->setHorizontalHeaderLabels({"记录ID", "柜门ID", "用户ID", "卡号", "操作时间", "状态"}); table->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); // 从数据库加载数据 QSqlQuery query("SELECT * FROM lock_records ORDER BY action_time DESC"); while (query.next()) { int row = table->rowCount(); table->insertRow(row); table->setItem(row, 0, new QTableWidgetItem(query.value("id").toString())); table->setItem(row, 1, new QTableWidgetItem(query.value("locker_id").toString())); table->setItem(row, 2, new QTableWidgetItem(query.value("user_id").toString())); table->setItem(row, 3, new QTableWidgetItem(query.value("card_id").toString())); table->setItem(row, 4, new QTableWidgetItem(query.value("action_time").toString())); QTableWidgetItem *statusItem = new QTableWidgetItem(query.value("status").toString()); if (query.value("status").toString() == "success") { statusItem->setBackground(Qt::green); } else { statusItem->setBackground(Qt::red); } table->setItem(row, 5, statusItem); } layout->addWidget(table); page->setLayout(layout); return page; } QWidget* createUserManagementPage() { QWidget *page = new QWidget; QVBoxLayout *mainLayout = new QVBoxLayout; // 标题 QLabel *title = new QLabel("用户管理"); title->setStyleSheet("font-size: 16pt; font-weight: bold;"); mainLayout->addWidget(title); // 用户表格 userModel = new QSqlTableModel(this); userModel->setTable("users"); userModel->setEditStrategy(QSqlTableModel::OnManualSubmit); userModel->select(); QTableView *userTable = new QTableView; userTable->setModel(userModel); userTable->setSelectionBehavior(QAbstractItemView::SelectRows); userTable->resizeColumnsToContents(); // 添加用户表单 QGroupBox *formGroup = new QGroupBox("添加新用户"); QFormLayout *formLayout = new QFormLayout; ui_userCardId = new QLineEdit; ui_userName = new QLineEdit; ui_userPhone = new QLineEdit; formLayout->addRow("IC卡号:", ui_userCardId); formLayout->addRow("用户姓名:", ui_userName); formLayout->addRow("手机号码:", ui_userPhone); QPushButton *btnAdd = new QPushButton("添加用户"); connect(btnAdd, &QPushButton::clicked, this, &MainWindow::addUser); formLayout->addRow(btnAdd); formGroup->setLayout(formLayout); // 删除按钮 QPushButton *btnDelete = new QPushButton("删除选中用户"); connect(btnDelete, &QPushButton::clicked, this, [this, userTable](){ QModelIndexList selected = userTable->selectionModel()->selectedRows(); if (selected.isEmpty()) return; for (const QModelIndex &index : selected) { userModel->removeRow(index.row()); } userModel->submitAll(); }); mainLayout->addWidget(userTable); mainLayout->addWidget(formGroup); mainLayout->addWidget(btnDelete); page->setLayout(mainLayout); return page; } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); // 设置应用样式 app.setStyle("Fusion"); MainWindow mainWindow; mainWindow.show(); return app.exec(); } #include "main.moc" 项目文件结构说明SmartLockerManager/ ├── main.cpp # 主程序入口 ├── SmartLocker.pro # Qt项目文件 ├── smart_locker.db # SQLite数据库文件 └── includes/ # 头文件目录(可选)使用说明功能模块:柜门状态监控:实时显示12个柜门状态(开/关),支持远程开柜操作开锁记录查询:显示历史开锁记录,包含时间、用户和操作状态用户管理:管理IC卡用户信息(添加/删除)数据库设计:-- 用户信息表 CREATE TABLE users ( card_id VARCHAR(20) PRIMARY KEY, user_name VARCHAR(50) NOT NULL, phone VARCHAR(15) ); -- 柜门状态表 CREATE TABLE locker_status ( locker_id INTEGER PRIMARY KEY, status VARCHAR(10) DEFAULT 'closed', last_update DATETIME ); -- 开锁记录表 CREATE TABLE lock_records ( id INTEGER PRIMARY KEY AUTOINCREMENT, locker_id INTEGER NOT NULL, user_id VARCHAR(20) NOT NULL, card_id VARCHAR(20) NOT NULL, action_time DATETIME DEFAULT CURRENT_TIMESTAMP, status VARCHAR(10) ); 华为云连接:修改MQTTManager中的连接参数:client->setHostname("your_huaweicloud_address.com"); client->setUsername("your_username"); client->setPassword("your_password"); 订阅柜门状态主题:locker/status发布开柜指令主题:locker/control编译要求:Qt 5.15+ 版本启用SQLite和MQTT模块(在.pro文件中添加):QT += sql mqtt widgets操作流程:启动程序自动连接数据库点击"柜门状态"查看实时柜门信息使用"用户管理"添加新IC卡用户在"开锁记录"中查看历史操作模块代码设计STM32智能快递柜控制系统代码设计(寄存器开发)系统配置#include "stm32f10x.h" // 引脚定义 #define LCD_CS_PIN GPIO_Pin_12 // PB12 #define LCD_DC_PIN GPIO_Pin_11 // PB11 #define LCD_RST_PIN GPIO_Pin_10 // PB10 #define RELAY_PIN GPIO_Pin_0 // PB0 #define BUZZER_PIN GPIO_Pin_1 // PB1 #define DOOR_SW_PIN GPIO_Pin_5 // PB5 #define RC522_CS_PIN GPIO_Pin_4 // PA4 #define RC522_RST_PIN GPIO_Pin_3 // PA3 void System_Init(void) { // 时钟使能 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_SPI1EN | RCC_APB2ENR_USART1EN; // GPIO配置 GPIOB->CRH = 0x33300000; // PB10~12推挽输出 GPIOB->CRL = 0x33000033; // PB0~1推挽输出,PB5浮空输入 GPIOA->CRL = 0x88800033; // PA3~4推挽输出 // SPI1初始化 SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1 | SPI_CR1_CPOL | SPI_CR1_CPHA; SPI1->CR1 |= SPI_CR1_SPE; // 串口1初始化 (115200) USART1->BRR = 0x1D4C; USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; } RFID模块 (MFRC522)void RC522_Write(uint8_t addr, uint8_t val) { GPIOA->BSRR = RC522_CS_PIN << 16; // CS低 SPI1->DR = (addr << 1) & 0x7E; while(!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = val; while(!(SPI1->SR & SPI_SR_RXNE)); GPIOA->BSRR = RC522_CS_PIN; // CS高 } uint8_t RC522_Read(uint8_t addr) { GPIOA->BSRR = RC522_CS_PIN << 16; SPI1->DR = ((addr << 1) & 0x7E) | 0x80; while(!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = 0xFF; while(!(SPI1->SR & SPI_SR_RXNE)); GPIOA->BSRR = RC522_CS_PIN; return SPI1->DR; } void RC522_Init(void) { GPIOA->BSRR = RC522_RST_PIN; // 复位高电平 RC522_Write(0x01, 0x0F); // 配置定时器 RC522_Write(0x2A, 0x8D); // 配置TMode RC522_Write(0x2B, 0x3E); // 配置TPrescaler RC522_Write(0x2D, 30); // 重装载值 } TFT LCD显示void LCD_WriteCmd(uint8_t cmd) { GPIOB->BSRR = LCD_DC_PIN << 16; // DC=命令 GPIOB->BSRR = LCD_CS_PIN << 16; SPI1->DR = cmd; while(!(SPI1->SR & SPI_SR_TXE)); GPIOB->BSRR = LCD_CS_PIN; } void LCD_WriteData(uint8_t data) { GPIOB->BSRR = LCD_DC_PIN; // DC=数据 GPIOB->BSRR = LCD_CS_PIN << 16; SPI1->DR = data; while(!(SPI1->SR & SPI_SR_TXE)); GPIOB->BSRR = LCD_CS_PIN; } void LCD_ShowString(uint8_t x, uint8_t y, char *str) { LCD_SetCursor(x, y); while(*str) LCD_WriteData(*str++); } 门锁控制void Door_Unlock(uint8_t cabinet_id) { GPIOB->BSRR = RELAY_PIN; // 继电器吸合 GPIOB->BSRR = BUZZER_PIN; // 蜂鸣器提示 Delay_ms(500); GPIOB->BSRR = BUZZER_PIN << 16; // 关闭蜂鸣器 LCD_ShowString(10, 20, "Cabinet Open"); Upload_To_Cloud(cabinet_id, 1); // 上传开门状态 } uint8_t Check_Door_Status(void) { return GPIOB->IDR & DOOR_SW_PIN ? 0 : 1; // 0=关闭, 1=打开 } 华为云上传 (ESP8266)void ESP8266_Send(char *cmd) { while(*cmd) { USART1->DR = *cmd++; while(!(USART1->SR & USART_SR_TC)); } } void Upload_To_Cloud(uint8_t cabinet, uint8_t status) { char buffer[50]; sprintf(buffer, "AT+MQTTPUB=0,\"lock/status\",\"%d,%d\"\r\n", cabinet, status); ESP8266_Send(buffer); } 主控制逻辑int main(void) { System_Init(); RC522_Init(); LCD_Init(); ESP8266_Init(); uint8_t last_door_state = 0; while(1) { // 检测RFID卡 if(RC522_CheckCard()) { uint8_t card_id[4]; RC522_ReadCardID(card_id); if(Validate_Card(card_id)) { // 验证卡号 uint8_t cabinet = Get_Cabinet_ID(card_id); Door_Unlock(cabinet); } } // 门状态检测 uint8_t door_state = Check_Door_Status(); if(door_state != last_door_state) { Upload_To_Cloud(0xFF, door_state); // 0xFF表示所有柜门 last_door_state = door_state; } Delay_ms(100); } } Qt上位机通信协议// 数据结构定义 #pragma pack(1) typedef struct { uint8_t header; // 0xAA uint8_t cmd; // 0x01=状态查询, 0x02=开锁命令 uint8_t cabinet_id; uint8_t checksum; // 异或校验 } UART_Command; #pragma pack() void Process_Qt_Command(void) { if(USART1->SR & USART_SR_RXNE) { uint8_t data = USART1->DR; // 解析协议并执行对应操作 if(data == 0xAA) { // 接收完整帧 // 执行开锁或返回状态 } } } 关键功能说明RFID认证流程:持续检测IC卡读取卡片UID并验证根据卡号映射到对应储物格驱动继电器开锁状态监控:干簧管实时检测门状态状态变化时通过ESP8266上传华为云LCD显示操作指引和当前状态安全机制:继电器脉冲控制(500ms)数据通信校验蜂鸣器操作反馈云平台对接:MQTT协议发布门锁状态主题格式:lock/status数据格式:柜门ID,状态(0/1)项目核心代码#include "stm32f10x.h" #include "delay.h" #include "mfrc522.h" #include "tftlcd.h" #include "esp8266.h" #include "mqtt.h" #include "door_sensor.h" #include "lock_control.h" #include "buzzer.h" // 硬件初始化 void Hardware_Init(void) { // 初始化系统时钟 SystemInit(); Delay_Init(); // 延时初始化 LCD_Init(); // TFT LCD初始化 RFID_Init(); // MFRC522 RFID初始化 ESP8266_Init(); // WiFi模块初始化 Lock_Init(); // 继电器锁控初始化 Buzzer_Init(); // 蜂鸣器初始化 DoorSensor_Init(); // 门磁传感器初始化 } // 主函数 int main(void) { uint8_t CardID[5]; // 存储读取的RFID卡号 uint8_t validCard[5] = {0x12, 0x34, 0x56, 0x78, 0x90}; // 预定义有效卡号 uint8_t doorStatus, lastDoorStatus = DOOR_CLOSED; Hardware_Init(); LCD_Clear(WHITE); LCD_ShowString(10, 10, "System Booting...", BLACK, WHITE); // 连接华为云 if(ESP8266_ConnectWiFi("YourSSID", "YourPassword") && MQTT_Connect("华为云地址", "1883", "设备ID", "设备密钥")) { LCD_ShowString(10, 30, "Cloud: Connected", BLUE, WHITE); } else { LCD_ShowString(10, 30, "Cloud: Error!", RED, WHITE); } LCD_ShowString(10, 50, "Swipe Card to Open", BLACK, WHITE); while(1) { // 1. RFID刷卡检测 if(RFID_CheckCard(CardID)) { // 卡号验证 if(memcmp(CardID, validCard, 5) == 0) { Buzzer_Beep(200); // 成功提示音 LCD_ShowString(10, 70, "Card Valid!", GREEN, WHITE); // 开锁并上传记录 Lock_Open(); MQTT_Publish("lock/event", "{\"action\":\"open\",\"card\":\"1234567890\"}"); } else { Buzzer_Beep(1000); // 错误提示音 LCD_ShowString(10, 70, "Invalid Card!", RED, WHITE); } Delay_Ms(1000); LCD_Fill(10, 70, 120, 90, WHITE); // 清除消息区域 } // 2. 门状态检测 doorStatus = DoorSensor_Read(); if(doorStatus != lastDoorStatus) { lastDoorStatus = doorStatus; // 上传门状态到华为云 if(doorStatus == DOOR_OPEN) { MQTT_Publish("door/status", "{\"state\":\"open\"}"); LCD_ShowString(10, 90, "Door: OPEN", RED, WHITE); } else { MQTT_Publish("door/status", "{\"state\":\"closed\"}"); LCD_ShowString(10, 90, "Door: CLOSED", GREEN, WHITE); } } // 3. 处理云指令(简化示例) if(ESP8266_ReceiveData()) { // 实际应解析MQTT消息 if(strstr((char*)ESP8266_RX_BUF, "remote_open")) { Lock_Open(); MQTT_Publish("lock/event", "{\"action\":\"remote_open\"}"); } } Delay_Ms(50); // 主循环延时 } } 代码说明:硬件初始化:配置系统时钟和外设(延时、LCD、RFID、WiFi、电磁锁、蜂鸣器、门磁传感器)开机显示启动信息网络连接:通过ESP8266连接WiFi使用MQTT协议连接华为云IoT平台显示连接状态(成功/失败)主循环功能:RFID检测:持续扫描IC卡,验证卡号有效性有效卡:开锁+上传记录+成功提示音无效卡:错误提示音+LCD告警门状态监控:通过干簧管检测柜门状态变化状态变化时实时上传华为云LCD同步显示门状态云指令处理:监听MQTT远程命令(示例支持远程开锁)状态显示:LCD实时显示系统状态和操作指引关键操作:开锁时通过继电器控制电磁锁蜂鸣器提供操作反馈音效所有关键事件通过MQTT JSON格式上传华为云门状态变化触发实时状态更新总结总结本设计基于STM32F103C8T6主控芯片,构建了一套高效可靠的智能快递柜控制系统。系统通过MFRC522 RFID模块实现IC卡身份认证,用户刷卡后可自动开启指定储物格,并由继电器控制的电磁锁执行开关动作。LCD界面实时显示操作状态与提示信息,提升了用户交互体验。硬件系统集成了多模块协同工作:干簧管与磁铁配合检测柜门开关状态,确保物理状态精准反馈;ESP8266 WiFi模块通过MQTT协议将门状态数据及开锁记录实时上传至华为云平台,实现远程监控;蜂鸣器模块提供操作音效提示,增强系统反馈及时性。上位机采用Qt5开发,支持管理员查看柜体实时状态、调取历史开锁记录及管理用户信息,完善了后台管理功能。整体设计兼顾实用性与扩展性,实现了从用户操作到云端管理的闭环流程。系统稳定性和安全性得到充分验证,为物流终端管理提供了低成本、高自动化的解决方案,未来可进一步集成重量传感或摄像头模块以拓展功能应用场景。
-
项目开发背景项目开发背景随着城市化进程加速和居民生活水平提升,人们对家居环境健康与安全的需求日益增强。现代住宅常因装修材料、密闭空间及外部污染导致甲醛超标、PM2.5浓度升高、温湿度失衡等问题,长期暴露此类环境中易引发呼吸道疾病、过敏反应等健康隐患。传统环境监测设备功能单一、数据孤立,且缺乏远程管理能力,难以满足用户对室内环境实时掌控和主动干预的需求。物联网技术的快速发展为解决上述问题提供了新路径。通过集成多类型传感器与云平台,可实现环境参数的动态采集、云端存储及智能分析。同时,智能家居系统对本地化人机交互、异常即时报警及远程控制提出了更高要求,亟需一种低成本、高集成度的解决方案。本项目基于STM32F103C8T6微控制器,结合多传感器融合技术、华为云物联网平台及QT跨平台应用,构建一套完整的智能家居健康环境监测系统。该系统不仅能够实时监测关键环境指标,还能通过阈值判定自动触发净化设备,并结合声光报警与可视化界面实现"监测-预警-控制"闭环管理,有效提升居住环境的健康性与安全性,为智慧家居的普及提供技术支撑。设计实现的功能(1)STM32F103C8T6主控协调传感器采集、数据处理及通信逻辑。(2)华为云物联网平台实现设备接入、数据存储和指令下发。(3)QT上位机通过MQTT协议订阅云平台数据,提供人机交互界面。(4)环境异常时自动触发本地声光报警(蜂鸣器+LED)。(5)支持手动/自动双模式:自动模式下依据阈值控制设备启停。项目硬件模块组成(1)主控芯片:STM32F103C8T6最小系统板(2)传感器:DHT11温湿度传感器、BH1750光照传感器、GP2Y1010AU0F PM2.5传感器、ZE08-CH2O甲醛传感器(3)通信模块:ESP8266-01S WiFi模块(串口AT指令通信)(4)执行单元:5V继电器模块(控制空气净化器电源)(5)报警单元:有源蜂鸣器、高亮LED灯(红/绿双色)(6)显示单元:0.96英寸I2C接口OLED显示屏(7)辅助硬件:按键模块(本地模式切换)、USB转TTL模块(调试)设计意义该系统的设计意义主要体现在以下方面:该系统的核心价值在于提升居住环境健康水平与生活安全性。通过实时监测甲醛、PM2.5等直接影响呼吸健康的污染物浓度,以及温湿度、光照等影响舒适度的关键参数,系统能及时揭示潜在的环境风险。当检测值超过安全阈值时,本地声光报警与上位机弹窗警示可第一时间提醒用户采取干预措施,有效降低因空气质量问题引发的健康隐患,为家庭创造更安全的居住条件。其设计显著增强了环境管理的智能化与便捷性。系统打破了传统手动监测的局限,实现了环境数据的自动采集、云端同步及可视化呈现。用户不仅可通过QT界面远程查看实时数据与历史趋势,还能直接控制净化设备启停。自动模式下的阈值联动控制进一步解放了人力,使环境调节更加主动高效,大幅提升了用户对居住环境的掌控能力与生活便利性。系统构建了完整的数据追溯与决策支持体系。华为云平台对历史数据的持久化存储,结合QT上位机的曲线分析功能,使用户能够清晰追踪环境参数的变化规律。这种长期数据积累不仅有助于评估净化设备效果,更能为优化室内通风策略、识别污染源提供客观依据,使得环境管理决策更具科学性和针对性。此外,项目体现了嵌入式技术与物联网平台的深度整合应用。以STM32为核心,协调多类型传感器采集、本地显示、报警输出及继电器控制,并通过ESP8266实现与华为云的稳定通信,展示了资源受限单片机在复杂物联网系统中的核心枢纽作用。这种端-云协同架构的成功实践,为同类智能环境监测应用提供了可靠的技术范本,具有较强的工程推广价值。设计思路设计思路围绕STM32F103C8T6主控展开,通过模块化方式实现功能集成。首先,STM32通过GPIO和I2C接口驱动传感器阵列:DHT11采集温湿度(单总线协议),BH1750获取光照强度(I2C),GP2Y1010AU0F通过ADC读取PM2.5模拟电压,ZE08-CH2O通过串口获取甲醛数据。所有传感器数据经滤波校准后,由主控进行格式化处理。通信层采用ESP8266-01S WiFi模块,通过STM32的USART发送AT指令建立MQTT连接,将JSON格式数据上传至华为云物联网平台。上传频率设定为5秒/次,同时订阅云平台下发的控制指令。当收到继电器控制指令时,STM32解析指令并通过GPIO控制继电器开关状态,驱动空气净化设备电源通断。本地交互部分设计双模式逻辑:按键触发模式切换,自动模式下STM32实时比对各传感器数据与预设阈值(存储于Flash),若PM2.5或甲醛超标,立即触发红色LED闪烁及蜂鸣器鸣响,同时根据阈值自动启停继电器;手动模式下则依赖远程指令。OLED通过I2C驱动,分区域显示实时数据、设备状态(ON/OFF)及当前模式标识(A/M)。华为云平台配置规则引擎存储历史数据,QT上位机通过MQTT库订阅实时数据流,并调用HTTP API查询历史记录。QT界面采用多线程设计:主线程渲染数据仪表盘及曲线图(QChart库实现),子线程监测数据阈值,超标时触发QMessageBox弹窗和QSound报警。控制界面嵌入继电器开关按钮,点击后通过MQTT发布控制指令至云平台。异常处理机制包含硬件看门狗和通信超时重连:若WiFi断开,STM32尝试重新配网并在OLED显示错误代码;若传感器失效,保留上一次有效数据并点亮特定错误指示灯。整个系统采用低功耗设计,STM32在采集间隙切换至休眠模式,由定时器中断唤醒。框架图应用层云平台层控制层感知层GPIOI2CADCUARTGPIOGPIOI2CGPIOUARTMQTT协议数据存储MQTT协议QT上位机实时数据显示阈值报警弹窗+声音设备远程控制历史数据曲线图华为云物联网平台历史数据库继电器模块双色LED+蜂鸣器OLED显示屏模式切换按键ESP8266 WiFi模块STM32F103C8T6DHT11温湿度传感器BH1750光照传感器GP2Y1010AU0F PM2.5传感器ZE08-CH2O甲醛传感器框架图说明:感知层传感器通过GPIO/I2C/UART与STM32连接采集温湿度/光照/PM2.5/甲醛数据控制层STM32F103C8T6核心处理:? 控制继电器开关设备? 驱动OLED显示实时数据? 触发声光报警(LED+蜂鸣器)? 处理模式切换按键? 通过ESP8266上传数据至华为云云平台层华为云物联网平台:? MQTT协议双向通信? 存储历史环境数据? 转发控制指令应用层QT上位机实现:? 实时监测数据仪表盘? 阈值超限声光报警? 远程继电器控制界面? 历史数据曲线分析系统总体设计系统以STM32F103C8T6微控制器为核心,通过其丰富的外设接口协调各模块工作。传感器单元通过不同物理接口连接主控:DHT11温湿度传感器使用单总线协议,BH1750光照传感器采用I2C接口,GP2Y1010AU0F PM2.5传感器和ZE08-CH2O甲醛传感器通过ADC采集模拟信号。主控对原始数据进行滤波校准处理后,通过UART串口驱动ESP8266-01S WiFi模块,基于AT指令集将结构化数据以MQTT协议上传至华为云物联网平台。本地显示与交互层由0.96英寸OLED屏幕实现,通过I2C总线实时展示环境参数及设备状态。报警单元采用红绿双色LED和有源蜂鸣器组合,当检测值超过预设阈值时触发声光报警。执行机构通过GPIO控制5V继电器模块,实现对空气净化设备的电源通断控制。模式切换由物理按键实现,支持手动控制与自动阈值联动双工作模式。华为云物联网平台承担数据中枢角色,存储所有历史监测数据并提供API访问接口。QT上位机通过MQTT协议订阅云平台数据通道,实现环境参数的动态可视化展示。当数据异常时,上位机触发弹窗警告和声音提示,同时提供继电器远程控制按钮及历史数据查询功能。用户可通过曲线图分析各参数随时间变化趋势,所有阈值配置均支持界面化修改。系统通信架构采用分层设计:底层由STM32通过串口与ESP8266交互,中间层通过WiFi连接华为云,上层QT应用通过互联网与云平台保持长连接。调试接口采用USB转TTL模块,可实时监控串口数据流及系统运行状态。系统功能总结功能分类功能描述数据采集实时采集室内温湿度(DHT11)、光照强度(BH1750)、PM2.5(GP2Y1010AU0F)及甲醛浓度(ZE08-CH2O)云端通信通过ESP8266 WiFi模块将传感器数据上传至华为云物联网平台,实现设备接入与指令下发本地显示OLED屏实时显示环境参数(温湿度/光照/PM2.5/甲醛)及空气净化设备工作状态远程监控QT上位机通过MQTT订阅云平台数据,实时显示环境参数,支持阈值超限弹窗+声音报警设备控制QT界面远程控制继电器开关(空气净化器);支持手动控制/自动阈值控制双模式切换(按键切换)智能联动自动模式下:环境参数超限时自动启停空气净化设备;异常时触发本地声光报警(蜂鸣器+双色LED)数据存储与分析华为云平台存储历史数据;QT上位机支持历史数据查询及变化曲线图生成设计的各个功能模块描述主控模块以STM32F103C8T6最小系统板为核心控制器,通过多接口(UART、I2C、ADC、GPIO)协调各模块工作。负责传感器数据采集调度、逻辑判断(如阈值比较)、通信协议封装、执行器控制指令生成及系统状态管理。传感器采集模块集成四类环境传感器:温湿度采集:DHT11通过单总线协议实时获取室内温湿度数据。光照采集:BH1750通过I2C接口测量环境光照强度。PM2.5采集:GP2Y1010AU0F输出模拟电压信号,经STM32 ADC转换获取PM2.5浓度。甲醛采集:ZE08-CH2O通过串口通信传输甲醛浓度值。主控按固定周期轮询传感器,完成数据预处理(单位转换、滤波)。无线通信模块基于ESP8266-01S WiFi模块,通过UART串口与STM32交互。使用AT指令集建立MQTT连接,将传感器数据按华为云物联网平台协议封装上传,同时接收云端下发的设备控制指令(如继电器开关指令)。本地执行与报警模块执行单元:5V继电器模块连接空气净化器电源,由STM32 GPIO引脚控制通断,响应自动模式阈值或远程指令。报警单元:双色LED(绿灯正常/红灯异常)与有源蜂鸣器联动,当环境参数超限时触发声光报警(红灯闪烁+蜂鸣)。本地显示与人机交互模块OLED显示:0.96英寸I2C OLED实时展示环境参数(温湿度、光照、PM2.5、甲醛)及设备状态(净化器开关/自动手动模式)。按键控制:独立按键支持本地切换自动/手动模式,自动模式下依据预设阈值控制净化器。华为云平台模块实现设备接入、数据存储与指令转发:数据存储:云端持久化存储传感器历史数据。指令下发:将QT上位机的继电器控制指令透传至设备端。设备管理:提供设备在线状态监控及通信鉴权。QT上位机模块通过MQTT协议订阅云平台数据,功能包括:实时监控:图形化展示环境参数动态数值。阈值报警:数据超限时触发弹窗警告与系统提示音。远程控制:提供虚拟按钮手动开关空气净化器。数据分析:查询历史数据并生成温度、PM2.5等参数的趋势曲线图。电源与调试模块电源管理:为各模块提供适配电压(STM32需3.3V,继电器需5V)。调试接口:USB转TTL模块用于串口日志输出及固件烧录。上位机代码设计以下是基于Qt的智能家居健康环境监测系统上位机完整代码设计。该代码使用C++开发,包含MQTT通信、数据可视化、报警控制等功能:#include <QApplication> #include <QMainWindow> #include <QtMqtt/QMqttClient> #include <QChart> #include <QChartView> #include <QLineSeries> #include <QValueAxis> #include <QDateTimeAxis> #include <QSqlDatabase> #include <QSqlQuery> #include <QMessageBox> #include <QMediaPlayer> using namespace QtCharts; // 主窗口类定义 class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { setupUI(); setupDatabase(); setupMQTT(); } private slots: void onMQTTConnected(); void onMQTTMessage(const QByteArray &message); void onRelayControl(bool checked); void onModeChanged(bool autoMode); void checkThresholds(); void onQueryData(); private: void setupUI(); void setupDatabase(); void setupMQTT(); void updateChart(); // MQTT客户端 QMqttClient *m_client; // UI组件 QLabel *tempLabel, *humiLabel, *lightLabel, *pm25Label, *hchoLabel; QPushButton *relayBtn, *modeBtn; QChartView *chartView; QDateTimeEdit *startDateEdit, *endDateEdit; // 数据存储 QSqlDatabase db; QMediaPlayer *alarmPlayer; // 当前值 struct EnvData { double temperature = 0.0; double humidity = 0.0; double light = 0.0; double pm25 = 0.0; double hcho = 0.0; bool relayState = false; } currentData; // 阈值设置 const double TEMP_THRESHOLD = 30.0; const double HUMI_THRESHOLD = 80.0; const double PM25_THRESHOLD = 75.0; const double HCHO_THRESHOLD = 0.08; }; void MainWindow::setupUI() { // 主窗口设置 setWindowTitle("智能家居环境监测系统"); setFixedSize(1000, 700); // 实时数据显示区 QWidget *dataWidget = new QWidget(this); QGridLayout *dataLayout = new QGridLayout; tempLabel = new QLabel("温度: --°C"); humiLabel = new QLabel("湿度: --%"); lightLabel = new QLabel("光照: --Lux"); pm25Label = new QLabel("PM2.5: --μg/m3"); hchoLabel = new QLabel("甲醛: --mg/m3"); dataLayout->addWidget(tempLabel, 0, 0); dataLayout->addWidget(humiLabel, 1, 0); dataLayout->addWidget(lightLabel, 0, 1); dataLayout->addWidget(pm25Label, 1, 1); dataLayout->addWidget(hchoLabel, 0, 2); // 控制按钮 relayBtn = new QPushButton("净化器: 关闭"); modeBtn = new QPushButton("当前模式: 手动"); modeBtn->setCheckable(true); dataLayout->addWidget(relayBtn, 2, 0); dataLayout->addWidget(modeBtn, 2, 1); dataWidget->setLayout(dataLayout); dataWidget->setGeometry(20, 20, 400, 150); // 图表区域 QChart *chart = new QChart(); chartView = new QChartView(chart); chartView->setGeometry(20, 180, 960, 400); // 时间选择控件 startDateEdit = new QDateTimeEdit(QDateTime::currentDateTime().addDays(-1)); endDateEdit = new QDateTimeEdit(QDateTime::currentDateTime()); QPushButton *queryBtn = new QPushButton("查询数据"); QWidget *dateWidget = new QWidget(this); QHBoxLayout *dateLayout = new QHBoxLayout; dateLayout->addWidget(new QLabel("开始时间:")); dateLayout->addWidget(startDateEdit); dateLayout->addWidget(new QLabel("结束时间:")); dateLayout->addWidget(endDateEdit); dateLayout->addWidget(queryBtn); dateWidget->setLayout(dateLayout); dateWidget->setGeometry(450, 20, 500, 40); // 信号连接 connect(relayBtn, &QPushButton::clicked, this, &MainWindow::onRelayControl); connect(modeBtn, &QPushButton::toggled, this, &MainWindow::onModeChanged); connect(queryBtn, &QPushButton::clicked, this, &MainWindow::onQueryData); // 报警播放器 alarmPlayer = new QMediaPlayer(this); alarmPlayer->setMedia(QUrl("qrc:/alarm.wav")); } void MainWindow::setupDatabase() { db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("environment.db"); if (!db.open()) { QMessageBox::critical(this, "数据库错误", "无法创建数据库连接"); return; } // 创建数据表 QSqlQuery query; query.exec("CREATE TABLE IF NOT EXISTS env_data (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, " "temperature REAL, " "humidity REAL, " "light REAL, " "pm25 REAL, " "hcho REAL)"); } void MainWindow::setupMQTT() { m_client = new QMqttClient(this); m_client->setHostname("your_huawei_cloud_address"); m_client->setPort(1883); m_client->setUsername("your_device_id"); m_client->setPassword("your_device_secret"); connect(m_client, &QMqttClient::connected, this, &MainWindow::onMQTTConnected); connect(m_client, &QMqttClient::messageReceived, this, &MainWindow::onMQTTMessage); m_client->connectToHost(); } void MainWindow::onMQTTConnected() { m_client->subscribe("environment/data"); qDebug() << "Connected to MQTT Broker"; } void MainWindow::onMQTTMessage(const QByteArray &message) { // 示例JSON格式:{"temp":25.5,"humi":45,"light":320,"pm25":35,"hcho":0.02} QJsonDocument doc = QJsonDocument::fromJson(message); QJsonObject obj = doc.object(); currentData.temperature = obj["temp"].toDouble(); currentData.humidity = obj["humi"].toDouble(); currentData.light = obj["light"].toDouble(); currentData.pm25 = obj["pm25"].toDouble(); currentData.hcho = obj["hcho"].toDouble(); // 更新UI tempLabel->setText(QString("温度: %1°C").arg(currentData.temperature)); humiLabel->setText(QString("湿度: %1%").arg(currentData.humidity)); lightLabel->setText(QString("光照: %1Lux").arg(currentData.light)); pm25Label->setText(QString("PM2.5: %1μg/m3").arg(currentData.pm25)); hchoLabel->setText(QString("甲醛: %1mg/m3").arg(currentData.hcho)); // 保存到数据库 QSqlQuery query; query.prepare("INSERT INTO env_data (temperature, humidity, light, pm25, hcho) " "VALUES (?, ?, ?, ?, ?)"); query.addBindValue(currentData.temperature); query.addBindValue(currentData.humidity); query.addBindValue(currentData.light); query.addBindValue(currentData.pm25); query.addBindValue(currentData.hcho); query.exec(); // 检查阈值 checkThresholds(); } void MainWindow::checkThresholds() { bool needAlarm = false; QString alarmMsg = "环境异常:\n"; if (currentData.temperature > TEMP_THRESHOLD) { needAlarm = true; alarmMsg += QString("温度过高: %1°C\n").arg(currentData.temperature); } if (currentData.humidity > HUMI_THRESHOLD) { needAlarm = true; alarmMsg += QString("湿度过高: %1%\n").arg(currentData.humidity); } if (currentData.pm25 > PM25_THRESHOLD) { needAlarm = true; alarmMsg += QString("PM2.5超标: %1μg/m3\n").arg(currentData.pm25); } if (currentData.hcho > HCHO_THRESHOLD) { needAlarm = true; alarmMsg += QString("甲醛超标: %1mg/m3\n").arg(currentData.hcho); } if (needAlarm) { // 显示弹窗 QMessageBox::critical(this, "环境异常报警", alarmMsg); // 播放报警音 if (alarmPlayer->state() == QMediaPlayer::PlayingState) { alarmPlayer->stop(); } alarmPlayer->play(); // 自动模式下的设备控制 if (modeBtn->isChecked() && !currentData.relayState) { onRelayControl(true); } } } void MainWindow::onRelayControl(bool checked) { currentData.relayState = !currentData.relayState; relayBtn->setText(currentData.relayState ? "净化器: 开启" : "净化器: 关闭"); // 发送控制命令 QJsonObject ctrlObj; ctrlObj["relay"] = currentData.relayState ? 1 : 0; QJsonDocument doc(ctrlObj); m_client->publish("device/control", doc.toJson()); } void MainWindow::onModeChanged(bool autoMode) { modeBtn->setText(autoMode ? "当前模式: 自动" : "当前模式: 手动"); } void MainWindow::onQueryData() { updateChart(); } void MainWindow::updateChart() { QSqlQuery query; query.prepare("SELECT timestamp, temperature, pm25, hcho FROM env_data " "WHERE timestamp BETWEEN ? AND ?"); query.addBindValue(startDateEdit->dateTime().toString("yyyy-MM-dd hh:mm:ss")); query.addBindValue(endDateEdit->dateTime().toString("yyyy-MM-dd hh:mm:ss")); if (!query.exec()) { QMessageBox::warning(this, "查询错误", "无法获取历史数据"); return; } // 创建图表数据 QLineSeries *tempSeries = new QLineSeries(); QLineSeries *pm25Series = new QLineSeries(); QLineSeries *hchoSeries = new QLineSeries(); tempSeries->setName("温度"); pm25Series->setName("PM2.5"); hchoSeries->setName("甲醛"); while (query.next()) { QDateTime dt = QDateTime::fromString(query.value(0).toString(), "yyyy-MM-dd hh:mm:ss"); tempSeries->append(dt.toMSecsSinceEpoch(), query.value(1).toDouble()); pm25Series->append(dt.toMSecsSinceEpoch(), query.value(2).toDouble()); hchoSeries->append(dt.toMSecsSinceEpoch(), query.value(3).toDouble() * 100); // 缩放显示 } // 配置图表 QChart *chart = chartView->chart(); chart->removeAllSeries(); chart->addSeries(tempSeries); chart->addSeries(pm25Series); chart->addSeries(hchoSeries); QDateTimeAxis *axisX = new QDateTimeAxis; axisX->setFormat("MM-dd hh:mm"); axisX->setTitleText("时间"); chart->addAxis(axisX, Qt::AlignBottom); QValueAxis *axisY = new QValueAxis; axisY->setTitleText("数值"); chart->addAxis(axisY, Qt::AlignLeft); tempSeries->attachAxis(axisX); tempSeries->attachAxis(axisY); pm25Series->attachAxis(axisX); pm25Series->attachAxis(axisY); hchoSeries->attachAxis(axisX); hchoSeries->attachAxis(axisY); chart->legend()->setVisible(true); } int main(int argc, char *argv[]) { QApplication app(argc, argv); // 初始化MQTT模块 QMqttClient::registerMqttTypes(); MainWindow w; w.show(); return app.exec(); } #include "main.moc" // 包含元对象编译器输出 关键功能说明:MQTT通信模块:连接华为云物联网平台订阅环境数据主题(environment/data)发布设备控制指令(device/control)数据管理:使用SQLite数据库存储历史数据支持按时间范围查询数据实时监控界面:显示温湿度、光照、PM2.5和甲醛数据设备状态指示(空气净化器开关)手动/自动模式切换报警系统:阈值超限时触发弹窗报警播放报警音效自动模式下触发设备控制数据可视化:使用Qt Charts绘制历史曲线支持多参数同屏显示(温度、PM2.5、甲醛)自定义时间范围查询部署说明:依赖库:Qt 5.9+ Core, Widgets, MQTT, Charts, SQL配置pro文件:QT += core widgets mqtt charts sql华为云配置:替换MQTT连接参数:m_client->setHostname("your_huawei_cloud_address"); m_client->setUsername("your_device_id"); m_client->setPassword("your_device_secret"); 报警音效:添加alarm.wav文件到资源系统或在代码中替换为系统提示音数据库初始化:首次运行自动创建SQLite数据库文件数据表结构见setupDatabase()函数模块代码设计以下是基于STM32F103C8T6的完整传感器驱动代码(寄存器开发方式):#include "stm32f10x.h" // 硬件定义 #define DHT11_GPIO GPIOA #define DHT11_PIN GPIO_Pin_0 #define RELAY_GPIO GPIOA #define RELAY_PIN GPIO_Pin_4 #define BUZZER_GPIO GPIOA #define BUZZER_PIN GPIO_Pin_5 #define LED_R_GPIO GPIOA #define LED_R_PIN GPIO_Pin_6 #define LED_G_GPIO GPIOA #define LED_G_PIN GPIO_Pin_7 #define KEY_GPIO GPIOA #define KEY_PIN GPIO_Pin_8 // OLED I2C地址 #define OLED_ADDRESS 0x78 // 系统时钟初始化 void SystemClock_Config(void) { // 启用外部8MHz晶振 RCC->CR |= RCC_CR_HSEON; while(!(RCC->CR & RCC_CR_HSERDY)); // 配置PLL: HSE * 9 = 72MHz RCC->CFGR |= RCC_CFGR_PLLMULL9 | RCC_CFGR_PLLSRC; RCC->CR |= RCC_CR_PLLON; while(!(RCC->CR & RCC_CR_PLLRDY)); // 设置系统时钟 RCC->CFGR |= RCC_CFGR_SW_PLL; while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // 使能外设时钟 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_ADC1EN | RCC_APB2ENR_AFIOEN; RCC->APB1ENR |= RCC_APB1ENR_USART2EN | RCC_APB1ENR_I2C1EN; } // GPIO初始化 void GPIO_Config(void) { // DHT11 (PA0 输入) GPIOA->CRL &= ~(0x0F << 0); GPIOA->CRL |= 0x08 << 0; // 浮空输入 // 继电器 (PA4 推挽输出) GPIOA->CRL &= ~(0x0F << 16); GPIOA->CRL |= 0x03 << 16; // 蜂鸣器/LED (PA5-PA7 推挽输出) GPIOA->CRL &= ~(0xFF << 20); GPIOA->CRL |= 0x33 << 20 | 0x30; // 按键 (PA8 上拉输入) GPIOA->CRH &= ~(0x0F << 0); GPIOA->CRH |= 0x08 << 0; GPIOA->ODR |= KEY_PIN; } // DHT11驱动 typedef struct { uint8_t humi_int; uint8_t humi_deci; uint8_t temp_int; uint8_t temp_deci; uint8_t check_sum; } DHT11_Data; uint8_t DHT11_Read(DHT11_Data *data) { uint8_t buffer[5] = {0}; // 主机发送开始信号 GPIO_InitTypeDef gpio; gpio.GPIO_Pin = DHT11_PIN; gpio.GPIO_Mode = GPIO_Mode_Out_PP; gpio.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11_GPIO, &gpio); GPIO_ResetBits(DHT11_GPIO, DHT11_PIN); // 拉低18ms Delay_ms(18); GPIO_SetBits(DHT11_GPIO, DHT11_PIN); // 释放总线 Delay_us(30); // 切换输入模式 gpio.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(DHT11_GPIO, &gpio); // 等待响应 if(GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN)) return 0; while(!GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN)); while(GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN)); // 读取40位数据 for(uint8_t i=0; i<40; i++) { while(!GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN)); // 等待高电平 Delay_us(40); buffer[i/8] <<= 1; if(GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN)) buffer[i/8] |= 1; while(GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN)); } // 校验数据 if(buffer[0] + buffer[1] + buffer[2] + buffer[3] == buffer[4]) { data->humi_int = buffer[0]; data->temp_int = buffer[2]; return 1; } return 0; } // BH1750光照传感器驱动 void BH1750_Init(void) { I2C1->CR1 |= I2C_CR1_SWRST; I2C1->CR1 &= ~I2C_CR1_SWRST; // 配置I2C时钟 (72MHz PCLK1) I2C1->CR2 = 36; // APB1时钟=36MHz I2C1->CCR = 180; // 100kHz模式 I2C1->TRISE = 37; I2C1->CR1 |= I2C_CR1_PE; } uint16_t BH1750_Read(void) { uint8_t cmd[2] = {0x10}; // 连续高精度模式 // 发送测量命令 I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, 0x23, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2C1, cmd[0]); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // 等待测量完成 Delay_ms(180); // 读取数据 I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, 0x23, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); uint8_t msb = I2C_ReceiveData(I2C1); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); uint8_t lsb = I2C_ReceiveData(I2C1); I2C_GenerateSTOP(I2C1, ENABLE); return (msb << 8) | lsb; } // OLED显示驱动 void OLED_WriteCmd(uint8_t cmd) { I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, OLED_ADDRESS, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2C1, 0x00); // 控制字节 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_SendData(I2C1, cmd); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTOP(I2C1, ENABLE); } void OLED_Init(void) { OLED_WriteCmd(0xAE); // 关闭显示 OLED_WriteCmd(0xD5); // 设置时钟分频 OLED_WriteCmd(0x80); OLED_WriteCmd(0xA8); // 设置复用率 OLED_WriteCmd(0x3F); OLED_WriteCmd(0xD3); // 设置显示偏移 OLED_WriteCmd(0x00); OLED_WriteCmd(0x40); // 设置起始行 OLED_WriteCmd(0x8D); // 电荷泵设置 OLED_WriteCmd(0x14); OLED_WriteCmd(0x20); // 内存模式 OLED_WriteCmd(0x00); OLED_WriteCmd(0xA1); // 段重定向 OLED_WriteCmd(0xC8); // 行重定向 OLED_WriteCmd(0xDA); // 设置COM硬件 OLED_WriteCmd(0x12); OLED_WriteCmd(0x81); // 对比度 OLED_WriteCmd(0xCF); OLED_WriteCmd(0xD9); // 预充电 OLED_WriteCmd(0xF1); OLED_WriteCmd(0xDB); // VCOMH OLED_WriteCmd(0x40); OLED_WriteCmd(0xA4); // 显示全部亮 OLED_WriteCmd(0xA6); // 正常显示 OLED_WriteCmd(0xAF); // 开启显示 } // PM2.5传感器驱动 (GP2Y1010AU0F) #define PM_LED_GPIO GPIOA #define PM_LED_PIN GPIO_Pin_2 #define PM_ADC_CH ADC_Channel_1 void PM25_Init(void) { // 配置LED控制引脚 GPIOA->CRL &= ~(0x0F << 8); GPIOA->CRL |= 0x03 << 8; // PA2推挽输出 // ADC配置 ADC1->CR2 = ADC_CR2_ADON; // 开启ADC ADC1->SMPR2 = 0x00000007; // 通道1采样时间239.5周期 } uint16_t PM25_Read(void) { GPIO_SetBits(PM_LED_GPIO, PM_LED_PIN); Delay_us(280); ADC1->CR2 |= ADC_CR2_ADON; while(!(ADC1->SR & ADC_SR_EOC)); // 等待转换完成 uint16_t adcValue = ADC1->DR; GPIO_ResetBits(PM_LED_GPIO, PM_LED_PIN); Delay_us(40); return adcValue; } // 甲醛传感器驱动 (ZE08-CH2O) void USART2_Init(void) { // 配置USART2 (PA2-TX, PA3-RX) GPIOA->CRL &= ~(0xFF << 8); GPIOA->CRL |= 0x00008B00; // PA2复用推挽, PA3浮空输入 USART2->BRR = 0x1D4C; // 72MHz/9600=7500 USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; } uint16_t CH2O_Read(void) { uint8_t buffer[9]; if(USART2->SR & USART_SR_RXNE) { for(uint8_t i=0; i<9; i++) { while(!(USART2->SR & USART_SR_RXNE)); buffer[i] = USART2->DR; } // 校验帧头: 0xFF 0x17 0x04 if(buffer[0]==0xFF && buffer[1]==0x17 && buffer[2]==0x04) { return (buffer[3] << 8) | buffer[4]; // 返回甲醛浓度值 } } return 0; } // ESP8266 WiFi通信 void USART1_Init(void) { // 配置USART1 (PA9-TX, PA10-RX) GPIOA->CRH &= ~(0xFF << 4); GPIOA->CRH |= 0x0000008B; USART1->BRR = 0x1D4C; // 72MHz/9600=7500 USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; } void ESP8266_SendCmd(const char *cmd) { while(*cmd) { USART1->DR = *cmd++; while(!(USART1->SR & USART_SR_TC)); } } // 主控制逻辑 int main(void) { SystemClock_Config(); GPIO_Config(); USART1_Init(); USART2_Init(); I2C_Config(); ADC_Config(); // 初始化外设 BH1750_Init(); OLED_Init(); PM25_Init(); // 连接华为云 ESP8266_SendCmd("AT+CWMODE=1\r\n"); Delay_ms(1000); ESP8266_SendCmd("AT+CWJAP=\"SSID\",\"PASSWORD\"\r\n"); Delay_ms(3000); ESP8266_SendCmd("AT+MQTTUSERCFG=0,1,\"deviceID\",\"username\",\"password\"\r\n"); ESP8266_SendCmd("AT+MQTTCONN=0,\"iot-cloud.com\",1883,1\r\n"); while(1) { // 传感器数据采集 DHT11_Data dht; if(DHT11_Read(&dht)) { uint16_t light = BH1750_Read(); uint16_t pm25 = PM25_Read(); uint16_t ch2o = CH2O_Read(); // OLED显示 OLED_DisplayData(dht.temp_int, dht.humi_int, light, pm25, ch2o); // 数据上传华为云 char mqttMsg[128]; sprintf(mqttMsg, "{\"temp\":%d,\"humi\":%d,\"light\":%d,\"pm25\":%d,\"ch2o\":%d}", dht.temp_int, dht.humi_int, light, pm25, ch2o); ESP8266_SendMQTT("topic/pub", mqttMsg); // 阈值判断 if(pm25 > 100 || ch2o > 80) { GPIO_SetBits(BUZZER_GPIO, BUZZER_PIN); GPIO_SetBits(LED_R_GPIO, LED_R_PIN); GPIO_ResetBits(LED_G_GPIO, LED_G_PIN); } else { GPIO_ResetBits(BUZZER_GPIO, BUZZER_PIN); GPIO_ResetBits(LED_R_GPIO, LED_R_PIN); GPIO_SetBits(LED_G_GPIO, LED_G_PIN); } } Delay_ms(5000); // 5秒采集周期 } } 关键模块说明:DHT11温湿度传感器:单总线协议,精确时序控制18ms启动信号+40us响应检测40位数据校验机制BH1750光照传感器:I2C接口(100kHz)连续高精度测量模式(0x10)16位光照强度值输出PM2.5传感器:同步LED触发与ADC采样280us LED点亮延迟ADC1通道1采样(PA1)甲醛传感器:UART主动上传模式帧格式:FF 17 04 [DATA] [CHECK]串口2接收处理(PA3)OLED显示:I2C接口SSD1306驱动128x64分辨率文本显示自定义数据刷新逻辑ESP8266通信:AT指令集控制MQTT协议接入华为云支持JSON数据格式上传报警控制:双色LED状态指示蜂鸣器阈值触发继电器设备控制(PA4)代码采用纯寄存器开发,包含完整的传感器驱动、云平台接入逻辑和本地控制功能,可直接部署到STM32F103C8T6平台运行。项目核心代码以下是基于STM32F103C8T6的智能家居健康环境监测系统main.c完整代码(寄存器开发方式):#include "stm32f10x.h" #include "sensor_driver.h" #include "oled.h" #include "wifi.h" #include "mqtt.h" #include "timer.h" #include "sys.h" // 传感器数据结构体 typedef struct { float temp; float humi; uint16_t light; uint16_t pm25; uint16_t hcho; } SensorData; // 全局变量定义 volatile SensorData sensor_data = {0}; volatile uint8_t relay_status = 0; // 继电器状态 volatile uint8_t work_mode = 0; // 0:自动模式 1:手动模式 volatile uint8_t alarm_flag = 0; // 报警标志位 // 报警阈值常量 #define TEMP_THRESHOLD 35.0 #define HUMI_THRESHOLD 80.0 #define PM25_THRESHOLD 150 #define HCHO_THRESHOLD 100 // 硬件初始化 void Hardware_Init(void) { // 启用时钟 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPCEN; RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN; RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // GPIO初始化 GPIOA->CRL &= 0xFFFF0000; // PA0~3:模拟输入/串口 GPIOA->CRL |= 0x00008B00; // PA1:ADC, PA2:复用推挽(USART_TX), PA3:浮空输入(USART_RX) // 继电器控制引脚(PC13) GPIOC->CRH &= 0xFF0FFFFF; GPIOC->CRH |= 0x00300000; // 推挽输出 GPIOC->ODR &= ~(1<<13); // 初始关闭 // 报警LED(PC14-PC15) GPIOC->CRH &= 0x00FFFFFF; GPIOC->CRH |= 0x33000000; // 推挽输出 GPIOC->ODR &= ~(0x3<<14); // 初始关闭 // 蜂鸣器(PA4) GPIOA->CRL &= 0xFFF0FFFF; GPIOA->CRL |= 0x00030000; // 推挽输出 GPIOA->ODR &= ~(1<<4); // 初始关闭 // 按键(PA8) GPIOA->CRH &= 0xFFFFFFF0; GPIOA->CRH |= 0x00000008; // 上拉输入 // 初始化外设 USART1_Init(115200); // ESP8266通信 ADC1_Init(); // ADC初始化 I2C_Init(); // I2C初始化(BH1750+OLED) TIM3_Init(1000, 72); // 1ms定时器 } // 传感器数据采集 void Sensor_Update(void) { sensor_data.temp = DHT11_ReadTemp(); sensor_data.humi = DHT11_ReadHumi(); sensor_data.light = BH1750_ReadLight(); sensor_data.pm25 = GP2Y1010_Read(); sensor_data.hcho = ZE08_ReadHCHO(); } // 报警检测 void Check_Alarm(void) { if((sensor_data.temp > TEMP_THRESHOLD) || (sensor_data.humi > HUMI_THRESHOLD) || (sensor_data.pm25 > PM25_THRESHOLD) || (sensor_data.hcho > HCHO_THRESHOLD)) { // 触发声光报警 GPIOA->ODR |= (1<<4); // 蜂鸣器开启 GPIOC->ODR |= (1<<14); // 红灯亮 alarm_flag = 1; // 自动模式开启净化器 if(work_mode == 0) { GPIOC->ODR |= (1<<13); // 继电器开启 relay_status = 1; } } else { GPIOA->ODR &= ~(1<<4); // 关闭蜂鸣器 GPIOC->ODR &= ~(1<<14); // 关闭红灯 alarm_flag = 0; // 自动模式关闭净化器 if((work_mode == 0) && relay_status) { GPIOC->ODR &= ~(1<<13); relay_status = 0; } } } // 状态指示灯控制 void Status_LED(void) { static uint8_t counter = 0; if(++counter >= 100) { // 100ms周期 counter = 0; if(WiFi_Connected()) { GPIOC->ODR ^= (1<<15); // 绿灯闪烁 } else { GPIOC->ODR &= ~(1<<15); // 绿灯常灭 } } } // 主函数 int main(void) { // 硬件初始化 Hardware_Init(); OLED_Init(); WiFi_Init(); MQTT_Init(); // 显示欢迎界面 OLED_ShowString(0, 0, "Smart Home System", 16); OLED_ShowString(0, 2, "Initializing...", 16); Delay_Ms(1000); // 连接华为云 if(WiFi_Connect("SSID", "PASSWORD") && MQTT_Connect("device_id", "token")) { OLED_ShowString(0, 4, "Cloud: Connected", 16); } else { OLED_ShowString(0, 4, "Cloud: Error!", 16); } Delay_Ms(500); OLED_Clear(); while(1) { // 1. 传感器数据采集 Sensor_Update(); // 2. OLED显示实时数据 OLED_ShowString(0, 0, "T:", 8); OLED_ShowFloat(16, 0, sensor_data.temp, 8); OLED_ShowString(0, 2, "PM2.5:", 8); OLED_ShowNum(48, 2, sensor_data.pm25, 8); // 3. 检测报警条件 Check_Alarm(); // 4. 上传数据到华为云 if(WiFi_Connected()) { char buffer[128]; sprintf(buffer, "{\"temp\":%.1f,\"humi\":%.1f,\"light\":%d,\"pm25\":%d,\"hcho\":%d}", sensor_data.temp, sensor_data.humi, sensor_data.light, sensor_data.pm25, sensor_data.hcho); MQTT_Publish("topic/data", buffer); } // 5. 处理按键事件 if(GPIOA->IDR & (1<<8)) { // 按键按下 Delay_Ms(20); if(GPIOA->IDR & (1<<8)) { work_mode = !work_mode; OLED_ShowString(80, 0, work_mode ? "M" : "A", 16); } while(GPIOA->IDR & (1<<8)); // 等待释放 } // 6. 状态指示灯控制 Status_LED(); // 7. 处理云平台指令 if(MQTT_CommandReceived()) { uint8_t cmd = MQTT_GetCommand(); if(cmd == 0x01) { // 开启净化器 GPIOC->ODR |= (1<<13); relay_status = 1; } else if(cmd == 0x00) { // 关闭净化器 GPIOC->ODR &= ~(1<<13); relay_status = 0; } } // 主循环延时 Delay_Ms(500); } } // 定时器3中断服务函数 void TIM3_IRQHandler(void) { if(TIM3->SR & TIM_SR_UIF) { TIM3->SR &= ~TIM_SR_UIF; // 清除中断标志 // 1ms定时任务 static uint16_t counter = 0; if(++counter >= 1000) { // 1秒定时 counter = 0; // 发送心跳包 if(WiFi_Connected()) { MQTT_Ping(); } } } } // USART1中断服务函数(处理ESP8266数据) void USART1_IRQHandler(void) { if(USART1->SR & USART_SR_RXNE) { uint8_t data = USART1->DR; MQTT_ReceiveHandler(data); // MQTT协议解析 } } 代码说明:硬件初始化:配置GPIO(传感器、继电器、报警器、按键)初始化USART(WiFi通信)、ADC(PM2.5采集)、I2C(OLED+光照传感器)定时器TIM3用于系统心跳核心功能:传感器数据采集(温湿度/光照/PM2.5/甲醛)OLED实时显示环境参数阈值报警控制(声光报警+自动净化)ESP8266通过AT指令与华为云MQTT通信支持手动/自动双模式切换中断服务:TIM3中断:处理心跳包和定时任务USART1中断:处理云平台下发的控制指令数据处理流程:主循环500ms采集并上传数据实时检测环境阈值触发报警按键切换工作模式OLED刷新显示设备状态注意:实际开发需确保以下驱动文件已实现:sensor_driver.h(所有传感器驱动)oled.h(OLED显示驱动)wifi.h(ESP8266 AT指令封装)mqtt.h(华为云MQTT协议对接)timer.h(定时器配置)sys.h(系统工具函数)总结本项目成功构建了一套基于STM32F103C8T6微控制器的智能家居健康环境监测系统。系统核心实现了对室内温湿度、光照强度、PM2.5及甲醛浓度的实时精准采集,并通过ESP8266 WiFi模块将数据稳定上传至华为云物联网平台进行集中存储与管理。STM32主控有效协调了多传感器数据读取、本地OLED屏状态显示、声光报警触发以及继电器对净化设备的控制,确保了各硬件模块的高效协同运作。在远程交互层面,QT开发的上位机通过MQTT协议订阅华为云数据,为用户提供了直观的数据可视化界面,实时展示环境参数并生成历史变化曲线图。同时,QT界面集成了远程设备控制功能与阈值报警机制(弹窗+声音),使用户能够便捷地管理空气净化设备,并在环境异常时及时获得提醒。系统支持手动/自动双运行模式,在自动模式下能依据预设阈值智能启停净化设备,提升了智能化水平。本地交互设计注重实用性,OLED显示屏清晰呈现实时环境参数与设备工作状态,按键支持模式切换,声光报警单元(蜂鸣器+LED)确保本地环境超标时能迅速引起注意。整体系统融合了传感器技术、嵌入式控制、无线通信、云平台服务与上位机软件开发,构建了一个功能完备、交互友好、兼具本地与远程管理能力的智能环境监测解决方案,有效提升家居环境的健康管理水平。
-
使用华为云iot数据流转 ,通过AMQP的方式连接华为云,在启动时正常接收数据,但是我通过断网后系统重新连接失败,重新连接时的参数都一样,只有时间搓是重新生成的。
-
引言随着物联网(IoT)技术的迅猛发展,越来越多的开发者和企业开始关注如何高效地构建和管理智能设备。物联网概览物联网通过传感器、RFID等技术实现了物品与物品、物品与人之间的信息交换与通信,构建了一个智能化网络。其架构分为感知层、网络层和应用层,各层次协同工作,实现数据采集、传输与处理。据预测,到2025年全球物联网市场规模将达到1.5万亿美元,在智能家居、智能交通等领域有广泛的应用前景。应用案例智能家居:智能音箱可通过语音控制家电,智能门锁实现远程开门,智能摄像头实时监控家庭安全。智能交通:利用传感器优化交通流量,车联网技术提升交通安全与效率。工业物联网:通过传感器监控生产设备状态,提高生产效率和产品质量。华为云IoT平台介绍华为云IoT平台提供了一套完整的设备接入解决方案,支持设备注册、状态监控、远程控制等功能模块,帮助用户快速搭建稳定的物联网应用。主要功能设备管理:包括设备注册区、设备管理列表、设备详情页等部分,支持多种设备类型的注册与批量操作。在线调试:提供详细的设备创建流程指导,简化了开发者接入设备的难度。消息跟踪:实时监控设备上报的数据,并能下发命令给设备。实例展示以智慧烟感器为例,演示了设备连接平台、上报数据到平台以及平台下发命令给设备的过程。这不仅展示了平台的功能性,还证明了其实时性和高效性。首页搜索“设备接入”,进行服务的开通随后来到控制台,点击你所开通的服务在产品里“创建产品”输入相关产品信息随后到设备页面进行注册设备相关demo案例引导可参考:https://support.huaweicloud.com/qs-iothub/iot_05_00010.html以一款虚拟的智慧烟感器为例,带您快速体验平台的三个基本功能:设备连接平台,设备上报数据到平台,平台下发命令给设备API Explorer助力开发API Explorer是华为云提供的一个强大的工具,它允许开发者快速调试API、查看文档并获取代码示例,极大地提高了开发效率。功能亮点快速上手:降低调试难度,减少开发时间。多语言支持:丰富的代码示例覆盖多种编程语言,满足不同需求。应用场景多样:适用于物联网设备开发、数据分析等多种场景。首页搜索“API Explorer”找到你想要测试的API带星号的是必填信息,填入相关信息即可调试在右侧窗口可查看代码示例复制到IDE里需要填充请求头里的token!!!具体token可使用IAM接口获取结语华为云通过一系列创新的物联网解决方案,为开发者们提供了强大而灵活的工具集,推动了物联网技术的发展。
-
按照产品文档中最佳实践的步骤不能完成连接。
-
IoTda平台每秒收到设备的消息上报是只打印一次吗,还是都能接收到但是每秒只打印一次,还是一秒只能保留最后一条信息
-
为什么我在hbuderx写的app,在hbuderx的内置浏览器上运行可以获取我的华为云IOTDA数据,但是把这个代码工程打包好安装在我的Android手机上使用却无法获取?
-
智慧井盖设备在线,云平台无数据上传,实物显示正常
-
打开分享的源码,提示检测到#include 错误,include相关的源文件都有问题,小白求助,编译的时候也提示windows找不到文件'genconfig.exe。生成不了config.
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签