引言

脉宽调制(Pulse Width Modulation,简称PWM)是一种广泛应用于电子工程、电力电子、自动化控制等领域的关键技术。它通过改变信号的占空比(Duty Cycle)来控制输出功率或信号强度,从而实现对电机速度、LED亮度、电源转换效率等的精确控制。PWM技术以其简单、高效、可靠的特点,成为现代电子系统中不可或缺的一部分。本文将从PWM的基本原理入手,逐步深入到数学分析、硬件实现、软件编程以及实际应用案例,提供一个全面而实用的指南。无论你是电子爱好者、工程师还是学生,这篇文章都将帮助你深入理解PWM,并能够在项目中灵活应用。

1. PWM的基本原理

1.1 什么是PWM?

PWM是一种模拟信号调制技术,它通过周期性地开关数字信号来模拟连续的模拟信号。核心思想是固定信号的频率,通过调整每个周期内高电平(On)和低电平(Off)的时间比例(即占空比)来控制平均输出电压或功率。

  • 关键参数:
    • 周期(Period, T):一个完整PWM波形的时间长度,T = t_on + t_off。
    • 频率(Frequency, f):周期的倒数,f = 1/T,单位Hz。
    • 占空比(Duty Cycle, D):高电平时间占周期的比例,D = (t_on / T) × 100%。
    • 脉宽(Pulse Width):高电平的持续时间,t_on = D × T。

例如,一个频率为1kHz、占空比为50%的PWM信号,周期为1ms,高电平时间为0.5ms,低电平时间为0.5ms。这种信号在驱动电机时,平均电压为电源电压的50%,从而使电机以一半速度运行。

1.2 PWM的工作原理

PWM的工作原理基于开关模式电源(Switch-Mode Power Supply, SMPS)的概念。通过快速开关(如MOSFET晶体管),将直流电源转换为脉冲序列。负载(如电机或LED)由于其惯性(电感或机械惯性),无法响应高频开关,而是响应平均值。

  • 数学表达:对于一个理想的PWM信号,输出平均电压 V_avg = V_supply × D。
  • 为什么有效:高频开关减少了功率损耗(因为开关器件在饱和区或截止区工作,导通电阻小,开关时间短),同时实现了精确控制。

1.3 PWM的类型

  • 单极性PWM:输出只在正半周期或负半周期变化,常用于H桥驱动。
  • 双极性PWM:输出在正负之间切换,适用于交流电机控制。
  • 空间矢量PWM(SVPWM):用于三相电机,提供更高的直流母线利用率和更低的谐波失真。

2. PWM的数学分析

2.1 占空比与平均输出

假设电源电压为V_cc,PWM频率足够高,负载为电阻R,则平均功率 P_avg = (V_cc^2 / R) × D。对于感性负载(如电机),平均电流 I_avg = (V_cc / R) × D,其中R为等效电阻。

示例计算:

  • V_cc = 12V, D = 25%, R = 10Ω。
  • V_avg = 12 × 0.25 = 3V。
  • I_avg = 3V / 10Ω = 0.3A。

2.2 频率选择的影响

频率过低会导致可见闪烁或电机振动;过高会增加开关损耗(如MOSFET的开关损失)。典型选择:

  • LED控制:100Hz - 1kHz(避免闪烁)。
  • 电机控制:1kHz - 20kHz(高于人耳可闻范围)。
  • 电源转换:100kHz - 1MHz(提高效率)。

2.3 谐波分析

PWM波形包含基波和高次谐波。傅里叶分析显示,谐波主要集中在频率的整数倍处。通过滤波(LC滤波器)可以平滑输出,得到近似直流或正弦波。

3. PWM的硬件实现

3.1 基本电路组件

PWM生成通常需要:

  • 微控制器(MCU):如Arduino、STM32,用于软件生成PWM。
  • 比较器或555定时器:用于硬件生成模拟PWM。
  • 功率开关:MOSFET、IGBT或继电器,用于驱动负载。
  • 驱动电路:如光耦或栅极驱动器,用于隔离和放大信号。

3.2 硬件PWM生成示例:555定时器电路

555定时器可以配置为非稳态多谐振荡器,生成PWM。电路图(描述):

  • 连接引脚7(放电)和引脚6(阈值)、2(触发)通过电阻R1、R2和电容C。
  • 引脚3(输出)产生方波。
  • 通过二极管和电位器调整占空比。

