Skip to content

Arduino - 脉冲宽度调制

脉冲宽度调制 (PWM) 是一种强大的技术,用于通过数字信号控制模拟设备。PWM 不是输出连续的模拟电压,而是快速地在数字引脚的HIGH和LOW之间切换。信号处于HIGH状态的时间百分比被称为占空比,它会产生一个平均电压,从而实现诸如调暗LED或控制直流电机速度等效果。

HIGH |----------| |----------|
| | | |
LOW +----------+----------+----------+
<-- Ton ---><--Toff--><-- Ton --->
<------- Period ------>
  • 高电平时间 (Ton): 信号处于HIGH状态的持续时间。
  • 低电平时间 (Toff): 信号处于LOW状态的持续时间。
  • 周期: 一个周期的总时间(周期 = Ton + Toff)。周期的倒数即为 PWM 频率。
  • 占空比: 信号处于HIGH状态的周期百分比。 占空比 = (Ton / 周期) * 100%。

0% 占空比意味着信号始终为 LOW(平均电压为0V)。100% 占空比意味着信号始终为 HIGH(平均电压为5V)。50% 占空比意味着信号在周期的一半时间内为 HIGH,产生2.5V的平均电压。

Arduino 提供了 analogWrite(pin, value) 函数,可以轻松生成 PWM 信号。在使用 PWM 引脚时,你无需在其之前调用 pinMode()。

analogWrite(pin, value);
  • pin: 你想要使用的具备 PWM 功能的引脚。在 Arduino UNO 上,这些引脚标有波浪线 ~(引脚 3、5、6、9、10、11)。请务必查阅你开发板的文档以了解其 PWM 引脚。
  • value: 占空比,指定为从 0 (0% 占空比) 到 255 (100% 占空比) 的整数值。

大多数 Arduino 开发板的默认 PWM 频率约为 490 Hz,但有些引脚(例如 UNO 上的 5 和 6 号引脚)运行在 980 Hz。ESP32 等更高级的开发板提供可配置的 PWM 频率。

示例项目:使用电位器渐变LED亮度

Section titled “示例项目:使用电位器渐变LED亮度”

这个经典示例演示了如何从电位器读取模拟值,并使用它通过 PWM 控制LED的亮度。

  • 1 × Arduino UNO
  • 1 × 电位器 (任意阻值,10kΩ 常见)
  • 1 × LED
  • 1 × 220Ω 电阻
// 电位器接线
// 电位器有3个引脚。
// 将两个外部引脚连接到电源和地。
// 中心引脚(“滑动端”)是输出电压。
Potentiometer Pin 1 --- Arduino GND
Potentiometer Pin 2 (Wiper) --- Arduino Analog Pin A0
Potentiometer Pin 3 --- Arduino 5V
// LED 接线
Arduino PWM Pin ~9 --- [220Ω Resistor] --- [LED Anode (+)]
Arduino GND --- [LED Cathode (-)]

analogRead() 函数返回 0-1023 范围的值,而 analogWrite() 需要 0-255 范围的值。我们可以使用方便的 map() 函数将输入范围映射到输出范围。

/**
* @文件 pwm_potentiometer_control.ino
* @简介 使用电位器通过 PWM 控制 LED 亮度。
* @作者 现代化教程
*/
constexpr int LED_PIN = 9; // 必须是 PWM 引脚 (~)
constexpr int POT_PIN = A0; // 电位器输入引脚
void setup() {
// 当使用 analogWrite 时,LED_PIN 不需要 pinMode。
// 模拟输入引脚不需要 pinMode。
Serial.begin(9600);
}
void loop() {
// 1. 从电位器读取值 (0 到 1023)
int potValue = analogRead(POT_PIN);
// 2. 将 10 位模拟输入范围 (0-1023) 映射到
// 8 位 PWM 输出范围 (0-255)。
int pwmValue = map(potValue, 0, 1023, 0, 255);
// 3. 将映射后的值写入 LED 引脚。
analogWrite(LED_PIN, pwmValue);
// 可选:将值打印到串口监视器以进行调试。
Serial.print("电位器:");
Serial.print(potValue);
Serial.print("\t PWM 值:");
Serial.println(pwmValue);
delay(10); // 短暂延迟以保持稳定性
}

PWM 功能非常多样:

  • 直流电机速度控制: 通过使用电机驱动芯片(如 L298N 或 TB6612),您可以使用 PWM 来控制发送给电机的有效电压,从而控制其速度。
  • 舵机控制: Arduino Servo 库使用 PWM 信号来告诉舵机移动到哪个角度。
  • 生成音调: tone() 函数使用 PWM 通过蜂鸣器或扬声器创建不同频率的声音。