第6节 PWM 输出

第6节 PWM 输出

脉冲宽度调制 (PWM)

1. 什么是 PWM?​

PWM(Pulse Width Modulation,脉冲宽度调制) 是一种数字信号调制技术,可以用来“模拟”出连续变化的电压。

当需要控制设备输出的“强度”(例如调节 LED 亮度或电机转速),而不仅仅是简单的开/关状态时,PWM (Pulse Width Modulation,脉冲宽度调制) 技术是一种有效的解决方案。

PWM 信号本质上仍然是数字信号,只有 HIGH 和 LOW 两种状态,但通过控制高电平持续的时间比例,可以实现类似模拟输出的效果。

PWM 的核心概念包括:

占空比 (Duty Cycle): 在一个 PWM 周期内,高电平(信号为 HIGH)持续的时间占整个周期的百分比。占空比直接影响输出的平均功率或强度。

不同占空比产生不同的平均电压效果:

占空比 0%:平均电压 ≈ 0V

占空比 25%:平均电压 ≈ 0.825V (3.3V * 0.25)

占空比 50%:平均电压 ≈ 1.65V (3.3V * 0.50)

占空比 75%:平均电压 ≈ 2.475V (3.3V * 0.75)

占空比 100%:平均电压 ≈ 3.3V

频率 (Frequency): PWM 信号每秒钟重复一个完整周期的次数,单位是赫兹 (Hz)。选择合适的频率对于应用至关重要:对于 LED 调光,频率需足够高以避免人眼察觉闪烁;对于电机控制,频率会影响效率和噪音。

2. ESP32 上的 PWM 实现​

ESP32 集成了专门的硬件模块用于生成 PWM 信号:

LEDC (LED Control) 外设: ESP32 的主要 PWM 生成器。虽然名为 LED 控制,但可产生通用的 PWM 信号。根据具体芯片型号,拥有 6 到 16 个独立通道,频率范围 1Hz-40MHz。

MCPWM (Motor Control PWM) 外设: 专门用于电机控制,包含死区控制等高级功能。其接口未被包含在标准的 Arduino ESP32 核心库中。

在 Arduino ESP32 编程环境中,主要通过以下两种方式来利用 LEDC 外设产生 PWM 信号:

analogWrite(pin, value) 函数: 这是 Arduino 平台的标准 PWM 函数,ESP32 对其提供了良好支持,使用便捷。

LEDC API 函数: 一系列如 ledcAttach(), ledcWrite(), ledcAttachChannel() 的函数,允许对 PWM 参数进行更细致和灵活的配置。

本节将通过控制外部 LED 的亮度来演示这两种 PWM 实现方法。

3. 搭建电路​

需要使用的器件有:

LED * 1

330Ω 电阻 * 1

面包板 * 1

导线

ESP32 开发板

按照下面接线图连接电路:

ESP32-S3-Zero 引脚图

4. 使用 analogWrite() 的 ESP32 PWM 示例代码​

const int ledPin = 7; // LED 连接的引脚号void setup() {}void loop() { // 亮度增加 (占空比值从 0 到 255) for (int dutyCycle = 0; dutyCycle <= 255; dutyCycle++) { analogWrite(ledPin, dutyCycle); // 设置 PWM 占空比值 delay(10); // 延时以控制变化速度 } // 亮度减少 (占空比值从 255 到 0) for (int dutyCycle = 255; dutyCycle >= 0; dutyCycle--) { analogWrite(ledPin, dutyCycle); // 设置 PWM 占空比值 delay(10); // 延时以控制变化速度 }}

代码解析

对于 analogWrite(),ESP32 的实现会自动处理引脚的 PWM 初始化,因此通常不需要显式调用 pinMode()。

loop() 函数:

第一个 for 循环:

for (int dutyCycle = 0; dutyCycle <= 255; dutyCycle++):

变量 dutyCycle 从 0 递增至 255。

第二个 for 循环:

for (int dutyCycle = 255; dutyCycle >= 0; dutyCycle--)

变量 dutyCycle 从 255 递减至 0,使 LED 亮度逐渐减弱。

analogWrite(ledPin, dutyCycle);:

将当前 dutyCycle 值(0-255)设为 ledPin 的 PWM 占空比,使 LED 亮度逐渐增加。

提示在使用 analogWrite() 时,ESP32 会自动管理 LEDC 通道的分配,并设置默认的频率 和 8 位分辨率。

delay(10);:

短暂延时,用于控制亮度变化速率。

5. 使用 LEDC API 的 ESP32 PWM 示例代码​

const int ledPin = 7; // LED 连接的 GPIO 引脚const int frequency = 5000; // PWM 频率 5kHzconst int resolution = 8; // PWM 分辨率 8 位(0-255)const int ledChannel = 0; // PWM 通道号void setup() { // 初始化 LED PWM 功能 ledcAttach(ledPin, frequency, resolution); // 如果你想指定通道 // ledcAttachChannel(ledPin, frequency,resolution,ledChannel)}void loop() { // 逐渐增加占空比,LED 变亮 for (int dutyCycle = 0; dutyCycle <= 255; dutyCycle++) { ledcWrite(ledPin, dutyCycle); // 设置 PWM 占空比值 delay(10); // 延时 10ms,控制变化速度 } // 逐渐减少占空比,LED 变暗 for (int dutyCycle = 255; dutyCycle >= 0; dutyCycle--) { ledcWrite(ledPin, dutyCycle); // 设置 PWM 占空比值 delay(10); // 延时 10ms,控制变化速度 }}

代码解析

ledcAttach(ledPin, frequency, resolution);

ledPin:指定要用作 PWM 输出的 GPIO 引脚

frequency:PWM 信号的频率,单位为赫兹 (Hz)

resolution:分辨率位数,决定占空比的精度

ledcWrite(ledPin, dutyCycle);:

设置 LEDC 引脚 ledPin 的占空比为 dutyCycle。

数值范围取决于分辨率设置:8 位为 0-255(2⁸-1)

6. 拓展​

请尝试实现:通过调节电位器旋钮来控制 LED 灯的亮度,使旋钮位置与灯光亮度相对应接线图:

代码:

const int ledPin = 7; // LED 连接的引脚const int potentiometerPin = 8; // 电位器连接的引脚int potentiometerValue; // 存储电位器读取值int brightness; // 存储映射后的亮度值void setup() {}void loop() { // 1. 读取电位器的模拟值 (范围 0-4095) potentiometerValue = analogRead(potentiometerPin); // 2. 将 ADC 读数映射到 PWM 的范围 (0-255) brightness = map(potentiometerValue, 0, 4095, 0, 255); // 3. 用映射后的值设置 LED 亮度 analogWrite(ledPin, brightness); delay(20);}代码解析:

map(potValue, 0, 4095, 0, 255);:

将电位器的 0-4095 范围线性映射到 PWM 的 0-255 范围,实现电位器旋转角度与 LED 亮度的对应关系。

语法为:

map(value, fromLow, fromHigh, toLow, toHigh)

value:要转换的输入值(这里是电位器读数)

fromLow, fromHigh:输入范围(0 到 4095)

toLow, toHigh:输出范围(0 到 255)

工作原理:

map() 函数按比例转换数值。例如:

电位器值 0(0%位置)→ LED 亮度 0(0% 亮度)

电位器值 2047(50%位置)→ LED 亮度 127(50% 亮度)

电位器值 4095(100%位置)→ LED 亮度 255(100% 亮度)

简单来说,电位器转到哪个位置,LED 就对应那个亮度。

7. 相关链接​

analogWrite() | Arduino-ESP32 documentation

LED Control (LEDC) | Arduino-ESP32 documentation

map() | Arduino Documentation

相关推荐

抖音怎么批量取消喜欢?一招帮你快速清空
365bet官方贴吧

抖音怎么批量取消喜欢?一招帮你快速清空

📅 09-20 👁️ 4770
华为(HUAWEI) Nova 11 Pro GOA
beat365官网下载

华为(HUAWEI) Nova 11 Pro GOA

📅 08-22 👁️ 4060
图文详解:新手试玩版和友人体验版的区别
365bet体育在线网投

图文详解:新手试玩版和友人体验版的区别

📅 07-16 👁️ 3681