电路描述:

Vcc --- R1 ---+--- R2 ---+--- C --- GND
             |          |
            D1 (可选)   |
             |          |
            Pin7       Pin6/2
输出 Pin3

计算:

  • 频率 f ≈ 1.44 / ((R1 + 2R2) × C)
  • 占空比 D ≈ (R1 + R2) / (R1 + 2R2)(无二极管时接近50%)。

示例值:R1=1kΩ, R2=10kΩ, C=0.1μF → f ≈ 1.44 / (1k + 20k) × 0.1μF ≈ 685Hz。调整R2可变电阻改变D。

3.3 微控制器硬件PWM

现代MCU内置PWM模块(如Arduino的analogWrite())。硬件PWM使用定时器/计数器,精确且不占用CPU时间。

Arduino Uno示例(ATmega328P):

  • 引脚3、5、6、9、10、11支持PWM。
  • 频率默认约490Hz(引脚5、6为980Hz)。

代码示例(Arduino IDE):

// Arduino PWM控制LED亮度
const int pwmPin = 9;  // 支持PWM的引脚
const int frequency = 1000;  // 目标频率(Hz),需调整定时器
const int resolution = 8;  // 8位分辨率(0-255)

void setup() {
  pinMode(pwmPin, OUTPUT);
  // Arduino默认频率,无需额外设置
}

void loop() {
  // 从0到255循环,改变占空比
  for (int duty = 0; duty <= 255; duty++) {
    analogWrite(pwmPin, duty);  // 占空比 = duty/255
    delay(10);  // 延时观察变化
  }
  for (int duty = 255; duty >= 0; duty--) {
    analogWrite(pwmPin, duty);
    delay(10);
  }
}

解释:analogWrite()设置占空比。连接LED(通过限流电阻)到引脚9,观察亮度变化。实际频率可通过修改定时器寄存器调整(如TCCR1B)。

3.4 STM32硬件PWM(高级示例)

STM32使用TIM定时器生成PWM。使用STM32CubeMX配置。

代码示例(STM32 HAL库,使用TIM2通道1):

// main.c 中初始化
#include "stm32f4xx_hal.h"

TIM_HandleTypeDef htim2;
TIM_OC_InitTypeDef sConfigOC;

void MX_TIM2_Init(void) {
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 84 - 1;  // 84MHz系统时钟,预分频到1MHz
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 1000 - 1;  // 1kHz频率 (1MHz / 1000)
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  HAL_TIM_PWM_Init(&htim2);

  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 500;  // 初始占空比 50% (500/1000)
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1);

  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);  // 启动PWM
}

// 在主循环中改变占空比
void loop() {
  for (int i = 0; i < 1000; i += 10) {
    __HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, i);  // 设置脉宽
    HAL_Delay(5);
  }
}

解释:预分频器将系统时钟降到1MHz,周期设为1000,实现1kHz PWM。Pulse控制高电平时间。连接示波器可观察波形。

4. PWM的软件实现

4.1 软件PWM vs 硬件PWM

  • 硬件PWM:精确、无CPU负载,但引脚有限。
  • 软件PWM:使用定时器中断或循环生成,灵活但占用CPU,适合低频或临时应用。

4.2 软件PWM示例:Arduino(无内置PWM引脚)

代码:

// 软件PWM on pin 2 (任意引脚)
const int pwmPin = 2;
const int pwmPeriod = 10000;  // 10ms周期 (100Hz)
const int maxDuty = 100;      // 1%分辨率

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

void loop() {
  for (int duty = 0; duty <= maxDuty; duty++) {
    unsigned long startTime = millis();
    while (millis() - startTime < pwmPeriod) {
      if (millis() - startTime < (duty * pwmPeriod / maxDuty)) {
        digitalWrite(pwmPin, HIGH);
      } else {
        digitalWrite(pwmPin, LOW);
      }
    }
  }
}

解释:使用millis()计时,模拟PWM周期。缺点:精度低,适合学习。

4.3 Raspberry Pi Python PWM

使用RPi.GPIO库。

代码:

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
pwm_pin = 18
GPIO.setup(pwm_pin, GPIO.OUT)

