基于STM32的智能风扇系统设计与实现
在现代智能家居场景中,一个看似简单的设备——风扇,正悄然经历着从“被动送风”到“主动感知、自适应调节”的智能化跃迁。用户不再满足于手动开关和固定档位,而是期待一种更安静、更节能、能随环境变化自动响应的使用体验。这种需求背后,离不开嵌入式系统的深度赋能。
以 STM32F103C8T6 为代表的 ARM Cortex-M 微控制器,凭借其高性价比、丰富的外设资源以及成熟的开发生态,在这类小型智能家电中扮演了核心角色。它不仅能够实时采集温度数据,还能通过精密控制算法驱动电机,并为未来扩展 Wi-Fi 或蓝牙通信预留空间。本文将围绕一款基于 STM32 的智能风扇原型展开,深入探讨其关键技术实现路径,揭示如何用有限的硬件资源构建一个稳定可靠的闭环控制系统。
整个系统的设计思路可以归结为三个关键词: 感知—决策—执行 。首先通过数字温度传感器获取环境信息;然后由 MCU 根据预设逻辑或用户指令进行判断;最后通过 PWM 信号精准调控风扇转速。这一过程看似简单,但在实际工程中涉及诸多细节考量,比如时序精度、电源噪声抑制、人机交互响应等。
我们选择 DS18B20 作为主要温度传感元件,原因在于它的单总线架构极大简化了引脚占用。在一个引脚资源紧张的小型 MCU 上(如 STM32F103C8T6 只有 37 个可用 GPIO),每节省一根线都意味着更高的布板灵活性和更低的成本。更重要的是,DS18B20 是纯数字输出器件,无需额外 ADC 转换,避免了模拟信号受干扰的问题。
但单总线协议也带来了挑战:严格的微秒级时序要求。例如主机发出复位脉冲必须持续至少 480μs,随后等待从机回应的存在脉冲不能超过 80μs。这些操作无法依赖标准 HAL 库中的
HAL_Delay()
函数(最小单位为毫秒),必须借助自定义的纳秒/微秒级延时函数,通常通过直接操作 SysTick 或编写空循环实现。
// 自定义us级延时(基于SysTick)
void delay_us(uint16_t us) {
__IO uint32_t temp = SysTick->CTRL;
SysTick->LOAD = us * 72; // 假设系统时钟72MHz
SysTick->VAL = 0;
SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;
SysTick->VAL = 0;
}
上述代码虽然简洁,但在实际调试过程中容易因编译器优化导致延时不准确。建议关闭对应文件的优化等级,或使用 DWT(Data Watchpoint and Trace)单元进行更高精度的时间控制。此外,GPIO 配置需设置为开漏输出模式并外加上拉电阻(推荐 4.7kΩ),以确保总线电平稳定。
有趣的是,DS18B20 支持寄生供电模式,即仅通过数据线获取能量。这在某些极端省线设计中有用,但代价是转换期间总线必须保持高电平,否则芯片会断电。因此在调用
START CONVERSION
指令后,主控应立即将引脚设为强推挽输出并拉高,直到 750ms 转换完成后再恢复通信状态。
当温度数据被成功读取后,下一步就是决定风扇该如何响应。最直观的方式是设定一个阈值,比如超过 26°C 就开启风扇。但如果采用“一刀切”的策略,很容易出现频繁启停的现象——温度刚降到 25.9°C 关闭,几秒后又回升至 26.1°C 再次启动,这对电机寿命和用户体验都不友好。
解决这个问题的经典方法是引入 回差控制(Hysteresis Control) 。例如,设定“开启温度”为 26°C,“关闭温度”为 24°C。这样系统只有在升温突破 26°C 时才启动风扇,而必须等到降温至 24°C 以下才会停止。中间的 2°C 区间形成了缓冲带,有效抑制了振荡。
进一步地,我们可以让风扇转速随温差动态调整,而不是简单的“全速或停转”。这就需要用到 PWM(脉宽调制)技术 。STM32 的通用定时器(如 TIM2)天然支持 PWM 输出功能。通过配置预分频器(PSC)和自动重载寄存器(ARR),我们可以生成频率固定的方波信号,再通过修改捕获/比较寄存器(CCR)来改变占空比,从而控制平均电压输出。
一个常见误区是认为 PWM 频率越高越好。实际上,对于直流电机而言,若频率低于 20kHz,可能会产生明显的“嗡嗡”声。但频率过高(如 >50kHz)会导致 MOSFET 开关损耗增加,效率下降。经过实测验证, 1kHz 左右的 PWM 频率 既能避免可闻噪音,又能保证良好的调速线性度。
void PWM_Motor_Init(void) {
__HAL_RCC_TIM2_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitTypeDef gpio = {0};
gpio.Pin = GPIO_PIN_1;
gpio.Mode = GPIO_MODE_AF_PP; // 推挽复用
gpio.Alternate = GPIO_AF1_TIM2;
gpio.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &gpio);
htim2.Instance = TIM2;
htim2.Init.Prescaler = 72 - 1; // 72MHz / 72 = 1MHz
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 1000 - 1; // 1MHz / 1000 = 1kHz
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_2);
}
void Set_Fan_Speed(uint8_t percent) {
if (percent > 100) percent = 100;
uint32_t pulse = (percent * 999) / 100;
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_2, pulse);
}
值得注意的是,直接从 0% 跳到 30% 占空比可能导致电机启动困难,尤其在负载较大或低温环境下。为此,加入“软启动”逻辑非常必要:初始阶段以 10% 占空比运行 500ms,再逐步递增至目标值,类似汽车缓踩油门的过程,既保护电机也减少电流冲击。
在整个系统集成过程中,有几个容易被忽视却至关重要的设计点:
首先是 电磁兼容性问题 。电机属于感性负载,每次关断都会产生反向电动势,可能损坏驱动 MOSFET。解决方案是在电机两端并联续流二极管(如 1N4007),并在靠近 MOSFET 的位置添加 100nF 陶瓷电容滤除高频噪声。PCB 布局上,功率走线应尽量短且宽,远离敏感信号线。
其次是功耗管理。虽然 STM32F103 本身具备 Stop 和 Standby 等低功耗模式,但在风扇待机状态下是否值得启用?答案取决于应用场景。如果系统需要保持 Wi-Fi 模块在线监听远程指令,则不宜进入深度睡眠;但如果只是本地温控,完全可以在无温变时让 MCU 进入 Stop 模式,仅靠 RTC 定时唤醒采样,整体待机电流可降至几十微安级别。
再者是 故障安全机制 。想象一下,程序因某种原因跑飞,导致 PWM 输出异常高电平,风扇长时间满速运转,不仅耗电还可能引发过热风险。为此,启用独立看门狗(IWDG)至关重要。只要主循环未能按时喂狗,系统就会自动重启,防止失控状态持续。
最后是可维护性考虑。尽管产品最终可能封闭外壳,但在开发阶段务必保留 SWD 下载接口(SWCLK 和 SWDIO 引出焊盘),以便随时更新固件或抓取调试信息。甚至可以设计一个“升级模式”:长按按键三秒进入 bootloader,通过串口接收新程序。
从硬件连接图来看,整个系统的结构清晰而紧凑:
[电源模块] → [STM32F103]
│
├─ [DS18B20] —— 温度感知
├─ [按键输入] —— 用户交互
├─ [OLED 显示屏] —— 状态反馈
├─ [MOSFET + 风扇] —— 执行机构
└─ [ESP-01S WiFi 模块] —— 远程接入
软件架构采用典型的前后台模式:主循环负责轮询任务(读温度、刷新显示、处理按键),而定时器中断则提供精确的时间基准(每 500ms 触发一次采样)。对于远程控制部分,可通过 UART 接收来自 ESP8266 的 MQTT 消息,解析 JSON 指令后切换工作模式或设定目标温度。
值得一提的是,若追求更平滑的控制效果,可在当前比例控制基础上引入 PID 算法 。例如当温度接近设定值时,适当降低响应速度,避免超调震荡。不过对于风扇这类惯性较小的系统,简单的查表法或分段线性映射往往已足够实用。
这套设计方案的价值不仅局限于风扇本身。类似的架构完全可以迁移至空气净化器、新风系统、工业排风机等需要根据环境参数自动调节风量的设备中。只需更换传感器类型(如 PM2.5、CO₂、湿度),即可快速适配不同应用场景。
展望未来,随着 Home Assistant、Mi Home 等开源智能家居平台的普及,这类基于 STM32 的节点设备有望成为家庭自动化生态中的重要组成部分。通过增加人体红外传感器实现“有人时自动开启”,或结合光照强度判断昼夜模式,都能进一步提升系统的智能化水平。
真正的智能,不在于堆砌功能,而在于理解用户未言明的需求,并以最自然的方式做出回应。而这,正是嵌入式工程师不断追求的技术境界。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
3万+

被折叠的 条评论
为什么被折叠?



