基于STM32的自动调节风扇设计

基于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 核心电路连接

2.2 抗干扰与安全设计

三、软件设计与核心代码

1. 系统架构(FreeRTOS多任务调度)

采用FreeRTOS实时操作系统,划分4个核心任务(优先级从高到低):

  1. 温度采集任务(优先级4):周期性读取DS18B20温度,滑动平均滤波后发送至队列。
  2. PID控制任务(优先级3):根据目标温度与实际温差,计算PID输出(PWM占空比)。
  3. 风扇驱动任务(优先级2):解析PID输出,更新PWM占空比,实现软启动/缓停。
  4. 人机交互任务(优先级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, &current_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. 温度控制算法优化

2. 风扇驱动优化

3. 低功耗设计

参考代码 基于STM32自动调节风扇设计 www.youwenfan.com/contentcnt/133610.html

五、系统调试与扩展

1. 调试步骤

阶段 操作 工具
硬件调试 测量DS18B20供电(3.3V)、PWM波形、风扇电压 万用表、示波器
PID整定 阶跃响应测试,调整Kp/Ki/Kd消除超调/震荡 串口打印温度/输出曲线
功能测试 验证自动/手动/睡眠模式切换,超温报警 热源(吹风机)、实际测试
功耗测试 测量运行/待机/STOP模式电流 万用表(串联在电源回路)

2. 扩展功能

专注于matlab/simulink,电子电路,编程