玩转ESP32 PWM输出,制作炫酷呼吸灯效果
文章目录
- 什么是PWM
- 软硬件使用
- ESP32实现PWM输出
- 代码讲解
- 结语
什么是PWM
PWM(Pulse Width Modulation)是一种常用的模拟信号产生技术,它通过对一个定时器的计数值进行调整来改变输出信号的占空比,从而控制输出信号的平均电压值,实现对电子元件的精确控制。
ESP32共拥有16个PWM通道,每个通道都可以设置不同的频率和分辨率。在使用PWM功能之前,需要先对相应的GPIO引脚进行初始化,并选择相应的PWM通道进行配置,然后才能通过修改PWM占空比来控制引脚输出的电信号。
软硬件使用
软件:arduino2.0.4
硬件:ESP32-WROOM-32E
ESP32实现PWM输出
呼吸灯是一种常见的LED特效,它可以让LED的亮度逐渐增加和减少,营造出一种类似于人呼吸的效果。下面是一个使用ESP32 PWM实现呼吸灯效果的示例代码
#include "esp32-hal-timer.h"
#define LED_PIN 18 // 设置LED连接的GPIO引脚
#define LED_CHANNEL 0 // 设置PWM通道号
#define LED_RESOLUTION 8 // 设置PWM分辨率(位数)
#define delay_time 3 // 延时时间
void setup() {
Serial.begin(115200);
ledcSetup(LED_CHANNEL, 5000, LED_RESOLUTION); // 配置PWM通道
ledcAttachPin(LED_PIN, LED_CHANNEL); // 将PWM通道连接到LED引脚
Serial.println("初始化完成");
}
void loop() {
// 呼吸灯效果:逐渐增加和减少占空比
for (int duty = 0; duty < 255; duty++) {
ledcWrite(LED_CHANNEL, duty); // 增加亮度
delay(delay_time);
}
for (int duty = 255; duty > 0; duty--) {
ledcWrite(LED_CHANNEL, duty); // 减少亮度
delay(delay_time);
}
}
示例中使用 ledcSetup 函数配置了一个 PWM 通道(LED_CHANNEL),并将它连接到一个GPIO引脚(LED_PIN)。然后,我们在 loop() 中使用循环来逐渐增加和减少PWM占空比,从而实现呼吸灯的效果。
除了基本的呼吸灯效果外,我们还可以制作更炫酷的呼吸灯效果。下面是一个使用ESP32的定时器和中断功能制作呼吸灯效果的示例代码:
#include "esp32-hal-timer.h"
#define LED_PIN 12 // 设置LED1连接的GPIO18引脚
#define LED_PIN2 13 // 设置LED2连接的GPIO19引脚
#define LED_CHANNEL 0 // 设置LED1 PWM通道号
#define LED_CHANNEL2 1 // 设置LED2 PWM通道号
#define LED_RESOLUTION 8 // 设置PWM分辨率(位数)
#define delay_time 3
#define set_time 3
hw_timer_t *timer = NULL;
void IRAM_ATTR onTimer() {
static uint32_t duty = 255;
static bool isIncreasing = false;
// 更新占空比
if (isIncreasing) {
duty++;
if (duty >= 255) {
isIncreasing = false;
}
} else {
duty--;
if (duty <= 0) {
isIncreasing = true;
}
}
// 更改PWM占空比
ledcWrite(LED_CHANNEL, duty);
}
void setup() {
Serial.begin(115200);
ledcSetup(LED_CHANNEL, 5000, LED_RESOLUTION); // 配置PWM通道0
ledcSetup(LED_CHANNEL2, 5000, LED_RESOLUTION); // 配置PWM通道1
ledcAttachPin(LED_PIN, LED_CHANNEL); // 将PWM通道连接到LED引脚
ledcAttachPin(LED_PIN2, LED_CHANNEL2);
timer = timerBegin(0, 80, true); // 设置计时器0,预分频80,countUp为true
timerAttachInterrupt(timer, onTimer, true); // 将定时器0连接到onTimer函数
timerAlarmWrite(timer, set_time * 1000, true); // 设置定时器报警时间为 set_time ms,重复报警
timerAlarmEnable(timer);
Serial.println("初始化完成");
}
void loop() {
// 呼吸灯效果:逐渐增加和减少占空比
for (int duty = 0; duty < 255; duty++) {
ledcWrite(LED_CHANNEL2, duty); // 增加亮度
delay(delay_time);
}
for (int duty = 255; duty > 0; duty--) {
ledcWrite(LED_CHANNEL2, duty); // 减少亮度
delay(delay_time);
}
}
代码讲解
ledcSetup(channel, frequency, resolution)
该函数用于设置一个 PWM 通道的频率和分辨率。
channel:PWM 通道号,0~15
frequency:PWM 信号的频率,单位为赫兹(Hz)
resolution:PWM 信号的分辨率,即占空比的位数
ledcAttachPin(pin, channel)
该函数用于将指定引脚连接到指定 PWM 通道。
pin:要连接的引脚编号
channel:要连接到该引脚的 PWM 通道号
因此,上述代码的作用如下:
ledcSetup(LED_CHANNEL, 5000, LED_RESOLUTION)
配置 PWM 通道 0 的频率为 5 kHz,分辨率为 8 位;
ledcSetup(LED_CHANNEL2, 5000, LED_RESOLUTION)
配置 PWM 通道 1 的频率为 5 kHz,分辨率为 8 位;
ledcAttachPin(LED_PIN, LED_CHANNEL)
将 PWM 通道 0 连接到 LED 引脚;
ledcAttachPin(LED_PIN2, LED_CHANNEL2)
将 PWM 通道 1 连接到 LED2 引脚。