基于STM32的自动调节风扇设计
一、系统概述与核心功能
1. 系统定位
基于STM32的自动调节风扇系统以“温度感知-智能调速-人机交互-低功耗管理”为核心,通过温度传感器实时监测环境温度,结合PID算法动态调节风扇转速,支持自动/手动模式切换、温度阈值设置、超温报警等功能,适用于智能家居、办公室、机房、温室等场景,兼顾舒适度与节能需求。
2. 核心功能模块
| 模块 | 功能描述 |
|---|---|
| 温度采集 | 支持DS18B20(单总线)或SHT30(I2C)温度传感器,精度±0.5℃,范围-55~125℃ |
| 风扇控制 | PWM无级调速(0-100%),支持软启动/缓停,避免电机冲击 |
| 模式管理 | 自动模式(温度闭环控制)、手动模式(固定转速)、睡眠模式(低转速静音运行) |
| 人机交互 | OLED显示(温度/转速/模式)、3个实体按键(模式切换/加减)、蜂鸣器超温报警 |
| 扩展功能 | 红外遥控、Wi-Fi远程控制(ESP8266)、温湿度联动控制(加湿器/空调) |
| 低功耗设计 | 无操作时进入STOP模式,温度超阈值自动唤醒,锂电池供电续航≥24小时 |
二、硬件设计方案
1. 核心硬件选型
| 模块 | 型号 | 关键参数 | 接口方式 |
|---|---|---|---|
| 主控MCU | STM32F103C8T6 | 72MHz Cortex-M3,64KB Flash,20KB RAM,3个定时器(PWM),12位ADC | 核心控制器 |
| 温度传感器 | DS18B20优先 | 单总线接口,测温范围-55125℃,精度±0.5℃(085℃),防水型可选 | GPIO(PA0,单总线) |
| 风扇驱动 | 直流风扇+MOS管 | 5V/12V直流风扇,IRF540N MOS管驱动,支持0-100% PWM无级调速 | PWM(PA8,TIM1_CH1) |
| 显示模块 | OLED 12864(I2C) | 0.96寸,128×64像素,自发光,低功耗(<10mA),支持图形/字符显示 | I2C1(PB6=SCL,PB7=SDA) |
| 按键模块 | 轻触按键×3 | 模式切换、加、减按键,上拉输入,支持长按/短按识别 | GPIO(PC0-PC2) |
| 电源模块 | 5V/2A电源+锂电池备份 | 输入220V AC→5V/2A,18650锂电池(2000mAh)备份,TP4056充电管理 | 双电源自动切换 |
| 辅助模块 | 有源蜂鸣器+LED | 蜂鸣器(超温报警),LED(红:报警,绿:正常,蓝:休眠) | GPIO(PB0=蜂鸣器,PB1-2=LED) |
2. 硬件电路设计要点
2.1 核心电路连接
- STM32最小系统:8MHz外部晶振+32.768kHz RTC晶振,SWD调试接口(PA13/PA14),复位电路(10kΩ上拉+0.1μF电容)。
- DS18B20温度传感器:VCC=3.3V,DQ=PA0(单总线),4.7kΩ上拉电阻至3.3V,GND共地,防水型需金属外壳接地。
- 风扇驱动电路:STM32 PA8(TIM1_CH1)输出PWM → 1kΩ限流电阻 → IRF540N栅极;漏极接风扇负极;源极接地;风扇正极接5V/12V电源。
2.2 抗干扰与安全设计
- 电源滤波:风扇电源输入端并联1000μF电解电容+0.1μF瓷片电容,滤除电机换向噪声。
- 信号隔离:DS18B20单总线串联100Ω电阻,防止静电损坏GPIO;风扇电源与STM32电源通过磁珠隔离。
- 过流保护:MOS管源极串联0.1Ω采样电阻,ADC采集电流,过流时切断PWM输出。
三、软件设计与核心代码
1. 系统架构(FreeRTOS多任务调度)
采用FreeRTOS实时操作系统,划分4个核心任务(优先级从高到低):
- 温度采集任务(优先级4):周期性读取DS18B20温度,滑动平均滤波后发送至队列。
- PID控制任务(优先级3):根据目标温度与实际温差,计算PID输出(PWM占空比)。
- 风扇驱动任务(优先级2):解析PID输出,更新PWM占空比,实现软启动/缓停。
- 人机交互任务(优先级1):扫描按键、更新OLED显示、处理模式切换。
2. 核心代码实现(基于HAL库)
2.1 DS18B20驱动(单总线时序)
#include "ds18b20.h"
#include "tim.h"
// DS18B20复位与存在脉冲检测
uint8_t DS18B20_Reset(void) {
uint8_t presence = 1;
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); // 拉低总线
delay_us(480); // 复位脉冲480us
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); // 释放总线
delay_us(60); // 等待存在脉冲
presence = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0); // 读取存在脉冲(0=存在)
delay_us(420); // 等待时隙结束
return presence;
}
// 写入1位数据
void DS18B20_WriteBit(uint8_t bit) {
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET);
if (bit) {
delay_us(2); // 写1:拉低2us后释放
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
delay_us(60); // 等待时隙结束
} else {
delay_us(60); // 写0:拉低60us
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET);
delay_us(2); // 恢复时间
}
}
// 读取温度值(摄氏度,精度0.0625℃)
float DS18B20_ReadTemp(void) {
uint8_t temp_l, temp_h;
int16_t temp_raw;
DS18B20_Reset();
DS18B20_WriteByte(0xCC); // 跳过ROM命令
DS18B20_WriteByte(0x44); // 启动温度转换
delay_ms(750); // 12位精度转换时间
DS18B20_Reset();
DS18B20_WriteByte(0xCC); // 跳过ROM命令
DS18B20_WriteByte(0xBE); // 读取暂存器
temp_l = DS18B20_ReadByte();
temp_h = DS18B20_ReadByte();
temp_raw = (temp_h << 8) | temp_l;
return temp_raw * 0.0625f; // 转换为摄氏度
}
2.2 PID温度控制算法
#include "pid.h"
// PID结构体
typedef struct {
float Kp; // 比例系数
float Ki; // 积分系数
float Kd; // 微分系数
float setpoint; // 目标温度
float integral; // 积分项
float prev_error; // 上次误差
float output_min; // 输出最小值(0%)
float output_max; // 输出最大值(100%)
} PID_Controller_t;
PID_Controller_t pid = {
.Kp = 2.0f, // 比例系数(根据风扇特性调整)
.Ki = 0.5f, // 积分系数(消除稳态误差)
.Kd = 0.2f, // 微分系数(抑制超调)
.setpoint = 26.0f, // 默认目标温度26℃
.integral = 0.0f,
.prev_error = 0.0f,
.output_min = 0.0f,
.output_max = 100.0f
};
// PID计算函数
float PID_Calculate(PID_Controller_t *pid, float current_temp) {
float error = pid->setpoint - current_temp; // 误差 = 目标 - 实际
// 比例项
float P = pid->Kp * error;
// 积分项(带抗饱和)
pid->integral += error;
if (pid->integral > pid->output_max) pid->integral = pid->output_max;
if (pid->integral < pid->output_min) pid->integral = pid->output_min;
float I = pid->Ki * pid->integral;
// 微分项
float D = pid->Kd * (error - pid->prev_error);
pid->prev_error = error;
// 计算输出并限幅
float output = P + I + D;
if (output > pid->output_max) output = pid->output_max;
if (output < pid->output_min) output = pid->output_min;
return output; // 返回PWM占空比(0-100%)
}
2.3 风扇PWM驱动(软启动/缓停)
#include "fan_driver.h"
// 风扇状态结构体
typedef struct {
uint8_t target_speed; // 目标转速(%)
uint8_t current_speed; // 当前转速(%)
uint8_t ramp_step; // 渐变步长(%/100ms)
uint8_t is_running; // 运行状态
} Fan_State_t;
Fan_State_t fan_state = {0, 0, 2, 0}; // 默认2%/100ms渐变
// 初始化TIM1_CH1 PWM输出(PA8)
void Fan_PWM_Init(void) {
TIM_HandleTypeDef htim1;
TIM_OC_InitTypeDef sConfigOC = {0};
__HAL_RCC_TIM1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
// GPIO配置:PA8复用推挽输出
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// TIM1时基配置:72MHz / (7199+1) = 10kHz
htim1.Instance = TIM1;
htim1.Init.Prescaler = 7199;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 999; // ARR=999,PWM频率10Hz
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
HAL_TIM_PWM_Init(&htim1);
// PWM通道配置
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0; // 初始占空比0%
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1);
HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1); // 高级定时器需使能互补输出
}
// 风扇转速渐变控制(每100ms调用一次)
void Fan_SpeedRamp(void) {
if (fan_state.current_speed < fan_state.target_speed) {
fan_state.current_speed += fan_state.ramp_step;
if (fan_state.current_speed > fan_state.target_speed) {
fan_state.current_speed = fan_state.target_speed;
}
} else if (fan_state.current_speed > fan_state.target_speed) {
fan_state.current_speed -= fan_state.ramp_step;
if (fan_state.current_speed < fan_state.target_speed) {
fan_state.current_speed = fan_state.target_speed;
}
}
// 更新PWM占空比(ARR=999)
uint16_t pulse = fan_state.current_speed * 10; // 0-100% → 0-1000
__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, pulse);
}
2.4 主程序框架(FreeRTOS任务调度)
#include "stm32f1xx_hal.h"
#include "FreeRTOS.h"
#include "task.h"
#include "ds18b20.h"
#include "pid.h"
#include "fan_driver.h"
#include "oled.h"
// 全局变量
float current_temp = 0.0f;
uint8_t system_mode = 0; // 0=自动,1=手动,2=睡眠
QueueHandle_t temp_queue;
// 温度采集任务
void Temp_Task(void *pvParameters) {
TickType_t xLastWakeTime = xTaskGetTickCount();
const TickType_t xFrequency = pdMS_TO_TICKS(1000); // 1秒采集一次
while (1) {
current_temp = DS18B20_ReadTemp();
xQueueSend(temp_queue, ¤t_temp, 0);
vTaskDelayUntil(&xLastWakeTime, xFrequency);
}
}
// PID控制任务
void PID_Task(void *pvParameters) {
float temp;
uint8_t target_speed;
while (1) {
if (xQueueReceive(temp_queue, &temp, portMAX_DELAY)) {
if (system_mode == 0) { // 自动模式
target_speed = (uint8_t)PID_Calculate(&pid, temp);
fan_state.target_speed = target_speed;
} else if (system_mode == 2) { // 睡眠模式
fan_state.target_speed = 30; // 30%转速静音运行
}
}
vTaskDelay(pdMS_TO_TICKS(100)); // 100ms控制周期
}
}
int main(void) {
HAL_Init();
SystemClock_Config(); // 72MHz
// 初始化外设
MX_GPIO_Init();
MX_TIM1_Init();
Fan_PWM_Init();
OLED_Init();
DS18B20_Init();
// 创建队列和任务
temp_queue = xQueueCreate(5, sizeof(float));
xTaskCreate(Temp_Task, "Temp", 128, NULL, 4, NULL);
xTaskCreate(PID_Task, "PID", 128, NULL, 3, NULL);
xTaskCreate(Fan_Task, "Fan", 128, NULL, 2, NULL);
xTaskCreate(UI_Task, "UI", 256, NULL, 1, NULL);
vTaskStartScheduler();
while (1);
}
四、关键技术与优化
1. 温度控制算法优化
- 滞环控制:避免温度在阈值附近波动导致风扇频繁启停(如28℃启动,27℃停止)。
- 分段PID:低温段用小Kp(避免震荡),高温段用大Kp(快速降温)。
- 前馈补偿:根据环境温度变化趋势提前调整输出,减少滞后。
2. 风扇驱动优化
- 软启动/缓停:转速变化率限制在2%/100ms,避免电机电流冲击。
- PWM频率优化:10-20Hz低频PWM可减少电机噪声,高频(20kHz)可降低可闻噪声。
- 堵转检测:通过电流采样检测风扇堵转,自动停机保护。
3. 低功耗设计
- STOP模式:无操作5分钟后进入STOP模式(电流<10μA),温度超阈值时DS18B20中断唤醒。
- 动态刷新:OLED在非活跃时段降低刷新率(每5秒一次),关闭不必要外设时钟。
参考代码 基于STM32自动调节风扇设计 www.youwenfan.com/contentcnt/133610.html
五、系统调试与扩展
1. 调试步骤
| 阶段 | 操作 | 工具 |
|---|---|---|
| 硬件调试 | 测量DS18B20供电(3.3V)、PWM波形、风扇电压 | 万用表、示波器 |
| PID整定 | 阶跃响应测试,调整Kp/Ki/Kd消除超调/震荡 | 串口打印温度/输出曲线 |
| 功能测试 | 验证自动/手动/睡眠模式切换,超温报警 | 热源(吹风机)、实际测试 |
| 功耗测试 | 测量运行/待机/STOP模式电流 | 万用表(串联在电源回路) |
2. 扩展功能
- 红外遥控:添加HS0038B,实现遥控调节温度/模式。
- Wi-Fi控制:集成ESP8266,通过手机APP远程监控和控制。
- 温湿度联动:增加SHT30湿度传感器,高湿时联动除湿机。
- 定时开关:添加RTC时钟,实现定时自动开关风扇。