1. 项目概述
这个基于STM32的WiFi远程温控风扇系统,是我去年指导的一个通信工程专业学生的毕业设计。当时学生找到我的时候,提出了一个特别实用的想法:能不能做一个可以通过手机远程控制,又能根据环境温度自动调节的风扇系统?这个需求听起来简单,但实际做起来涉及到了嵌入式开发、无线通信、传感器技术等多个领域的知识整合。
作为一个在智能硬件领域摸爬滚打多年的工程师,我一眼就看出这个项目的价值所在。它不仅涵盖了通信工程专业的核心知识点,还具有很强的实用性和市场潜力。想象一下,在炎热的夏天,你可以在回家前就通过手机打开风扇,让它根据室内温度自动调节风速,这种体验多么惬意!
2. 系统设计与核心组件选型
2.1 硬件架构设计
整个系统的硬件架构可以分为三个主要部分:控制核心、感知层和执行层。控制核心自然选择了STM32系列单片机,具体型号我们选用了STM32F103C8T6,也就是俗称的"蓝莓派"。这款芯片性价比极高,72MHz主频足够应对我们的需求,而且外设资源丰富,最重要的是开发资料齐全,非常适合学生项目。
感知层包括两个关键传感器:DHT11温湿度传感器和红外人体感应模块。DHT11负责采集环境温湿度数据,虽然精度不算特别高(±2℃),但对于风扇控制来说完全够用。红外模块则用于检测是否有人在场,实现"人在开,人走关"的节能模式。
执行层就是风扇电机及其驱动电路了。考虑到安全性和控制精度,我们选择了带PWM调速的直流风扇,通过MOS管驱动,可以实现无级调速。整个系统的供电采用5V/2A的开关电源,确保稳定可靠。
2.2 通信模块选型
WiFi模块的选择是整个项目的关键之一。我们对比了ESP8266和ESP32两种方案:
| 型号 | 价格 | 功耗 | 开发难度 | 功能特性 |
|---|---|---|---|---|
| ESP8266 | 较低 | 较低 | 较简单 | 基础WiFi功能 |
| ESP32 | 稍高 | 稍高 | 较复杂 | 双核、蓝牙、更强大外设 |
考虑到项目主要需要WiFi功能,且学生是第一次做物联网项目,最终选择了ESP8266(ESP-01S型号)。这个模块价格不到20元,通过串口与STM32通信,AT指令相对简单,资料也非常丰富。
提示:ESP-01S模块有多个固件版本,建议使用安信可官方提供的AT固件,稳定性最好。刷写固件时需要特别注意电压匹配,避免烧毁模块。
2.3 软件架构设计
软件部分采用了分层设计的思想:
- 底层驱动层:包括STM32的外设初始化、PWM生成、定时器配置等
- 传感器数据采集层:定时读取DHT11和红外模块数据
- 通信协议层:处理与ESP8266的AT指令交互
- 业务逻辑层:实现温度控制算法、远程指令解析
- 用户接口层:包括本地按键控制和手机APP远程控制
这种分层设计使得各功能模块耦合度低,便于调试和维护。例如当需要更换WiFi模块时,只需修改通信协议层的代码,其他部分基本不受影响。
3. 核心功能实现细节
3.1 温度采集与滤波处理
DHT11传感器的数据采集看似简单,实则暗藏玄机。这个传感器采用单总线协议,对时序要求非常严格。我们在实际调试中发现,直接读取的数据经常会出现跳变,严重影响控制效果。
解决方法是通过软件滤波算法对原始数据进行处理。具体实现采用了滑动平均滤波结合限幅滤波的方式:
c复制#define FILTER_LEN 5
static float temp_history[FILTER_LEN] = {0};
static uint8_t filter_index = 0;
float filter_temperature(float raw_temp) {
// 限幅滤波:排除明显异常值
static float last_temp = 25.0;
if(fabs(raw_temp - last_temp) > 5.0) {
return last_temp;
}
// 滑动平均滤波
temp_history[filter_index++] = raw_temp;
if(filter_index >= FILTER_LEN) filter_index = 0;
float sum = 0;
for(int i=0; i<FILTER_LEN; i++) {
sum += temp_history[i];
}
last_temp = sum / FILTER_LEN;
return last_temp;
}
这种组合滤波方式有效平滑了数据波动,实测可以将温度读数波动控制在±0.5℃以内,大大提升了系统的稳定性。
3.2 WiFi通信协议设计
ESP8266模块通过AT指令与STM32交互,我们需要设计一套简洁高效的通信协议。考虑到数据量不大,我们采用了文本格式的协议设计,格式如下:
code复制[命令类型][分隔符][参数1][分隔符][参数2]\r\n
具体命令示例:
- 温度上报:
TEMP:25.6\r\n - 风速设置:
FAN:3\r\n(1-5档) - 模式切换:
MODE:A\r\n(A自动/M手动)
在STM32端,我们使用串口中断接收数据,通过状态机解析协议:
c复制typedef enum {
WAIT_START,
IN_COMMAND,
IN_PARAM
} ParserState;
void USART_IRQHandler(void) {
static ParserState state = WAIT_START;
static char cmd[10];
static char param[20];
static uint8_t cmd_idx = 0, param_idx = 0;
uint8_t ch = USART_ReceiveData(USART1);
switch(state) {
case WAIT_START:
if(ch == 'T' || ch == 'F' || ch == 'M') {
cmd[0] = ch;
cmd_idx = 1;
state = IN_COMMAND;
}
break;
case IN_COMMAND:
if(ch == ':') {
cmd[cmd_idx] = '\0';
state = IN_PARAM;
param_idx = 0;
} else {
cmd[cmd_idx++] = ch;
}
break;
case IN_PARAM:
if(ch == '\r' || ch == '\n') {
param[param_idx] = '\0';
process_command(cmd, param);
state = WAIT_START;
} else {
param[param_idx++] = ch;
}
break;
}
}
这种协议设计简单易懂,调试方便,完全满足了项目需求。在实际测试中,即使在网络不稳定的情况下,也能保证通信的可靠性。
3.3 温度控制算法实现
自动温控是系统的核心功能之一。我们设计了一个基于模糊控制的算法,根据当前温度与目标温度的差值,动态调整风扇转速。具体实现如下:
-
设置三个温度阈值:
- T_low(例如26℃):低于此温度风扇停止
- T_medium(例如28℃):中等风速
- T_high(例如30℃):最大风速
-
在温度区间之间采用线性插值计算风速:
c复制#define FAN_MIN 30 // 最小风速(PWM占空比)
#define FAN_MAX 100 // 最大风速
uint8_t calculate_fan_speed(float current_temp) {
if(current_temp < T_low) return 0;
if(current_temp >= T_high) return FAN_MAX;
if(current_temp < T_medium) {
// 在T_low和T_medium之间线性插值
return FAN_MIN + (FAN_MAX - FAN_MIN) *
(current_temp - T_low) / (T_medium - T_low);
} else {
// 在T_medium和T_high之间线性插值
return FAN_MIN + (FAN_MAX - FAN_MIN) *
(current_temp - T_medium) / (T_high - T_medium);
}
}
这种算法实现简单,响应快速,实测效果非常好。用户还可以通过手机APP自定义这三个温度阈值,满足个性化需求。
4. 手机APP远程控制实现
4.1 APP功能设计
为了方便用户远程控制,我们开发了一个简单的Android APP,主要功能包括:
- 实时显示当前温度和风扇状态
- 手动控制风扇开关和风速
- 设置自动模式下的温度阈值
- 定时开关机功能
- 历史温度曲线查看
APP界面设计遵循KISS原则(Keep It Simple, Stupid),主要操作都能在首页完成,高级功能通过侧边栏菜单进入。
4.2 通信协议实现
APP与硬件设备之间通过MQTT协议通信,这是物联网领域最常用的轻量级协议之一。我们在ESP8266上实现了MQTT客户端,连接到免费的公共MQTT服务器(如test.mosquitto.org)。
通信主题设计如下:
- 设备上报:
device/[MAC地址]/sensor - 控制命令:
device/[MAC地址]/control - 参数设置:
device/[MAC地址]/settings
例如,APP发送风速控制命令的JSON格式如下:
json复制{
"cmd": "fan_speed",
"value": 3,
"timestamp": 1625097600
}
设备端接收到命令后,会先校验JSON格式,然后执行相应操作,并返回确认信息:
json复制{
"status": "success",
"cmd": "fan_speed",
"current_value": 3
}
这种设计使得通信过程清晰可靠,也便于后期功能扩展。
4.3 安全性考虑
虽然是一个毕业设计项目,但我们还是考虑了基本的安全性问题:
- 每个设备有唯一的MAC地址作为标识
- 通信数据采用Base64编码,防止明文传输
- APP与设备配对时需要输入配对码(印在设备标签上)
- MQTT连接使用简单的用户名/密码认证
这些措施虽然不能提供企业级的安全保障,但足以应对一般的家庭使用场景,避免了设备被随意控制的风险。
5. 系统集成与调试经验
5.1 硬件组装注意事项
在PCB设计和组装过程中,我们积累了一些宝贵经验:
- 电源部分要预留足够的滤波电容,特别是在电机附近,我们加了4个100μF的电解电容,有效减少了电机干扰
- WiFi模块的天线部分要远离电机和电源线,避免信号干扰
- 所有外接接口(如传感器、电机)都加了保护二极管,防止反接损坏
- 给STM32和ESP8266分别供电,中间用光耦隔离,提高稳定性
重要提示:DHT11传感器的接线不要超过20cm,否则容易出现通信失败。如果必须长距离连接,建议在传感器端加一个上拉电阻。
5.2 软件调试技巧
软件开发过程中,我们采用了以下调试方法:
- 使用STM32的SWD接口配合J-Link调试器,可以单步执行、查看变量
- 通过串口打印详细的调试信息,我们定义了一个宏方便开关调试输出:
c复制#define DEBUG 1
#if DEBUG
#define debug_printf(fmt, ...) printf("[DEBUG] " fmt "\r\n", ##__VA_ARGS__)
#else
#define debug_printf(fmt, ...)
#endif
- 对WiFi模块,先用USB转TTL工具单独测试AT指令,确保模块正常工作
- 使用逻辑分析仪抓取单总线传感器的时序,精确调试通信协议
5.3 典型问题与解决方案
在开发过程中,我们遇到了几个典型问题:
-
问题:ESP8266经常掉线
- 原因:电源不稳定,电机启动时电压跌落
- 解决:给WiFi模块增加1000μF的储能电容,并优化电源布线
-
问题:温度读数偶尔出现异常值
- 原因:DHT11通信被中断打断
- 解决:在读取传感器数据时暂时关闭中断
-
问题:手机APP有时收不到设备消息
- 原因:MQTT服务器连接超时
- 解决:实现心跳机制,定期检查连接状态,自动重连
6. 项目扩展与改进方向
虽然这个毕业设计已经实现了基本功能,但从产品化角度还有很多可以改进的地方:
-
能耗优化:
- 增加红外人体感应功能,无人时自动降低风速或关闭
- 实现基于时间表的智能控制,比如夜间自动降低风速
-
用户体验提升:
- 增加语音控制功能,集成离线语音识别模块
- 开发iOS版本APP,扩大用户覆盖面
- 实现设备分组控制,同时管理多个风扇
-
技术升级:
- 将WiFi模块替换为ESP32,实现蓝牙双模控制
- 加入机器学习算法,学习用户习惯自动优化控制策略
- 改用NB-IoT通信,降低功耗,适合无WiFi环境
这个项目最让我欣慰的是,它不仅帮助学生顺利完成了毕业设计,还让他对嵌入式系统开发有了全面的认识。从硬件选型到软件开发,从传感器调试到无线通信,每个环节都锻炼了解决实际问题的能力。