PWM (Pulse Width Modulation),即脉冲宽度调制,是一种利用数字信号(脉冲)来模拟模拟信号电平输出的强大技术。它通过调整一个方波信号的高电平持续时间(即脉冲宽度)来改变其在一个固定周期内的平均电压,从而实现对输出功率、速度、亮度等模拟量的精确控制。

核心思想:在固定周期内,通过改变高电平持续时间(占空比),来改变输出信号的平均值,实现对模拟量的数字控制。


一、为什么需要 PWM?

在许多应用中,我们需要控制设备的模拟量,例如:

  • LED 亮度:希望 LED 渐亮渐灭,而不是只有亮或灭。
  • 直流电机速度:需要精确控制电机的转速。
  • 加热器功率:需要调节加热器的输出功率。
  • 模拟电压输出:模拟 DA 转换器输出。

传统的模拟控制需要复杂的模拟电路,并且容易受到噪声、温度漂移等因素的影响。而微控制器(如 Arduino、ESP32)通常只能直接输出数字信号(高电平或低电平)。PWM 技术就成为了连接数字世界和模拟世界的重要桥梁,它允许我们用简单的数字输出引脚来有效地控制模拟设备。

二、PWM 的核心概念

PWM 信号是一个周期性的方波,它有两个关键参数:

  1. 周期 (Period) / 频率 (Frequency)

    • 周期:一个完整的 PWM 脉冲(包括高电平和低电平)所需的时间。
    • 频率:周期分之一。例如,如果周期是 20 毫秒,那么频率就是 50 Hz。
    • 重要性:频率的选择取决于应用。对于 LED,频率通常为几百 Hz 到几 KHz,高到人眼无法察觉闪烁;对于电机,频率过低可能导致电机抖动或噪声。
  2. 占空比 (Duty Cycle)

    • 占空比定义为在一个周期内,高电平持续时间 (Ton) 占总周期时间 (Tperiod) 的比例。
    • 占空比 = (高电平时间 / 周期时间) × 100%
    • 例如,如果周期是 20 毫秒,高电平持续时间是 10 毫秒,则占空比为 50%。
    • 重要性:占空比直接决定了 PWM 信号的平均电压平均功率
      • 占空比为 0%:输出始终为低电平(0V)。
      • 占空比为 50%:高电平持续时间等于低电平持续时间,平均电压为电源电压的一半。
      • 占空比为 100%:输出始终为高电平(例如 5V)。

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 硬件定时器的工作原理

  1. 计数器 (Counter):定时器内部有一个计数器,它以一个固定的频率(由系统时钟和预分频器决定)从 0 开始递增。
  2. 周期寄存器 (TOP / ARR):计数器达到一个预设值(通常称为 TOP 或 ARR - Auto-Reload Register)后,会重新从 0 开始计数,完成一个周期。这个值决定了 PWM 信号的周期或频率
  3. 比较匹配寄存器 (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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
const int ledPin = 9; // 使用支持 PWM 的引脚

void setup() {
pinMode(ledPin, OUTPUT);
}

void loop() {
// 渐亮
for (int brightness = 0; brightness <= 255; brightness += 5) {
analogWrite(ledPin, brightness);
delay(30);
}
delay(1000);

// 渐灭
for (int brightness = 255; brightness >= 0; brightness -= 5) {
analogWrite(ledPin, brightness);
delay(30);
}
delay(1000);
}

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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const int ledPin = 13; // 任意 GPIO 引脚
const int ledcChannel = 0; // 使用 LEDC 通道 0
const int frequency = 5000; // PWM 频率 5 KHz
const int resolution = 8; // 8 位分辨率,占空比范围 0-255

void setup() {
Serial.begin(115200);
Serial.println("ESP32 PWM (LEDC) Example");

// 配置 LEDC 通道
ledcSetup(ledcChannel, frequency, resolution);

// 将通道与 GPIO 引脚关联
ledcAttachPin(ledPin, ledcChannel);
}

void loop() {
// 渐亮
for (int dutyCycle = 0; dutyCycle <= pow(2, resolution) - 1; dutyCycle += 5) {
ledcWrite(ledcChannel, dutyCycle);
delay(30);
}
delay(1000);

// 渐灭
for (int dutyCycle = pow(2, resolution) - 1; dutyCycle >= 0; dutyCycle -= 5) {
ledcWrite(ledcChannel, dutyCycle);
delay(30);
}
delay(1000);
}

五、PWM 的应用场景

  • 直流电机速度控制:改变电机两端电压的平均值,从而控制电机转速。
  • LED 亮度调节:通过改变 LED 的平均电流,控制 LED 的发光亮度。
  • 舵机控制:通过调整特定频率下(通常 50Hz)的脉冲宽度,控制舵机的角度或连续旋转速度。
  • D/A 转换 (数字模拟转换):通过低通滤波器平滑 PWM 信号,可以生成近似的模拟电压。
  • 加热控制:通过控制加热设备的通电时间比例,调节其平均功率。
  • 音频信号生成:通过快速改变占空比,模拟复杂的音频波形(需要较高的 PWM 频率和分辨率)。
  • 电源转换器 (如 Buck/Boost):用于高效地转换电压。

六、PWM 的优缺点

6.1 优点

  1. 高效率:当开关器件(如 MOS 管)处于完全导通(低压降)或完全截止(低电流)状态时,功率损耗最小。PWM 通过快速切换状态,避免了模拟电路中晶体管长时间工作在线性区导致的能量损耗。
  2. 数字控制:可以使用微控制器直接生成和控制,编程简单。
  3. 精确控制:可以实现非常精细的调节,例如 8 位分辨率提供 256 级调节,16 位分辨率提供 65536 级调节。
  4. 抗干扰能力强:数字信号相对于模拟信号更不容易受到噪声干扰。
  5. 成本低:无需复杂的模拟电路。

6.2 缺点

  1. 噪声:PWM 信号的开关特性可能会产生电磁干扰 (EMI) 和噪声,尤其是在高功率应用中。
  2. 非线性响应:某些负载(如白炽灯)对平均电压的响应可能不是线性的,可能需要通过查找表或算法进行校正。
  3. 需要滤波:如果需要获得纯净的模拟电压,PWM 信号需要经过低通滤波器进行平滑。
  4. 频率选择:不合适的 PWM 频率可能导致可闻噪声(电机)或可见闪烁(LED)。

七、总结

PWM 是一种简单而强大的技术,它极大地拓展了微控制器在控制模拟世界方面的能力。从简单的 LED 调光到复杂的电机控制和电源管理,PWM 都扮演着核心角色。理解其基本原理、核心参数和在不同平台上的实现方式,是进行嵌入式开发和物联网项目不可或缺的知识。