第三章 PWM基本原理:占空比、频率、分辨率与电机控制
各位同学,今天我们来聊聊PWM。说实话,PWM这东西在嵌入式领域太常见了,但很多人用了好几年,真问起原理来,还是模模糊糊的。我记得刚入行那会儿,调一个舵机PWM,频率设错了,舵机吱吱叫就是不转,折腾了一下午才发现是频率不对。嗯,今天咱们就把这些基础概念彻底捋清楚。
3.1 什么是PWM?
PWM,全称Pulse Width Modulation,脉冲宽度调制。说白了,就是通过调节脉冲的宽度来控制平均电压。你想想看,单片机输出的数字信号只有0和3.3V(或者5V),但电机需要的是连续可变的电压,怎么办?
答案就是:快速开关。让电压在0和3.3V之间高速切换,通过调节高电平持续的时间比例,来模拟出一个中间电压。这就是PWM的核心思想。
核心公式:平均电压 = 高电平电压 × 占空比
比如3.3V的PWM,占空比50%,平均电压就是1.65V。
3.2 PWM的三个核心参数
搞懂PWM,你只需要记住三个东西:频率、占空比、分辨率。我习惯把它们比作水龙头——频率是开关的快慢,占空比是开多大,分辨率是你能多精细地调节开度。
3.2.1 占空比(Duty Cycle)
占空比就是高电平时间占整个周期的比例。单位是百分比,0%就是一直低电平,100%就是一直高电平。
- 50%占空比:高电平和低电平各占一半时间
- 75%占空比:高电平占3/4,低电平占1/4
- 0%占空比:完全关闭
- 100%占空比:完全打开
我在做四旋翼电调驱动时遇到过一个问题:电机在低占空比(比如5%以下)时根本不转,因为启动扭矩不够。后来我加了一个「软启动」策略,先给一个高占空比脉冲再降下来,问题就解决了。
3.2.2 频率(Frequency)
频率就是一秒钟内PWM波形重复的次数,单位是Hz。频率决定了PWM的「细腻程度」。
| 应用场景 | 典型频率 | 说明 |
|---|---|---|
| LED调光 | 100Hz - 1kHz | 人眼有视觉暂留,太低会闪烁 |
| 舵机控制 | 50Hz | 标准舵机周期20ms |
| 直流电机 | 10kHz - 50kHz | 太高开关损耗大,太低有噪音 |
| 无刷电机(FOC) | 16kHz - 40kHz | 避开人耳可听范围 |
避坑指南:我曾经在PX4上调试一个电调,把PWM频率设成了400Hz,结果电机发出刺耳的尖叫声。后来才发现,400Hz刚好在人耳最敏感的频段附近。建议电机控制至少用16kHz以上,人耳基本听不到。
3.2.3 分辨率(Resolution)
分辨率决定了你能把占空比调节得多精细。比如8位PWM,分辨率就是256级(0-255);16位PWM,分辨率就是65536级。
计算公式很简单:
分辨率 = log2(定时器计数周期)
举个例子:STM32的定时器ARR设为999,那么分辨率就是log2(1000) ≈ 10位。这意味着你可以把占空比分成1000个等级。
我的经验:电机控制一般10位分辨率就够了,但LED调光或者高精度伺服,建议用12位以上。分辨率太高也有代价——定时器频率会受限,因为计数周期变长了。
3.3 PWM在电机控制中的应用
电机控制是PWM最经典的应用场景。我参与过好几个无人机电调项目,这里分享一下实际经验。
3.3.1 直流有刷电机
最简单的应用。通过PWM控制MOS管的开关,调节电机两端的平均电压,从而控制转速。
// 伪代码示例:直流电机PWM控制
void motor_set_speed(uint8_t speed) {
// speed: 0-255
TIM1->CCR1 = speed; // 设置占空比
}
这里要注意:电机是感性负载,PWM开关时会产生反电动势。我刚开始做的时候没加续流二极管,结果MOS管烧了好几个。嗯,教训深刻。
3.3.2 无刷直流电机(BLDC)
BLDC需要六步换向,PWM配合换相时序。在PX4中,我们通常使用定时器的互补PWM输出,带死区插入。
// PX4中BLDC PWM配置示例
// 使用STM32 TIM1的CH1/CH1N互补输出
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 互补通道
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
关键点:死区时间设置很关键。太短会导致上下管直通短路,太长会影响效率。我一般设1-2μs,具体看MOS管的开关速度。
3.3.3 永磁同步电机(PMSM)与FOC
FOC(磁场定向控制)是现在无人机的主流方案。它需要两路高频PWM(SVPWM调制),配合电流采样。
在PX4中,FOC的PWM频率通常设在20kHz-40kHz。为什么是这个范围?
- 低于16kHz:人耳能听到,电机噪音大
- 高于40kHz:开关损耗急剧增加,MOS管发热严重
- 20kHz左右:平衡了噪音和效率
3.4 知识体系总览
下面这张图是我自己画的PWM知识体系,帮你把今天的内容串起来:
3.5 实际项目中的避坑指南
最后,分享几个我踩过的坑:
- 频率和分辨率是矛盾的:定时器时钟固定时,频率越高,分辨率越低。你需要根据应用做取舍。
- PWM输出要加RC滤波吗?:控制电机不需要,但如果你要测量PWM的平均电压,需要加低通滤波。
- 启动时别直接给满占空比:电机启动电流很大,容易烧MOS管。我习惯用软启动,从10%逐渐升到目标值。
- 注意PWM的极性:有些电调是高电平有效,有些是低电平有效。接反了电机不转,别问我怎么知道的。
调试小技巧:用逻辑分析仪看PWM波形,比用示波器方便多了。我一般先看频率对不对,再看占空比变化是否线性,最后看死区时间是否合适。
好了,PWM的基本原理就讲到这里。这些概念虽然基础,但真要在项目中用好,还是需要不少实践积累的。下次我们讲定时器的具体配置,到时候会结合STM32和PX4的代码,手把手教你配出稳定的PWM输出。