4、PWM调制技术:PWM原理、占空比与频率的关系、分辨率选择
好,咱们进入第四讲。前面聊了电机选型和驱动电路,现在该聊聊怎么让电机转得「听话」了。说白了,就是PWM调制技术。
PWM这东西,你肯定不陌生。但用在电动牙刷这种小玩意儿上,讲究还挺多。我刚开始做这个项目时,觉得PWM嘛,不就是给个方波嘛,能有多难?结果第一次调出来的牙刷,震得我手都麻了,噪音还大。后来才明白,频率、占空比、分辨率,这三者得配合好才行。
4.1 PWM原理:其实就是个开关
PWM的全称是Pulse Width Modulation,脉冲宽度调制。原理很简单:用数字信号模拟模拟信号。
你想想看,单片机只能输出高电平和低电平,没法直接输出3.5V这种中间值。那怎么办?快速开关!
比如,你要让电机转一半的力气。那就让高电平占一半时间,低电平占一半时间。电机因为有惯性,不会跟着每个脉冲跳,它感受到的是平均电压。
核心公式:
平均电压 = 高电平电压 × 占空比
占空比 = 高电平时间 / 整个周期时间
举个例子:供电是5V,占空比60%。那电机感受到的平均电压就是5V × 60% = 3V。嗯,就这么简单。
我在项目中遇到过一个问题:有些新手工程师觉得PWM频率越高越好,结果选了个几百kHz的。电机倒是安静了,但驱动芯片烫得能煎鸡蛋。为什么?因为开关损耗上去了。所以频率不是越高越好,得平衡。
4.2 占空比与频率的关系:别搞混了
这两个概念,我见过太多人搞混了。咱们捋一捋。
频率:一秒钟开关多少次。单位是Hz。
占空比:每次开关中,高电平占多少比例。单位是百分比。
频率决定了「开关的快慢」,占空比决定了「力气的大小」。两者是独立的,但实际应用中会互相影响。
举个例子:
- 频率20kHz,占空比50%:每秒钟开关20000次,每次高电平占一半时间。
- 频率20kHz,占空比80%:每秒钟还是开关20000次,但高电平占了八成时间。
你看,频率没变,但电机转速变了。反过来,频率变了,占空比不变,电机转速也不变。
我的经验:
电动牙刷的PWM频率,我一般选在20kHz到40kHz之间。为什么?
- 低于20kHz:人耳能听到,会有「滋滋」声,用户体验差。
- 高于40kHz:开关损耗增加,电池续航下降。
20kHz刚好在人类听觉上限附近,大部分用户听不到。当然,年轻人可能还能听到一点点,但已经可以接受了。
4.3 分辨率选择:精度和资源的博弈
分辨率,说白了就是占空比能调多细。
8位分辨率:占空比可以调0/255到255/255,共256级。
10位分辨率:占空比可以调0/1023到1023/1023,共1024级。
16位分辨率:占空比可以调0/65535到65535/65535,共65536级。
分辨率越高,控制越精细。但代价是什么?
- 定时器资源占用更多
- 中断频率可能更高
- 代码复杂度增加
我建议电动牙刷选8位或10位分辨率就够了。为什么?
你想想看,电动牙刷的振动频率控制,其实不需要那么精细。用户能感受到的振动变化,大概在5%的占空比变化以上。8位分辨率有256级,每级变化约0.4%,已经远远超过人眼(或者说人手)能分辨的精度了。
我曾经踩过的坑:
有一次我为了追求「极致控制」,选了16位分辨率。结果定时器溢出中断频繁触发,导致主循环被频繁打断,按键响应都变慢了。后来查了半天才发现是分辨率太高惹的祸。
所以,别盲目追求高分辨率。够用就好。
4.4 实际代码示例:STM32的PWM配置
咱们以STM32为例,看看怎么配置PWM。我用的是HAL库,但原理都一样。
// 定时器句柄
TIM_HandleTypeDef htim2;
// PWM初始化函数
void PWM_Init(void)
{
TIM_OC_InitTypeDef sConfigOC = {0};
// 定时器基础配置
htim2.Instance = TIM2;
htim2.Init.Prescaler = 71; // 72MHz / (71+1) = 1MHz
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 999; // 1MHz / (999+1) = 1kHz
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_PWM_Init(&htim2);
// PWM通道配置
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 500; // 占空比 500/1000 = 50%
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);
// 启动PWM
HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
}
// 动态修改占空比
void PWM_SetDuty(uint16_t duty)
{
__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, duty);
}
这段代码里,Prescaler和Period决定了PWM频率。Prescaler=71,Period=999,算下来频率是1kHz。但前面我说了,电动牙刷要用20kHz以上,所以实际项目中我会把Period改成49,这样频率就是20kHz了。
频率计算公式:
PWM频率 = 定时器时钟 / (Prescaler + 1) / (Period + 1)
占空比 = Pulse / (Period + 1) × 100%
你看,Prescaler和Period配合,就能得到想要的频率。Pulse就是占空比控制值。
4.5 避坑指南:PWM常见问题
做PWM控制,有几个坑我帮你们踩过了,直接说结论:
- 死区时间:如果驱动电路是半桥或全桥,一定要加死区时间。否则上下管直通,瞬间烧管子。我吃过这个亏,一次就烧了三个MOS管。
- PWM引脚复用:很多MCU的PWM引脚和普通IO复用。记得配置成复用功能,不然输出不了波形。
- 负载变化:电机启动时电流大,PWM占空比不要从0直接跳到100%。我习惯做软启动,比如500ms内从0逐渐升到目标值。
- 滤波电容:PWM输出端加个小电容(比如0.1μF),能滤掉高频噪声。但别太大,否则波形会变圆,影响控制精度。
嗯,PWM这块就聊这么多。下一章咱们讲PID控制算法,那才是让牙刷振动「指哪打哪」的关键。到时候见。