文章目录
- 一、前言
-
- 1.1 项目介绍
-
- 【1】项目开发背景
- 【2】设计实现的功能
- 【3】项目硬件模块组成
- 【4】摘要
- 【5】开发工具与源码下载
- 1.2 设计思路
- 1.3 系统功能总结
- 1.4 开发工具的选择
-
-
- 【1】设备端开发
- 【2】客户端与上位机开发
-
- 1.5 系统框架图
- 1.6 实物图
- 1.7 模块的技术详情介绍
- 三、部署华为云物联网平台
-
- 3.1 物联网平台介绍
- 3.2 开通物联网服务
- 3.3 创建产品
-
- (1)创建产品
- (2)填写产品信息
- (3)产品创建成功
- (4)添加自定义模型
-
-
- 【1】创建服务ID
- 【2】SHT30_T 环境温度 整型
- 【3】SHT30_H 环境湿度 整型
- 【4】adc_water 水量检测 浮点数类型
- 【5】motor_sw 加湿器开关 BOOL类型
- 【6】RunMode 运行模式 BOOL类型
- 【7】SHT30_H_MAX 湿度阀值 整型
-
- (5)创建完成
- 3.4 添加设备
-
- (1)注册设备
- (2)根据自己的设备填写
- (3)保存设备信息
- (4)设备创建完成
- (5)设备详情
- 3.5 MQTT协议主题订阅与发布
-
- (1)MQTT协议介绍
- (2)华为云平台MQTT协议使用限制
- (3)主题订阅格式
- (4)主题发布格式
- 3.6 MQTT三元组
-
- (1)MQTT服务器地址
- (2)生成MQTT三元组
- 3.7 模拟设备登录测试
-
- (1)填入登录信息
- (2)打开网页查看
- 四、上位机开发
-
- 4.1 Qt开发环境安装
- 4.2 新建上位机工程
- 4.3 切换编译器
- 4.4 编译测试功能
- 4.5 设计UI界面与工程配置
-
- 【1】打开UI文件
- 【2】开始设计界面
- 5.5 编译Windows上位机
- 5.6 配置Android环境
-
- 【1】选择Android编译器
- 【2】创建Android配置文件
- 【3】配置Android图标与名称
- 【3】编译Android上位机
- 5.7 设备仿真调试
- 六、ESP32代码设计
-
-
- 代码架构说明
-
- 复刻资料包下载
一、前言
本项目支持0基础小白复刻,可以文章结尾关注我获取资料包。
1.1 项目介绍
【1】项目开发背景
随着物联网技术的快速发展和智能家居产品的普及,人们对居家环境舒适度的要求日益提高。空气湿度作为影响人体舒适感和健康的重要环境因素,正受到越来越多的关注。研究表明,当环境湿度过低时,容易引发皮肤干燥、呼吸道不适等问题,而冬季供暖或夏季空调使用往往会加剧室内空气干燥的情况。空气加湿器因此成为许多家庭改善居住环境的重要设备。
多数加湿器需要用户手动开关,无法根据环境湿度自动调节工作状态,容易出现过度加湿或加湿不足的情况。传统加湿器缺乏水位监测功能,在水箱缺水时仍可能持续工作,导致设备干烧,不仅损坏机器,还存在火灾安全隐患。用户只能现场操作设备,无法远程了解家中湿度状况或控制加湿器运行,使用便利性受到限制。
针对上述问题,本项目设计并开发了一款基于ESP32的智能空气加湿器系统。该系统能够实时采集环境温湿度数据和水箱水位信息,支持自动恒湿控制与手动模式切换,具备缺水报警和防干烧保护功能。同时,系统通过WiFi连接华为云物联网平台,利用MQTT协议上传设备数据,并开发基于Qt框架的Android手机APP和Windows上位机软件,实现远程数据监测与控制功能。该设计旨在提升加湿器的智能化水平和使用安全性,为用户提供更加便捷、舒适的居家环境管理体验。
【2】设计实现的功能
(1)空气加湿控制功能:系统支持本地和远程双重控制模式。用户既可以通过本地的机械按键手动开启或关闭加湿继电器,也可以通过Android手机APP或Windows电脑上位机进行远程控制,实现加湿器的启停。
(2)环境温湿度检测与智能调节功能:系统通过SHT30传感器实时采集当前环境的温度和湿度数值。在自动模式下,系统会进行智能自适应调节:当检测到的环境湿度小于设定的湿度阈值时,自动开启加湿器;当环境湿度大于或等于设定的湿度阈值时,自动停止加湿。
(3)防干烧水位检测功能:系统利用模拟量水位传感器实时监测加湿器内部的水量,通过ADC接口采集数据并换算为具体水量。当检测到加湿器没水时,系统会自动切断加湿模块并停止工作,从硬件和软件双层面防止干烧;当重新加水、检测到水位充足时,系统将自动恢复加湿功能。
(4)声光报警提示功能:系统集成了高电平触发的有源蜂鸣器。当水位传感器监测到加湿器内部缺水时,系统会立即触发蜂鸣器发出警报,提示用户及时加水;一旦用户完成加水且监测到水量恢复充足,蜂鸣器将自动停止报警。
(5)多功能按键交互功能:系统设计了3颗独立的机械按压式按键,提供直观的本地交互。按键1用于控制本地OLED显示屏的界面翻页;按键2用于在“自动模式”与“手动模式”之间进行切换;按键3则用于在手动模式下直接控制加湿器的开启或关闭。
(6)本地OLED数据显示功能:设备本地搭载了0.96寸SPI协议控制的OLED显示屏。屏幕能够实时、直观地滚动或翻页显示环境温度(SHT30_T)、环境湿度(SHT30_H)、当前水量(adc_water)、加湿器开启/关闭状态(motor_sw)、运行模式(RunMode)以及系统设定的湿度阈值(SHT30_H_MAX)。
(7)物联网数据上云与多端远程监控功能:ESP32S3主控芯片利用自带的Wi-Fi功能,通过标准的MQTT协议跨网络连接至华为云IoT物联网服务器。设备端可将温湿度、水量、开关状态、运行模式及湿度阈值等6项核心数据实时上传至云端;同时,基于Qt(C++)开发的Windows上位机和Android手机APP通过连接华为云,实现远程数据的同步刷新显示以及远程控制指令的下发。
【3】项目硬件模块组成
(1)主控芯片模块(ESP32S3R8N8):作为整个智能加湿器的“大脑”,负责采集传感器数据、处理按键交互逻辑、驱动OLED显示屏,并通过内置的Wi-Fi功能运行MQTT协议,实现与华为云物联网平台的数据交互与控制。
(2)温湿度检测模块(SHT30):采用I2C接口的高精度SHT30温湿度传感器模块,负责实时采集加湿器周围环境的温度(SHT30_T)与湿度(SHT30_H)数据,为系统的自动加湿逻辑提供精密的数据支撑。
(3)加湿控制模块(5V加湿器+继电器):加湿核心采用5V供电的加湿器模块,其电源通断由一个继电器模块进行物理隔离与控制。ESP32-S3通过引脚输出高低电平控制继电器的吸合与断开,从而实现加湿器的本地或远程启停。
(4)水位检测模块(模拟量水量传感器):采用模拟信号输出的水位检测传感器,置于加湿器水箱中。通过ESP32-S3的ADC(模数转换)接口实时采集传感器输出的模拟电压值,并在程序内部换算为具体的水量数据(adc_water),用于缺水保护。
(5)报警提示模块(有源蜂鸣器):采用高电平触发的有源蜂鸣器。当水位检测模块判定水箱缺水时,主控芯片向蜂鸣器控制引脚输出高电平,触发声音警报以提示用户加水;水量充足时输出低电平停止报警。
(6)本地显示模块(0.96寸OLED屏):采用0.96寸的OLED显示屏,通过SPI串行总线协议与ESP32-S3连接。负责在本地实时直观地显示环境温湿度、当前水量、加湿器开关状态、当前运行模式以及系统湿度阈值。
(7)按键交互模块(独立机械按键):由3颗独立的机械按压式按键组成,通过GPIO引脚与主控芯片相连并启用软件防抖。分别实现显示屏翻页(按键1)、自动/手动模式切换(按键2)以及手动开关加湿器(按键3)的本地控制。
(8)电源供电模块(5V电源):整个系统采用统一的5V直流电源供电,负责为ESP32-S3开发板、SHT30模块、继电器、加湿模块、OLED显示屏及蜂鸣器提供稳定可靠的电力支持。
【4】摘要
本项目设计并实现了一款基于ESP32-S3微控制器的智能空气加湿器系统,旨在解决传统加湿器智能化程度低、无法自适应调节及缺乏安全缺水保护等问题。系统以ESP32S3R8N8为主控芯片,集成SHT30高精度温湿度传感器与模拟量水位传感器,实现了环境温湿度的实时采集与水箱水量的精准监测。系统支持“自动/手动”双模式运行:自动模式下,系统根据环境湿度与预设阈值的关系智能控制加湿启停;手动模式下,支持本地按键与远程指令控制。针对安全隐患,设计了防干烧保护机制,在检测到缺水时自动切断加湿模块并触发有源蜂鸣器声光报警。本地通过0.96寸SPI接口的OLED显示屏实时显示各项运行参数。
在云端与多端交互方面,系统利用ESP32-S3内置的Wi-Fi功能,基于MQTT协议接入华为云IoT物联网平台,实现了设备端数据的稳定上云。客户端采用跨平台Qt(C++ 5.12.6)框架开发,在Win10环境下实现了“一套代码、多端编译”,成功构建了Windows电脑上位机软件与Android手机APP。测试结果表明,该系统实现了本地物理交互与云端远程监控的无缝联动,数据传输准确可靠,防干烧响应迅速,为现代家居环境的智能调节提供了一种高性价比、高稳定性的端到端解决方案。
关键字
ESP32-S3;智能加湿器;华为云IoT;MQTT协议;Qt框架;SHT30传感器;防干烧保护
【5】开发工具与源码下载
项目开发使用的全部软件工具已经上传到网盘:https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
1.2 设计思路
本项目的整体设计思路立足于“端-云-结”的一体化架构,旨在构建一个集本地智能感知、硬件安全防护与多平台远程监控于一体的闭环控制系统。系统以高性能、低功耗的ESP32-S3微控制器为核心控制中枢,围绕其展开硬件外设的驱动与软件逻辑的编写。在设计初期,首先确立了本地控制与远程协同的互补原则,确保设备在脱离网络时具备完整的独立运行与安全自愈能力,而在联网状态下则能实现无缝的数字化升级。整体研发路径严格围绕功能需求展开,拒绝冗余设计,专注于温湿度控制、水位安全监测以及多端数据同步的核心价值。
在硬件层面的架构设计上,系统采用模块化与分层驱动的思路。主控芯片通过SPI总线和I2C总线分别建立与0.96寸OLED显示屏及SHT30温湿度传感器的通信链路,确保高频次数据刷新的稳定与准确。为了实现加湿器的物理启停,设计中引入继电器作为电子开关,实现微控制器弱电信号对5V加湿模块强电供电的隔离控制。针对关键的安全防护需求,设计思路强调“硬监测与软控制”的结合,利用ADC接口对水位传感器的模拟量进行连续采样,并将其转换为直观的水量百分比或数值,作为系统运行的核心前置条件。
在软件的状态机与业务逻辑设计上,系统围绕“自动”与“手动”两种运行模式构建核心控制循环。自动模式的设计思路是以软件设定的湿度阈值为判定基准,将SHT30采集的实时湿度与其进行动态比对,产生滞回或直接的开关动作,实现环境湿度的自适应调节。而在所有控制逻辑中,缺水防干烧机制被赋予了最高执行优先级。无论是自动模式还是手动模式,一旦ADC采样的水位数据触发缺水临界值,系统将立即强行切断继电器输出并驱动有源蜂鸣器进行高电平报警,直到水位恢复充足。这种优先级设计确保了设备在无人看管时的绝对安全。
在云端接入与跨平台客户端的设计上,系统遵循了“标准协议、跨平台复用”的高效开发思路。设备端利用ESP32-S3自带的Wi-Fi射频单元,通过轻量化的MQTT协议连接至华为云IoT物联网平台,将封装好的温湿度、水量、开关状态、模式及阈值等六大核心数据按固定频率上报。客户端则规避了针对不同操作系统重复编写代码的弊端,创新性地采用Qt(C++ 5.12.6)框架进行开发。利用Qt强大的跨平台特性与网络通信模块,在Win10开发环境下编写一套核心逻辑与UI代码,通过不同的编译器分别生成Windows上位机和Android手机APP,实现了多终端对云端数据的同步接收与对加湿器的远程反向控制。
1.3 系统功能总结
| 功能模块 | 功能名称 | 对应数据标识/变量 | 控制/实现方式 | 详细功能描述 |
|---|---|---|---|---|
| 核心加湿 | 空气加湿控制 | motor_sw (BOOL) |
本地按键3 / 远程APP与上位机 / 自动逻辑 | 控制5V加湿器模块的启停。支持本地、远程以及系统自动触发继电器进行加湿或停止加湿。 |
| 环境监测 | 温湿度检测 | SHT30_T (整型) SHT30_H (整型) |
SHT30传感器 I2C采集 | 实时采集当前室内环境的温度与湿度数值,为智能加湿调节提供核心数据。 |
| 智能调节 | 自动加湿模式 | RunMode (BOOL) SHT30_H_MAX (整型) |
本地按键2切换 / 软件逻辑比对 | 当运行模式为自动时: 1. 环境湿度 < 湿度阈值时,自动开启加湿; 2. 环境湿度 湿度阈值时,自动停止加湿。 |
| 安全防护 | 防干烧水位检测 | adc_water (浮点数) |
水位传感器 ADC模拟量采集 | 实时监测水箱水量: 1. 检测到没水时,强制切断继电器停止加湿,防止干烧; 2. 检测到水量充足时,恢复正常加湿控制。 |
| 异常报警 | 缺水提示功能 | - | 高电平触发有源蜂鸣器 | 联动水位检测: 1. 当系统判定没水时,蜂鸣器开启警报,提示用户加水; 2. 当用户加水至水量充足时,蜂鸣器自动停止警报。 |
| 本地交互 | 独立按键控制 | - | 3颗独立机械按键(GPIO输入) | 按键1:控制OLED显示屏翻页查看数据; 按键2:切换“自动/手动”运行模式; 按键3:手动模式下开启或关闭加湿器。 |
| 本地显示 | OLED数据显示 | 包含上述所有6项数据 | 0.96寸OLED显示屏(SPI协议) | 在本地屏幕上直观地实时显示:环境温湿度、当前水量、加湿器开关状态、运行模式、湿度阈值。 |
| 云端物联网 | 数据上云交互 | 6项核心物联网属性 | ESP32 Wi-Fi模块 + MQTT协议 | 设备联网并接入华为云IoT物联网服务器,按固定频率双向交互,上传本地状态并接收云端控制指令。 |
| 多端远程控制 | 跨平台客户端监控 | 6项核心物联网属性 | Qt (C++ 5.12.6) 框架开发 | 在Win10下编译出Windows电脑上位机与Android手机APP,远程同步显示设备端上传的数据,并实现跨终端远程反向控制。 |
1.4 开发工具的选择
【1】设备端开发
设备端开发环境的选择和配置对于本项目的顺利进行至关重要。本项目的设备端开发采用了 Visual Studio Code (VSCODE) 联合 ESP-IDF (Espressif IoT Development Framework) 官方物联网开发框架。VSCODE 作为一款轻量级且扩展性极强的代码编辑器,配合 Espressif 官方提供的编译插件,构成了高效、现代化的集成开发环境(IDE)。它完美支持本项目所选用的 ESP32-S3R8N8 高性能微控制器,能够提供高效的 CMake 编译构建系统、静态代码分析以及便捷的固件烧录功能。
VSCODE 结合 ESP-IDF 提供了强大的调试与日志分析功能。通过内置的串口监视器(Monitor),开发人员可以实时捕获 ESP32-S3 运行时的死机堆栈信息(Backtrace),并利用 GDB 调试工具进行源码级的精准定位。这种现代化开发组合与 ESP32-S3 芯片的硬件架构契合度极高,能够轻松配置和管理复杂的多任务物联网项目。
编程语言方面,本项目采用 C语言 进行开发。C语言作为嵌入式开发中的标准语言,具备极高的执行效率和对硬件底层的直接操控能力。在编写代码时,本项目基于 ESP-IDF 框架底层的寄存器映射与硬件抽象层(HAL)进行开发,既保证了对 SHT30 传感器(I2C 总线)、OLED 显示屏(SPI 总线)及 ADC 水位采集等硬件接口的精细化、高效率控制,又充分利用了 ESP-IDF 内置的 FreeRTOS 实时操作系统对 Wi-Fi 联网与 MQTT 通信任务的灵活调度,从而确保了整个智能加湿器系统在多任务并发时的低延迟与高稳定性。
在程序下载与固件烧录方面,本项目采用了 ESP32-S3 芯片原生支持的 USB/串口下载方式。利用芯片内置的 ROM Bootloader,开发人员只需通过一根 USB 数据线连接电脑,即可在 VSCODE 环境下一键完成编译、固件擦除、程序烧录及串口日志打印。这种下载方式摆脱了传统单片机对外部专用仿真器或复杂 ISP 跳线开关的依赖,极大地简化了硬件调试过程,缩短了系统迭代周期,显著提升了设备端的开发效率。
【2】客户端与上位机开发
APP与上位机的开发环境选用了 Qt 5.12.6 版本。这是一个强大的跨平台 C++ 开发框架,广泛应用于高性能图形用户界面(GUI)应用程序的构建。Qt 提供了极其丰富的类库(如 QNetworkAccessManager 和用于网络通信的 Socket 模块),支持开发者创建视觉效果良好、交互流畅的用户界面。由于其优秀的跨平台底层架构,Qt 能够完美适配本项目的多端监控需求,使得同一套核心逻辑能够同时运行于 Windows 和 Android 操作系统之上。
Qt 开发环境中使用的编程语言为 C++。C++ 作为一种面向对象的编译型语言,具备优异的运行时性能和内存管理能力,非常适合处理物联网客户端高频次的数据刷新、MQTT 异步网络事件解析以及复杂的 UI 动态渲染。通过 Qt 独创的信号与槽(Signals and Slots)机制,开发者可以非常优雅地实现事件驱动编程:当接收到华为云 IOT 物联网服务器下发的 MQTT 消息时,系统可以瞬间触发信号,自动异步更新本地界面的温湿度、水量等数值,从而构建出响应迅速、实时同步的上位机应用。
开发环境部署在 Windows 10 操作系统下。作为开发主机,Windows 10 能够提供成熟、稳定的软件生态。通过 Qt Creator 集成开发环境,开发人员可以在一个统一的软件界面中完成代码编写、UI 可视化设计、逻辑调试与项目编译。Qt Creator 强大的代码补全、智能语法提示以及内置的 GDB 调试器,帮助开发人员快速定位网络连接异常或界面布局错误,极大提升了软件构建效率。
得益于 Qt 的跨平台特性,该开发环境支持在 Windows 10 系统下通过配置不同的工具链(MSVC/MinGW 编译器以及 Android NDK/SDK 交叉编译器),实现“一套代码、多端编译”。这使得开发人员无需针对两个操作系统重复开发,即可直接编译出可在 PC 电脑上运行的 Windows 上位机软件,以及可在手机上运行的 Android APK 应用程序。这一方案不仅大幅度降低了软件开发与后期维护的成本,更从根本上保证了 Windows 端与 Android 端在数据交互逻辑、华为云接入协议以及用户 UI 体验上的一致性与兼容性。
1.5 系统框架图
【 用户客户端 (Qt 5.12.6 开发) 】
【 网络与云端平台 】
【 执行与显示层 】
【 核心控制层 】
【 感知与输入层 】
【 供电系统 】
供电 (5V/3.3V)
5V供电
5V供电
5V供电
I2C 协议
ADC 模拟量采集
GPIO 输入
SPI 协议
GPIO 高低电平
控制电源通断
GPIO 高电平驱动
板载 Wi-Fi (MQTT双向通信)
数据上报 / 指令下发
数据上报 / 指令下发
5V 直流电源
SHT30传感器
(温度/湿度检测)
拟水量传感器
(水位检测)
3颗独立机械按键
(翻页/模式/手动)
ESP32-S3R8N8 主控芯片
(VSCODE + ESP-IDF C语言开发)
0.96寸 OLED显示屏
(本地数据显示)
继电器模块
5V 超声波加湿器
有源蜂鸣器
(缺水报警)
华为云 IoT 物联网服务器
(MQTT 协议)
Windows 电脑上位机
Android 手机 APP
1.6 实物图
、、
1.7 模块的技术详情介绍
(1) 主控芯片模块(ESP32-S3R8N8)
ESP32-S3R8N8 是一款集成 2.4 GHz Wi-Fi 和低功耗蓝牙 (Bluetooth LE) 的双核微处理器芯片,专为物联网(IoT)市场设计。该芯片搭载 Xtensa 32 位 LX7 双核处理器,主频高达 240 MHz,内置 8MB PSRAM(八线)与 8MB Flash,为处理复杂的网络协议栈和多外设调度提供了强大的算力与存储保障。在本项目中,它作为整个智能加湿器系统的控制中枢,不仅负责通过 I2C、SPI、ADC 等底层总线协议驱动温湿度传感器、OLED 屏幕及执行机构,同时还依靠其原生的无线通信能力运行 MQTT 协议,承载着本地数据处理与华为云端双向通信的核心任务。
(2) 温湿度检测模块(SHT30)
SHT30 是由 Sensirion 公司推出的一款高精度、低功耗的数字式温湿度传感器模块。该传感器采用标准的 I2C 通信接口,内部集成了放大的声表面波(SAW)湿度传感器和带隙温度传感器,具有极强的抗干扰能力与长期的稳定性。在系统中,SHT30 负责对加湿器周围的环境温湿度进行高频次、高精度的实时采集,并将其转化为数字信号输出给 ESP32-S3。主控芯片据此获取准确的环境温度(SHT30_T)与环境湿度(SHT30_H),该模块的数据是系统在“自动模式”下判断是否启动加湿的核心逻辑依据。
(3) 加湿控制模块(5V加湿器与继电器)
加湿执行机构由一个 5V 供电的微型超声波加湿器模块和一个电磁继电器模块组合而成。由于加湿器工作时需要稳定的 5V 电源,且微控制器的 GPIO 引脚无法直接驱动大电流设备,因此项目引入了继电器作为电子开关。继电器模块利用微弱的控制信号来驱动机械触点,实现弱电控制侧与强电负载侧的物理隔离。ESP32-S3 通过单引脚输出高低电平,控制继电器内部线圈的通断,从而间接控制 5V 加湿器电源线的闭合与断开。无论是本地按键触发、反向云端控制,还是自动模式下的逻辑触发,最终都通过该模块执行加湿器的启停。
(4) 水位检测模块(模拟量水量传感器)
水量监测采用了一款专门的模拟量输出水位传感器,用于实时感知加湿器水箱内部的存水量。该传感器表面覆有平行的导电走线,当其浸入水中时,走线之间的电导率会随着浸入深度的变化而改变,从而输出一个与水量成正比的模拟电压信号。ESP32-S3 通过内部集成的 ADC(模数转换器)接口对该电压进行高精度采样,并在软件算法中将模拟电压值换算为具体的水量数据(adc_water)。该模块是系统安全机制的基石,用于判定水箱是否进入缺水状态。
(5) 报警提示模块(高电平触发有源蜂鸣器)
报警提示模块选用了高电平触发的有源蜂鸣器。有源蜂鸣器内部自带震荡源,只需通入直流高电平电压即可直接发出固定频率的蜂鸣声,相比无源蜂鸣器,其控制逻辑更为简单高效。在本项目中,该模块与水位检测模块形成软件上的紧密联动:当主控芯片根据 ADC 采样数据判定加湿器已经处于没水状态时,会立即向蜂鸣器的控制引脚写入高电平,触发连续的警报声以提醒用户及时加水;而当水量恢复充足时,引脚拉低,蜂鸣器立即停止报警,起到直观的硬件状态提示作用。
(6) 本地显示模块(0.96寸OLED屏)
本地信息交互采用了一块 0.96 寸的单色 OLED(有机发光二极管)显示屏。该屏幕分辨率为
128
×
64
128 times 64
128×64,由于其自发光的特性,具备高对比度、广视角以及低功耗的优点。屏幕通过 4 线制 SPI 串行总线协议与 ESP32-S3 进行高速通信。它作为系统的本地“视窗”,负责动态、直观地刷新并显示系统当前的所有核心运行参数,包括环境温湿度、当前水量、加湿器的开关状态、系统当前的运行模式(自动/手动)以及预设的湿度阈值,使用户在不查看手机的情况下也能对设备状态一目了然。
(7) 按键交互模块(独立机械按键)
本地控制输入由 3 颗独立的机械式按压按键组成,它们通过 GPIO 引脚直接与 ESP32-S3 相连。为了消除机械触点在按下和弹起瞬间产生的电平抖动,系统在软件层面对其进行了防抖处理。3 颗按键各自承载着明确的本地控制功能:按键 1 负责切换 OLED 显示屏的显示页面以滚动查看不同数据;按键 2 专门用于在“自动模式”和“手动模式”之间进行一键切换;按键 3 则提供手动控制权限,允许用户在手动模式下直接强制开启或关闭加湿器。
(8) 电源供电模块(5V电源)
电源供电模块是整个硬件系统稳定运行的电力保障。本项目采用统一的 5V 直流电源进行整机供电。输入进来的 5V 电源分为两条路径:一条路径直接供给需要 5V 驱动的电磁继电器、5V 超声波加湿器模块以及有源蜂鸣器;另一条路径则通过开发板板载的低压差线性稳压器(LDO)将 5V 电压降至 3.3V,为 ESP32-S3 主控芯片、SHT30 温湿度传感器以及 0.96 寸 OLED 显示屏提供纯净稳定的数字电源,确保系统在联网上报和加湿器启停切换时不会因电压波动而死机。
三、部署华为云物联网平台
华为云官网: https://www.huaweicloud.com/
打开官网,搜索物联网,就能快速找到 设备接入IoTDA。
3.1 物联网平台介绍
华为云物联网平台(IoT 设备接入云服务)提供海量设备的接入和管理能力,将物理设备联接到云,支撑设备数据采集上云和云端下发命令给设备进行远程控制,配合华为云其他产品,帮助快速构筑物联网解决方案。
使用物联网平台构建一个完整的物联网解决方案主要包括3部分:物联网平台、业务应用和设备。
物联网平台作为连接业务应用和设备的中间层,屏蔽了各种复杂的设备接口,实现设备的快速接入;同时提供强大的开放能力,支撑行业用户构建各种物联网解决方案。
设备可以通过固网、2G/3G/4G/5G、NB-IoT、Wifi等多种网络接入物联网平台,并使用LWM2M/CoAP、MQTT、HTTPS协议将业务数据上报到平台,平台也可以将控制命令下发给设备。
业务应用通过调用物联网平台提供的API,实现设备数据采集、命令下发、设备管理等业务场景。

