PWM (脉冲宽度调制) 详解
PWM (Pulse Width Modulation),即脉冲宽度调制,是一种利用数字信号(脉冲)来模拟模拟信号电平输出的强大技术。它通过调整一个方波信号的高电平持续时间(即脉冲宽度)来改变其在一个固定周期内的平均电压,从而实现对输出功率、速度、亮度等模拟量的精确控制。
核心思想:在固定周期内,通过改变高电平持续时间(占空比),来改变输出信号的平均值,实现对模拟量的数字控制。
一、为什么需要 PWM?
在许多应用中,我们需要控制设备的模拟量,例如:
- LED 亮度:希望 LED 渐亮渐灭,而不是只有亮或灭。
- 直流电机速度:需要精确控制电机的转速。
- 加热器功率:需要调节加热器的输出功率。
- 模拟电压输出:模拟 DA 转换器输出。
传统的模拟控制需要复杂的模拟电路,并且容易受到噪声、温度漂移等因素的影响。而微控制器(如 Arduino、ESP32)通常只能直接输出数字信号(高电平或低电平)。PWM 技术就成为了连接数字世界和模拟世界的重要桥梁,它允许我们用简单的数字输出引脚来有效地控制模拟设备。
二、PWM 的核心概念
PWM 信号是一个周期性的方波,它有两个关键参数:
周期 (Period) / 频率 (Frequency):
- 周期:一个完整的 PWM 脉冲(包括高电平和低电平)所需的时间。
- 频率:周期分之一。例如,如果周期是 20 毫秒,那么频率就是 50 Hz。
- 重要性:频率的选择取决于应用。对于 LED,频率通常为几百 Hz 到几 KHz,高到人眼无法察觉闪烁;对于电机,频率过低可能导致电机抖动或噪声。
占空比 (Duty Cycle):
- 占空比定义为在一个周期内,高电平持续时间 (Ton) 占总周期时间 (Tperiod) 的比例。
占空比 = (高电平时间 / 周期时间) × 100%- 例如,如果周期是 20 毫秒,高电平持续时间是 10 毫秒,则占空比为 50%。
- 重要性:占空比直接决定了 PWM 信号的平均电压或平均功率。
- 占空比为 0%:输出始终为低电平(0V)。
- 占空比为 50%:高电平持续时间等于低电平持续时间,平均电压为电源电压的一半。
- 占空比为 100%:输出始终为高电平(例如 5V)。
graph TD
A[PWM 信号] --> B{"周期 (T)"};
A --> C{"高电平时间 (Ton)"};
B -- 定义 --> D["频率 (f = 1/T)"];
C -- 占一个周期的比例 --> E[占空比 = Ton / T];
subgraph 示例波形
SquareWave1["Ton = 0, Duty Cycle = 0%"]
SquareWave2["Ton = 1/4 T, Duty Cycle = 25%"]
SquareWave3["Ton = 1/2 T, Duty Cycle = 50%"]
SquareWave4["Ton = 3/4 T, Duty Cycle = 75%"]
SquareWave5["Ton = T, Duty Cycle = 100%"]
end
SquareWave1 -- 平均电压 0V --> F[输出低];
SquareWave2 -- 平均电压 1/4 VCC --> G[输出低中等];
SquareWave3 -- 平均电压 1/2 VCC --> H[输出中等];
SquareWave4 -- 平均电压 3/4 VCC --> I[输出高中等];
SquareWave5 -- 平均电压 VCC --> J[输出高];
2.1 平均电压计算
在一个周期内,PWM 信号的平均电压 (V_avg) 可以近似为:V_avg = 占空比 × V_max
其中 V_max 是高电平电压(例如,Arduino 为 5V,ESP32 为 3.3V)。
例如,一个 5V 的 PWM 信号,占空比为 50%,其平均电压就是 2.5V。虽然瞬间电压只有 0V 或 5V,但对于许多设备(如 LED、电机),它们响应的是这种平均电压/功率。
三、PWM 的实现方式
PWM 信号通常由微控制器内部的硬件定时器 (Timer) 模块生成。
3.1 硬件定时器的工作原理
- 计数器 (Counter):定时器内部有一个计数器,它以一个固定的频率(由系统时钟和预分频器决定)从 0 开始递增。
- 周期寄存器 (TOP / ARR):计数器达到一个预设值(通常称为 TOP 或 ARR - Auto-Reload Register)后,会重新从 0 开始计数,完成一个周期。这个值决定了 PWM 信号的周期或频率。
- 比较匹配寄存器 (Compare Match / CCR):定时器内部还有一个比较匹配寄存器。当计数器的值与这个寄存器中的值相等时,PWM 输出引脚的状态会发生翻转(通常是从高电平变为低电平或反之)。这个值决定了 PWM 信号的高电平持续时间或低电平持续时间,从而决定了占空比。
通过修改周期寄存器和比较匹配寄存器的值,就可以灵活地控制 PWM 信号的频率和占空比。
四、PWM 在 Arduino 中的应用
4.1 Arduino Uno (AVR 微控制器)
Arduino Uno (ATmega328P) 提供 6 个 PWM 引脚 (通常是 D3, D5, D6, D9, D10, D11)。这些引脚的 PWM 功能由其内部的 Timer0、Timer1 和 Timer2 模块提供。
analogWrite(pin, value);- 这是 Arduino 提供的一个高层抽象函数。
pin: 支持 PWM 的引脚编号。value: 0 到 255 之间的整数值。value = 0:占空比 0%(输出低电平)。value = 127:约占空比 50%。value = 255:占空比 100%(输出高电平)。
- 默认频率:
analogWrite()函数默认使用 490 Hz (D5, D6) 或 980 Hz (D3, D9, D10, D11) 的 PWM 频率,分辨率为 8 位(0-255)。
示例:LED 亮度调节
1 | const int ledPin = 9; // 使用支持 PWM 的引脚 |
4.2 ESP32 Arduino
ESP32 拥有强大的 LEDC (LED Controller) 模块,提供多达 16 个独立的 PWM 通道,支持 1 到 16 位的分辨率,并且频率可调范围更广。这使得 ESP32 在生成精确、多通道 PWM 信号方面远超 AVR 微控制器。
ESP32 的 PWM 函数 (ledc):
ledcSetup(channel, freq, resolution_bits): 配置 LEDC 通道。channel: LEDC 通道编号 (0-15)。freq: PWM 频率 (Hz)。resolution_bits: 占空比分辨率 (1-16)。例如,8 位分辨率意味着占空比范围是 0 到 (2^8 - 1) = 255。
ledcAttachPin(pin, channel): 将 LEDC 通道与一个 GPIO 引脚关联。ledcWrite(channel, duty_cycle): 设置指定通道的占空比。duty_cycle: 值范围取决于resolution_bits。对于 8 位分辨率,范围是 0-255。
示例:ESP32 LED 亮度调节
1 | const int ledPin = 13; // 任意 GPIO 引脚 |
五、PWM 的应用场景
- 直流电机速度控制:改变电机两端电压的平均值,从而控制电机转速。
- LED 亮度调节:通过改变 LED 的平均电流,控制 LED 的发光亮度。
- 舵机控制:通过调整特定频率下(通常 50Hz)的脉冲宽度,控制舵机的角度或连续旋转速度。
- D/A 转换 (数字模拟转换):通过低通滤波器平滑 PWM 信号,可以生成近似的模拟电压。
- 加热控制:通过控制加热设备的通电时间比例,调节其平均功率。
- 音频信号生成:通过快速改变占空比,模拟复杂的音频波形(需要较高的 PWM 频率和分辨率)。
- 电源转换器 (如 Buck/Boost):用于高效地转换电压。
六、PWM 的优缺点
6.1 优点
- 高效率:当开关器件(如 MOS 管)处于完全导通(低压降)或完全截止(低电流)状态时,功率损耗最小。PWM 通过快速切换状态,避免了模拟电路中晶体管长时间工作在线性区导致的能量损耗。
- 数字控制:可以使用微控制器直接生成和控制,编程简单。
- 精确控制:可以实现非常精细的调节,例如 8 位分辨率提供 256 级调节,16 位分辨率提供 65536 级调节。
- 抗干扰能力强:数字信号相对于模拟信号更不容易受到噪声干扰。
- 成本低:无需复杂的模拟电路。
6.2 缺点
- 噪声:PWM 信号的开关特性可能会产生电磁干扰 (EMI) 和噪声,尤其是在高功率应用中。
- 非线性响应:某些负载(如白炽灯)对平均电压的响应可能不是线性的,可能需要通过查找表或算法进行校正。
- 需要滤波:如果需要获得纯净的模拟电压,PWM 信号需要经过低通滤波器进行平滑。
- 频率选择:不合适的 PWM 频率可能导致可闻噪声(电机)或可见闪烁(LED)。
七、总结
PWM 是一种简单而强大的技术,它极大地拓展了微控制器在控制模拟世界方面的能力。从简单的 LED 调光到复杂的电机控制和电源管理,PWM 都扮演着核心角色。理解其基本原理、核心参数和在不同平台上的实现方式,是进行嵌入式开发和物联网项目不可或缺的知识。
