1. 项目背景与核心需求
最近在整理工作室的毕设项目资料时,翻到了去年指导的一个很有意思的STM32项目——智能换气系统。这个系统特别适合作为计算机/物联网专业的毕业设计选题,既有硬件又有软件,还能结合当下热门的智能家居概念。今天我就把这个项目的完整设计思路和实现细节整理出来,给正在做类似课题的同学参考。
这个系统的核心功能其实很简单:通过传感器监测室内空气质量(主要是CO2浓度),当空气质量变差时自动启动换气设备(比如排气扇)。但要把这个看似简单的功能做稳定、做智能,里面有不少门道。我们团队当时用了STM32F103C8T6作为主控,搭配MH-Z19B二氧化碳传感器和DHT11温湿度传感器,通过PID算法实现了精准控制。
提示:选择STM32F103C8T6是因为它价格适中(约10元)、资源丰富(72MHz主频、64KB Flash),完全能满足这种控制类项目的需求,比用51单片机更专业,又不像F4系列那么贵。
2. 硬件系统设计详解
2.1 核心器件选型
先说说硬件部分的关键器件选择,这是整个项目的基础:
-
主控芯片:STM32F103C8T6(蓝色pill开发板)
- 72MHz Cortex-M3内核
- 64KB Flash + 20KB RAM
- 3个USART、2个SPI、2个I2C
- 价格约10-15元,性价比极高
-
CO2传感器:MH-Z19B
- NDIR原理(非分散红外),比廉价的半导体传感器准得多
- 0-5000ppm量程,±(50ppm+5%读数)精度
- 自带温度补偿,UART/PWM输出
- 注意:需要预热3分钟才能稳定工作
-
温湿度传感器:DHT11
- 虽然精度一般(湿度±5%,温度±2℃)
- 但胜在便宜(约5元)、接口简单(单总线)
- 对于换气系统来说完全够用
-
执行机构:
- 5V继电器模块控制排气扇
- 可选配OLED显示屏(SSD1306)用于本地显示
- 蜂鸣器用于报警提示
2.2 电路设计要点
硬件连接有几个关键点需要注意:
-
传感器供电:
- MH-Z19B需要5V供电,但STM32是3.3V电平
- 需要电平转换或直接接开发板的5V输出
- DHT11可以接3.3V
-
抗干扰设计:
- 继电器线圈要加续流二极管(1N4007)
- 传感器信号线最好加100Ω电阻和104电容滤波
- 电源入口加100μF电解电容
-
PCB布局:
- 传感器尽量远离继电器等大电流器件
- 走线避免形成环路
- 关键信号线尽量短
注意:MH-Z19B的UART RX引脚内部有10K上拉电阻,直接接STM32的TX即可,不需要额外上拉。但如果是PWM输出模式,需要接10K上拉电阻。
3. 软件系统实现
3.1 开发环境搭建
软件部分我们用的是Keil MDK + STM32CubeMX的组合:
-
CubeMX配置:
- 时钟树配置为72MHz(8MHz晶振→PLL×9)
- 启用USART2用于MH-Z19B(9600bps)
- 启用TIM3用于DHT11时序控制
- 配置一个GPIO用于继电器控制
-
代码框架:
c复制// 主循环结构
while(1) {
read_DHT11(&temp, &humi); // 读取温湿度
read_MHZ19(&co2); // 读取CO2浓度
pid_control(co2); // PID控制计算
display_status(); // OLED显示
HAL_Delay(1000); // 1秒周期
}
3.2 传感器驱动开发
MH-Z19B驱动要点:
- 发送读取指令:0xFF 0x01 0x86 0x00 0x00 0x00 0x00 0x00 0x79
- 接收9字节数据,第2-3字节是CO2浓度(高位在前)
- 需要校验和(0xFF - 前面所有字节和的低8位)
示例代码:
c复制uint16_t MHZ19_ReadCO2(void) {
uint8_t cmd[9] = {0xFF,0x01,0x86,0x00,0x00,0x00,0x00,0x00,0x79};
uint8_t buf[9];
HAL_UART_Transmit(&huart2, cmd, 9, 100);
HAL_UART_Receive(&huart2, buf, 9, 100);
// 校验和验证
uint8_t sum = 0;
for(int i=1; i<8; i++) sum += buf[i];
if(buf[8] != (0xFF - sum)) return 0;
return (buf[2]<<8) | buf[3];
}
DHT11驱动要点:
- 主机拉低总线18ms后释放
- 等待传感器响应(83μs低电平+87μs高电平)
- 40位数据(高位在前):湿度整数+湿度小数+温度整数+温度小数+校验和
3.3 PID控制算法实现
为了让换气系统更智能,我们采用了增量式PID算法:
c复制typedef struct {
float Kp, Ki, Kd;
float err, last_err, prev_err;
} PID_TypeDef;
void PID_Init(PID_TypeDef *pid, float Kp, float Ki, float Kd) {
pid->Kp = Kp;
pid->Ki = Ki;
pid->Kd = Kd;
pid->err = pid->last_err = pid->prev_err = 0;
}
float PID_Calculate(PID_TypeDef *pid, float setpoint, float pv) {
pid->err = setpoint - pv;
float delta = pid->Kp*(pid->err - pid->last_err)
+ pid->Ki*pid->err
+ pid->Kd*(pid->err - 2*pid->last_err + pid->prev_err);
pid->prev_err = pid->last_err;
pid->last_err = pid->err;
return delta;
}
参数整定经验:
- 初始值:Kp=1.0, Ki=0.05, Kd=0.1
- 调整原则:
- 先调Kp直到出现小幅振荡
- 然后调Kd抑制振荡
- 最后调Ki消除静差
4. 系统优化与调试
4.1 传感器数据处理
原始传感器数据会有波动,需要做平滑处理:
- 移动平均滤波:
c复制#define FILTER_LEN 5
uint16_t CO2_filter_buf[FILTER_LEN];
uint8_t filter_index = 0;
uint16_t Moving_Average_Filter(uint16_t new_val) {
CO2_filter_buf[filter_index] = new_val;
filter_index = (filter_index + 1) % FILTER_LEN;
uint32_t sum = 0;
for(int i=0; i<FILTER_LEN; i++) sum += CO2_filter_buf[i];
return sum / FILTER_LEN;
}
- 异常值剔除:
- 连续3次读数突变超过100ppm视为异常
- 保留上次有效值
4.2 功耗优化技巧
虽然这个系统通常接市电,但做好低功耗设计总是加分项:
-
传感器间歇工作:
- MH-Z19B每10秒唤醒一次(发送0xFF 0x01 0x79 0x00 0x00 0x00 0x00 0x00 0x86)
- DHT11每分钟读取一次
-
STM32低功耗模式:
c复制// 进入STOP模式
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
// 被唤醒后需要重新初始化时钟
SystemClock_Config();
4.3 常见问题排查
调试过程中我们遇到过这些问题:
-
MH-Z19B读数不稳定:
- 确保预热时间足够(上电后等待3分钟)
- 检查电源电压(不能低于4.5V)
- 避免强光直射传感器(红外干扰)
-
继电器频繁开关:
- 调整PID参数(增大Kd)
- 加入死区控制(±50ppm内不动作)
- 设置最小开关间隔(至少30秒)
-
DHT11读取失败:
- 检查时序是否精确(特别是18ms起始信号)
- 确保上拉电阻(4.7K)正常
- 线长不超过20米
5. 扩展功能建议
如果想让项目更出彩,可以考虑这些扩展:
-
无线通信模块:
- 添加ESP8266实现WiFi连接
- 通过MQTT上传数据到云平台
- 手机APP远程监控和控制
-
多区域联动控制:
- 多个节点通过RS485组网
- 主从机协调换气策略
-
能耗统计功能:
- 记录换气设备运行时间
- 计算预估电费消耗
- 生成节能建议
-
语音交互:
- 集成LD3320语音识别芯片
- 支持"打开换气"等语音指令
这个项目最让我满意的是它的实用性——我们工作室现在用的就是这套系统,配合ESP8266实现了手机远程监控,CO2浓度超过1000ppm自动换气,再也不用担心开会时空气闷了。对于毕设来说,它涵盖了嵌入式开发的完整流程:传感器驱动、控制算法、人机交互,还能结合物联网做扩展,是个非常不错的选题方向。