3.2 开通物联网服务
地址: https://www.huaweicloud.com/product/iothub.html
开通免费单元。
点击立即创建。
正在创建标准版实例,需要等待片刻。
创建完成之后,点击详情。 可以看到标准版实例的设备接入端口和地址。
下面框起来的就是端口号和域名
点击实例名称,可以查看当前免费单元的配置情况。
开通之后,点击接入信息,也能查看接入信息。 当前设备准备采用MQTT协议接入华为云平台,这里可以看到MQTT协议的地址和端口号等信息。
总结:
端口号: MQTT (1883)| MQTTS (8883)
接入地址: dab1a1f2c6.st1.iotda-device.cn-north-4.myhuaweicloud.com
根据域名地址得到IP地址信息:
打开Windows电脑的命令行控制台终端,使用ping 命令。ping一下即可。
Microsoft Windows [版本 10.0.19045.5011]
(c) Microsoft Corporation。保留所有权利。
C:UsersLenovo>ping dab1a1f2c6.st1.iotda-device.cn-north-4.myhuaweicloud.com
正在 Ping dab1a1f2c6.st1.iotda-device.cn-north-4.myhuaweicloud.com [117.78.5.125] 具有 32 字节的数据:
来自 117.78.5.125 的回复: 字节=32 时间=37ms TTL=44
来自 117.78.5.125 的回复: 字节=32 时间=37ms TTL=44
来自 117.78.5.125 的回复: 字节=32 时间=37ms TTL=44
来自 117.78.5.125 的回复: 字节=32 时间=37ms TTL=44
117.78.5.125 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 37ms,最长 = 37ms,平均 = 37ms
C:UsersLenovo>
MQTT协议接入端口号有两个,1883是非加密端口,8883是证书加密端口,单片机无法加载证书,所以使用1883端口合适。
3.3 创建产品
链接:https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-dev/all-product?instanceId=03c5c68c-e588-458c-90c3-9e4c640be7af
(1)创建产品
(2)填写产品信息
根据自己产品名字填写,下面的设备类型选择自定义类型。
(3)产品创建成功
创建完成之后点击查看详情。
(4)添加自定义模型
产品创建完成之后,点击进入产品详情页面,翻到最下面可以看到模型定义。
模型简单来说: 就是存放设备上传到云平台的数据。
当前设备需要与云平台交互的属性如下: 接下来就按照下面的属性创建 华为云平台的模型。
SHT30_T 环境温度 整型
SHT30_H 环境湿度 整型
adc_water 水量检测 浮点数类型
motor_sw 加湿器开关 BOOL类型
RunMode 运行模式 BOOL类型
SHT30_H_MAX 湿度阀值 整型
先点击自定义模型。
【1】创建服务ID
名字设置为: stm32
然后点击新增属性。
【2】SHT30_T 环境温度 整型
【3】SHT30_H 环境湿度 整型
【4】adc_water 水量检测 浮点数类型
【5】motor_sw 加湿器开关 BOOL类型
【6】RunMode 运行模式 BOOL类型
【7】SHT30_H_MAX 湿度阀值 整型
(5)创建完成
3.4 添加设备
产品是属于上层的抽象模型,接下来在产品模型下添加实际的设备。添加的设备最终需要与真实的设备关联在一起,完成数据交互。
(1)注册设备
(2)根据自己的设备填写
(3)保存设备信息
创建完毕之后,点击保存并关闭,得到创建的设备密匙信息。该信息在后续生成MQTT三元组的时候需要使用。
内容信息。
{
"device_id": "67b0606c2ff1872637db980c_dev1",
"secret": "12345678"
}
(4)设备创建完成
(5)设备详情
点击详情。
下面是详情说明:
3.5 MQTT协议主题订阅与发布
(1)MQTT协议介绍
当前的设备是采用MQTT协议与华为云平台进行通信。
MQTT是一个物联网传输协议,它被设计用于轻量级的发布/订阅式消息传输,旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务。MQTT是专门针对物联网开发的轻量级传输协议。MQTT协议针对低带宽网络,低计算能力的设备,做了特殊的优化,使得其能适应各种物联网应用场景。目前MQTT拥有各种平台和设备上的客户端,已经形成了初步的生态系统。
MQTT是一种消息队列协议,使用发布/订阅消息模式,提供一对多的消息发布,解除应用程序耦合,相对于其他协议,开发更简单;MQTT协议是工作在TCP/IP协议上;由TCP/IP协议提供稳定的网络连接;所以,只要具备TCP协议栈的网络设备都可以使用MQTT协议。 本次设备采用的ESP8266就具备TCP协议栈,能够建立TCP连接,所以,配合STM32代码里封装的MQTT协议,就可以与华为云平台完成通信。
华为云的MQTT协议接入帮助文档在这里: https://support.huaweicloud.com/devg-iothub/iot_02_2200.html