pwm = GPIO.PWM(pwm_pin, 1000)  # 1kHz频率
pwm.start(0)  # 初始占空比0%

try:
    for duty in range(0, 101, 10):
        pwm.ChangeDutyCycle(duty)
        time.sleep(0.5)
    pwm.stop()
finally:
    GPIO.cleanup()

解释:控制GPIO 18引脚输出PWM,适合树莓派项目如电机控制。

5. PWM的应用

5.1 电机控制

PWM是直流电机调速的核心。H桥电路允许正反转。

H桥电路描述:

  • 四个开关(Q1-Q4):Q1/Q4导通正转,Q2/Q3导通反转。
  • PWM输入到开关栅极。

Arduino + L298N驱动模块示例:

// 控制直流电机
const int enA = 9;  // PWM使能
const int in1 = 8;
const int in2 = 7;

void setup() {
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
}

void loop() {
  // 正转,50%速度
  digitalWrite(in1, HIGH);
  digitalWrite(in2, LOW);
  analogWrite(enA, 128);  // 50%占空比
  delay(2000);
  
  // 反转,全速
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  analogWrite(enA, 255);
  delay(2000);
}

解释:L298N模块处理H桥,PWM控制速度。适用于机器人、电动车。

5.2 LED亮度控制

PWM允许无级调光,避免模拟电位器损耗。

扩展:多通道PWM用于RGB LED,实现颜色混合。例如,Arduino Uno的3个引脚控制RGB,占空比分别为R=255, G=0, B=0 → 红色。

5.3 电源转换:DC-DC降压(Buck)转换器

PWM控制开关,实现高效电压转换。

原理:输入直流 → PWM开关 → LC滤波 → 输出直流。

  • 效率 > 90%,远高于线性稳压器。

示例电路(描述):使用MOSFET、电感、电容、二极管。PWM频率100kHz,占空比决定输出电压(V_out = V_in × D)。

计算:V_in=12V, D=0.5 → V_out=6V。电感值 L = (V_in - V_out) × D / (f × ΔI),其中ΔI为纹波电流。

5.4 其他应用

  • 音频放大:Class D放大器使用PWM生成音频信号。
  • 加热控制:烤箱或3D打印机热床,通过PWM调节功率。
  • 伺服电机:PWM脉宽决定角度(1-2ms脉宽对应0-180°)。

伺服控制代码(Arduino):

#include <Servo.h>
Servo myservo;
void setup() { myservo.attach(9); }
void loop() {
  for (int pos = 0; pos <= 180; pos++) {
    myservo.write(pos);
    delay(15);
  }
}

解释:Servo库内部使用PWM,脉宽控制位置。

6. PWM的优化与故障排除

6.1 优化技巧

  • 死区时间:在H桥中添加死区,避免上下桥臂直通短路。
  • 滤波:添加LC滤波器平滑输出,减少谐波。
  • 同步整流:在DC-DC中使用同步MOSFET提高效率。

6.2 常见问题与解决

  • 噪声/振动:频率太低 → 提高到20kHz以上。
  • 过热:开关损耗高 → 优化栅极驱动,使用低Rds(on) MOSFET。
  • 不精确:软件抖动 → 使用硬件定时器。
  • 测试工具:示波器观察波形,万用表测平均电压。

故障排除步骤:

  1. 检查电源和接地。
  2. 测量占空比(用示波器)。
  3. 隔离负载测试。
  4. 参考数据手册调整参数。

7. 高级主题:三相PWM与FOC

对于交流电机,使用空间矢量PWM(SVPWM)和磁场定向控制(FOC)。这涉及Clark/Park变换,生成三相PWM信号。

简要代码框架(STM32 FOC库):

// 伪代码,使用STM32 FOC库
FOC_Init();
FOC_SetSpeed(1000);  // RPM
FOC_Run();

解释:SVPWM生成三个相位的PWM,优化转矩和效率。适用于电动汽车、无人机。

8. 结论

PWM技术是现代电子控制的基石,从简单LED调光到复杂电机驱动,都离不开它。通过理解原理、掌握硬件/软件实现,并结合实际应用,你可以构建高效、可靠的系统。建议从Arduino项目入手,逐步探索高级应用。始终注意安全,尤其是高功率场景。如果你有特定项目需求,如代码调试或电路设计,欢迎提供更多细节,我将进一步指导。