业务流程:

(2)华为云平台MQTT协议使用限制
| 描述 | 限制 |
|---|---|
| 支持的MQTT协议版本 | 3.1.1 |
| 与标准MQTT协议的区别 | 支持Qos 0和Qos 1支持Topic自定义不支持QoS2不支持will、retain msg |
| MQTTS支持的安全等级 | 采用TCP通道基础 + TLS协议(最高TLSv1.3版本) |
| 单帐号每秒最大MQTT连接请求数 | 无限制 |
| 单个设备每分钟支持的最大MQTT连接数 | 1 |
| 单个MQTT连接每秒的吞吐量,即带宽,包含直连设备和网关 | 3KB/s |
| MQTT单个发布消息最大长度,超过此大小的发布请求将被直接拒绝 | 1MB |
| MQTT连接心跳时间建议值 | 心跳时间限定为30至1200秒,推荐设置为120秒 |
| 产品是否支持自定义Topic | 支持 |
| 消息发布与订阅 | 设备只能对自己的Topic进行消息发布与订阅 |
| 每个订阅请求的最大订阅数 | 无限制 |
(3)主题订阅格式
帮助文档地址:https://support.huaweicloud.com/devg-iothub/iot_02_2200.html
对于设备而言,一般会订阅平台下发消息给设备 这个主题。
设备想接收平台下发的消息,就需要订阅平台下发消息给设备 的主题,订阅后,平台下发消息给设备,设备就会收到消息。
如果设备想要知道平台下发的消息,需要订阅上面图片里标注的主题。
以当前设备为例,最终订阅主题的格式如下:
$oc/devices/{device_id}/sys/messages/down
最终的格式:
$oc/devices/67b0606c2ff1872637db980c_dev1/sys/messages/down
(4)主题发布格式
对于设备来说,主题发布表示向云平台上传数据,将最新的传感器数据,设备状态上传到云平台。
这个操作称为:属性上报。
帮助文档地址:https://support.huaweicloud.com/api-iothub/iot_06_v5_3010.html
根据帮助文档的介绍, 当前设备发布主题,上报属性的格式总结如下:
发布的主题格式:
$oc/devices/{device_id}/sys/properties/report
最终的格式:
$oc/devices/67b0606c2ff1872637db980c_dev1/sys/properties/report
发布主题时,需要上传数据,这个数据格式是JSON格式。
上传的JSON数据格式如下:
{
"services": [
{
"service_id": <填服务ID>,
"properties": {
"<填属性名称1>": <填属性值>,
"<填属性名称2>": <填属性值>,
..........
}
}
]
}
根据JSON格式,一次可以上传多个属性字段。 这个JSON格式里的,服务ID,属性字段名称,属性值类型,在前面创建产品的时候就已经介绍了,不记得可以翻到前面去查看。
比如当前设备的数据格式如下:
{"services": [{"service_id": "stm32","properties":{"SHT30_T":18.1,"SHT30_H":16.2,"adc_water":60,"RunMode":1,"motor_sw":1,"SHT30_H_MAX":40}}]}
3.6 MQTT三元组
MQTT协议登录需要填用户ID,设备ID,设备密码等信息,就像平时登录QQ,微信一样要输入账号密码才能登录。MQTT协议登录的这3个参数,一般称为MQTT三元组。
接下来介绍,华为云平台的MQTT三元组参数如何得到。
(1)MQTT服务器地址
要登录MQTT服务器,首先记得先知道服务器的地址是多少,端口是多少。
帮助文档地址:https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-portal/overview?instanceId=03c5c68c-e588-458c-90c3-9e4c640be7af
MQTT协议的端口支持1883和8883,它们的区别是:8883 是加密端口更加安全。但是单片机上使用比较困难,所以当前的设备是采用1883端口进连接的。
根据上面的域名和端口号,得到下面的IP地址和端口号信息: 如果设备支持填写域名可以直接填域名,不支持就直接填写IP地址。 (IP地址就是域名解析得到的)
华为云的MQTT服务器地址:117.78.5.125
华为云的MQTT端口号:1883
如何得到IP地址?如何域名转IP? 打开Windows的命令行输入以下命令。
ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com
(2)生成MQTT三元组
华为云提供了一个在线工具,用来生成MQTT鉴权三元组: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com
打开这个工具,填入设备的信息(也就是刚才创建完设备之后保存的信息),点击生成,就可以得到MQTT的登录信息了。
下面是打开的页面:
填入设备的信息: (上面两行就是设备创建完成之后保存得到的)
直接得到三元组信息。
得到三元组之后,设备端通过MQTT协议登录鉴权的时候,填入参数即可。
ClientId 6793a4dcef99673c8ae328d8_dev1_0_0_2025012414
Username 6793a4dcef99673c8ae328d8_dev1
Password ce8e657b1d75c2903a4e764af5d34058b8943a107c0638f7a5c9f7f8b0f1192c
3.7 模拟设备登录测试
经过上面的步骤介绍,已经创建了产品,设备,数据模型,得到MQTT登录信息。 接下来就用MQTT客户端软件模拟真实的设备来登录平台。测试与服务器通信是否正常。
MQTT软件下载地址【免费】: https://download.csdn.net/download/xiaolong1126626497/89928772
(1)填入登录信息
打开MQTT客户端软件,对号填入相关信息(就是上面的文本介绍)。然后,点击登录,订阅主题,发布主题。
点击之后的效果:
(2)打开网页查看
完成上面的操作之后,打开华为云网页后台,可以看到设备已经在线了。
点击详情页面,可以看到上传的数据:
到此,云平台的部署已经完成,设备已经可以正常上传数据了。
四、上位机开发
4.1 Qt开发环境安装
Qt的中文官网: https://www.qt.io/zh-cn/
QT5.12.6的下载地址:https://download.qt.io/archive/qt/5.12/5.12.6
打开下载链接后选择下面的版本进行下载:
如果下载不了,可以在网盘里找到安装包下载: 飞书文档记录的网盘地址:https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
软件安装时断网安装,否则会提示输入账户。
安装的时候,第一个复选框里的编译器可以全选,直接点击下一步继续安装。
选择编译器: (一定要看清楚了)
4.2 新建上位机工程
前面2讲解了需要用的API接口,接下来就使用Qt设计上位机,设计界面,完成整体上位机的逻辑设计。
【1】新建工程
【2】设置项目的名称。
【3】选择编译系统
【4】选择默认继承的类
【5】选择编译器
【6】点击完成
【7】工程创建完成
4.3 切换编译器
在左下角是可以切换编译器的。 可以选择用什么样的编译器编译程序。
目前新建工程的时候选择了2种编译器。 一种是mingw32这个编译Windows下运行的程序。 一种是Android编译器,可以生成Android手机APP。
不过要注意:Android的编译器需要配置一些环境才可以正常使用,这个大家可以网上找找教程配置一下就行了。
windows的编译器就没有这么麻烦,安装好Qt就可以编译使用。
下面我这里就选择的 mingw32这个编译器,编译Windows下运行的程序。
4.4 编译测试功能
创建完毕之后,编译测试一下功能是否OK。
点击左下角的绿色三角形按钮。
正常运行就可以看到弹出一个白色的框框。这就表示工程环境没有问题了。 接下来就可以放心的设计界面了。
4.5 设计UI界面与工程配置
【1】打开UI文件
打开默认的界面如下:
【2】开始设计界面
根据自己需求设计界面。
5.5 编译Windows上位机
点击软件左下角的绿色三角形按钮进行编译运行。
编译之后的效果:
点击更新Toekn,在点击自动更新。
5.6 配置Android环境
如果想编译Android手机APP,必须要先自己配置好自己的Android环境。
然后才可以进行下面的步骤。
【1】选择Android编译器
选择编译器。
切换编译器。
【2】创建Android配置文件
创建完成。
【3】配置Android图标与名称
【3】编译Android上位机
Qt本身是跨平台的,直接选择Android的编译器,就可以将程序编译到Android平台。
然后点击构建。
成功之后,在目录下可以看到生成的apk文件,也就是Android手机的安装包,电脑端使用QQ发送给手机QQ,手机登录QQ接收,就能直接安装。
生成的apk的目录在哪里呢? 编译完成之后,在控制台会输出APK文件的路径。
知道目录在哪里之后,在Windows的文件资源管理器里,找到路径,具体看下图,找到生成的apk文件。
-- File: D:/QtProject/build-307_QtProject-Android_for_arm64_v8a_Clang_Qt_5_12_6_for_Android_ARM64_v8a-Release/android-build//build/outputs/apk/debug/android-build-debug.apk
安装运行效果:
5.7 设备仿真调试
通过MQTT客户端模拟设备登录华为云服务器。进行设备联调,实现数据上传测试。
六、ESP32代码设计
#include <stdio.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_log.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "nvs_flash.h"
#include "mqtt_client.h"
// 引入您项目对应的底层驱动头文件(实际开发中需实现这些接口)
// #include "sht30.h"
// #include "oled_spi.h"
static const char *TAG = "SMART_HUMIDIFIER";
// --- 硬件引脚定义 ---
#define GPIO_RELAY 18 // 继电器控制引脚
#define GPIO_BUZZER 19 // 有源蜂鸣器控制引脚
#define GPIO_KEY1 4 // 按键1:OLED翻页
#define GPIO_KEY2 5 // 按键2:自动/手动模式切换
#define GPIO_KEY3 6 // 按键3:手动开关加湿器
#define ADC_WATER_CH ADC1_CHANNEL_0 // 模拟量水位检测引脚 (例如 GPIO1)
// --- 全局变量(对应上传华为云的数据类型) ---
int SHT30_T = 0; // 环境温度
int SHT30_H = 0; // 环境湿度
float adc_water = 0.0f; // 水量检测值
bool motor_sw = false; // 加湿器开关状态 (false:关, true:开)
bool RunMode = false; // 运行模式 (false:手动, true:自动)
int SHT30_H_MAX = 60; // 湿度阈值(默认60%)
// --- 本地状态变量 ---
uint8_t oled_page = 0; // OLED当前页码
esp_mqtt_client_handle_t mqtt_client = NULL;
bool is_wifi_connected = false;
// --- 模拟底层硬件接口(实际开发时替换为真实驱动) ---
void SHT30_Read_Data(int *temp, int *hum) {
// 实际应为I2C读取
*temp = 25;
*hum = 45;
}
void OLED_Refresh_Display(void) {
// 实际应通过SPI刷屏,根据 oled_page 显示不同数据
// 页1显示: 温湿度、水量; 页2显示: 状态、模式、阈值
}
// --- 硬件初始化 ---
void hardware_init(void) {
// 1. 初始化输出引脚:继电器与蜂鸣器
gpio_config_t io_conf = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_OUTPUT,
.pin_bit_mask = (1ULL << GPIO_RELAY) | (1ULL << GPIO_BUZZER),
.pull_down_en = 0,
.pull_up_en = 0
};
gpio_config(&io_conf);
gpio_set_level(GPIO_RELAY, 0);
gpio_set_level(GPIO_BUZZER, 0);
// 2. 初始化输入引脚:3个独立按键(带上拉)
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pin_bit_mask = (1ULL << GPIO_KEY1) | (1ULL << GPIO_KEY2) | (1ULL << GPIO_KEY3);
io_conf.pull_up_en = 1;
gpio_config(&io_conf);
// 3. 初始化ADC(水位检测)
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC_WATER_CH, ADC_ATTEN_DB_11);
ESP_LOGI(TAG, "Hardware peripherals initialized.");
}
// --- Wi-Fi 与 MQTT 回调事件处理 ---
static void mqtt_event_handler(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data) {
esp_mqtt_event_handle_t event = event_data;
switch ((esp_mqtt_event_id_t)event_id) {
case MQTT_EVENT_CONNECTED:
ESP_LOGI(TAG, "MQTT Connected to Huawei Cloud.");
// 订阅华为云下发命令的Topic(实际Topic需根据华为云产品ID和设备名替换)
esp_mqtt_client_subscribe(mqtt_client, "$oc/devices/YOUR_DEVICE_ID/sys/commands/#", 0);
break;
case MQTT_EVENT_DATA:
ESP_LOGI(TAG, "MQTT Data Received. Topic=%.*s", event->topic_len, event->topic);
// 解析来自手机APP或上位机的控制指令(下发JSON格式)
// 实际开发中需使用 cJSON 库解析诸如 motor_sw, RunMode, SHT30_H_MAX 的控制字段
break;
default:
break;
}
}
static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
is_wifi_connected = false;
esp_wifi_connect();
ESP_LOGI(TAG, "Retrying connection to Wi-Fi...");
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
is_wifi_connected = true;
ESP_LOGI(TAG, "Wi-Fi Connected. Initializing MQTT...");
// 华为云MQTT连接配置(根据实际参数填写)
esp_mqtt_client_config_t mqtt_cfg = {
.uri = "mqtt://YOUR_HUAWEI_CLOUD_ENDPOINT:1883",
.client_id = "YOUR_DEVICE_ID_CLIENT_ID",
.username = "YOUR_HUAWEI_CLOUD_USERNAME",
.password = "YOUR_HUAWEI_CLOUD_PASSWORD",
};
mqtt_client = esp_mqtt_client_init(&mqtt_cfg);
esp_mqtt_client_register_event(mqtt_client, ESP_EVENT_ANY_ID, mqtt_event_handler, NULL);
esp_mqtt_client_start(mqtt_client);
}
}
void wifi_init_sta(void) {
esp_netif_init();
esp_event_loop_create_default();
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, &instance_any_id);
esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, &instance_got_ip);
wifi_config_t wifi_config = {
.sta = {
.ssid = "YOUR_WIFI_SSID",
.password = "YOUR_WIFI_PASSWORD",
},
};
esp_wifi_set_mode(WIFI_MODE_STA);
esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
esp_wifi_start();
}
// --- FreeRTOS任务1:按键扫描与本地交互 ---
void button_task(void *pvParameters) {
bool last_k1 = true, last_k2 = true, last_k3 = true;
while (1) {
bool k1 = gpio_get_level(GPIO_KEY1);
bool k2 = gpio_get_level(GPIO_KEY2);
bool k3 = gpio_get_level(GPIO_KEY3);
// 按键1:OLED 翻页
if (last_k1 && !k1) { // 检测到下降沿
vTaskDelay(pdMS_TO_TICKS(20)); // 软件防抖
if (gpio_get_level(GPIO_KEY1) == 0) {
oled_page = !oled_page; // 2页来回切换
ESP_LOGI(TAG, "Key1 Pressed: Screen Page Switched to %d", oled_page);
}
}
// 按键2:自动/手动模式切换
if (last_k2 && !k2) {
vTaskDelay(pdMS_TO_TICKS(20));
if (gpio_get_level(GPIO_KEY2) == 0) {
RunMode = !RunMode;
ESP_LOGI(TAG, "Key2 Pressed: RunMode Changed to %s", RunMode ? "AUTO" : "MANUAL");
}
}
// 按键3:手动模式下开启/关闭加湿器
if (last_k3 && !k3) {
vTaskDelay(pdMS_TO_TICKS(20));
if (gpio_get_level(GPIO_KEY3) == 0) {
if (!RunMode) { // 只有在手动模式下才起作用
motor_sw = !motor_sw;
ESP_LOGI(TAG, "Key3 Pressed: Manual Motor Switch to %s", motor_sw ? "ON" : "OFF");
}
}
}
last_k1 = k1; last_k2 = k2; last_k3 = k3;
vTaskDelay(pdMS_TO_TICKS(10)); // 扫描周期10ms
}
}
// --- FreeRTOS任务2:传感器采集与核心逻辑控制 ---
void sensor_control_task(void *pvParameters) {
while (1) {
// 1. 读取温湿度
SHT30_Read_Data(&SHT30_T, &SHT30_H);
// 2. 读取水位 (ADC)
int adc_raw = adc1_get_raw(ADC_WATER_CH);
// 根据传感器特性,将0~4095的原始值转换为水量数值(此处作简化线性映射)
adc_water = ((float)adc_raw / 4095.0f) * 100.0f;
// 3. 核心逻辑控制
// 【安全防线:水位检测优先级最高】
if (adc_water < 10.0f) { // 判定为“没水”阈值
gpio_set_level(GPIO_RELAY, 0); // 强行关闭加湿器,防止干烧
gpio_set_level(GPIO_BUZZER, 1); // 开启蜂鸣器警报
motor_sw = false;
ESP_LOGW(TAG, "WARNING: Water shortage! Humidifier stopped, Buzzer ON.");
}
else {
gpio_set_level(GPIO_BUZZER, 0); // 水量充足,关闭蜂鸣器
// 【模式判定】
if (RunMode) { // 自动模式
if (SHT30_H < SHT30_H_MAX) {
motor_sw = true; // 低于阈值,智能加湿
} else {
motor_sw = false; // 高于阈值,停止加湿
}
}
// 手动模式下 motor_sw 状态完全由按键3或远程APP修改,在此不做逻辑干预
// 执行物理输出
gpio_set_level(GPIO_RELAY, motor_sw ? 1 : 0);
}
// 4. 本地OLED刷新
OLED_Refresh_Display();
vTaskDelay(pdMS_TO_TICKS(500)); // 每500ms循环一次
}
}
// --- FreeRTOS任务3:华为云数据上报 ---
void cloud_report_task(void *pvParameters) {
char payload[256];
while (1) {
if (is_wifi_connected && mqtt_client != NULL) {
// 按照华为云物联网平台指定的设备属性上报JSON格式封装数据
snprintf(payload, sizeof(payload),
"{\"services\": [{\"service_id\": \"Humidifier\",\"properties\": {"
"\"SHT30_T\": %d,"
"\"SHT30_H\": %d,"
"\"adc_water\": %.2f,"
"\"motor_sw\": %s,"
"\"RunMode\": %s,"
"\"SHT30_H_MAX\": %d"
"}}]}",
SHT30_T, SHT30_H, adc_water,
motor_sw ? "true" : "false",
RunMode ? "true" : "false",
SHT30_H_MAX);
// 发布到华为云设备属性上报Topic
esp_mqtt_client_publish(mqtt_client, "$oc/devices/YOUR_DEVICE_ID/sys/properties/report", payload, 0, 1, 0);
ESP_LOGI(TAG, "Data reported to Huawei Cloud: %s", payload);
}
vTaskDelay(pdMS_TO_TICKS(3000)); // 每3秒上报一次数据
}
}
// --- 主函数入口 ---
void app_main(void) {
// 初始化NVS(Wi-Fi和MQTT协议栈必需)
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// 1. 初始化底层硬件IO
hardware_init();
// 2. 初始化网络STA模式并连接华为云
wifi_init_sta();
// 3. 创建FreeRTOS多任务并行处理业务
xTaskCreate(button_task, "button_task", 3072, NULL, 5, NULL);
xTaskCreate(sensor_control_task, "sensor_control_task", 4096, NULL, 4, NULL);
xTaskCreate(cloud_report_task, "cloud_report_task", 4096, NULL, 3, NULL);
}
代码架构说明
- 多任务并行 (FreeRTOS):
button_task:独立扫描按键,确保每10ms消抖并响应本地交互,不会因为网络阻塞导致按键卡顿。sensor_control_task:500ms周期轮询温湿度和水位。缺水防干烧逻辑放在首位判断,拥有最高控制权。cloud_report_task:3秒周期将6个目标参数封装为标准华为云JSON payload并通过MQTT送出。
- 数据类型契合:温度、湿度、阈值采用
int;水量采用float;模式与加湿开关采用bool。
复刻资料包下载
开发工具下载网盘:https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink
【嘉立创导入工程与PCB下单制板的过程演示(2026)】 https://www.bilibili.com/video/BV1vz6RB1Egt/?share_source=copy_web&vd_source=347136f3e32fe297fc17177194ce0a8b
【嘉立创如何一键下单购买元器件?】 https://www.bilibili.com/video/BV1fszyBHEuA/?share_source=copy_web&vd_source=347136f3e32fe297fc17177194ce0a8b
【项目复刻_PCB焊接过程演示】 https://www.bilibili.com/video/BV1FmPVzYEVx/?share_source=copy_web&vd_source=347136f3e32fe297fc17177194ce0a8b
87