ESP32 使用PWM控制板载的LED实现呼吸效果

凌顺实验室(lingshunlab.com)分享如何在 ESP32 SoC 中使用 PWM。
PWM可用控制LED的亮度,舵机的角度,直流电机的速度等等。

ESP32 LED PWM 控制器 (LEDC)

ESP32 的 LEDC 外设由 16 个 PWM 通道组成,能够生成独立的波形,主要用于 RGB LED 控制,但也可用于其他目的。关于 ESP32 中的 LED PWM 控制器,您应该注意几个有趣的点。

  • 16 个独立 PWM 通道,分为两组,每组 8 个通道。
  • 1 位和 16 位之间的可编程分辨率。
  • PWM波的频率取决于PWM的分辨率。
  • 自动增加/减少占空比,无需处理器干预。

但在ESP32中使用PWM,并不像Arduino开发板的那么简单。需要一些配置才能生效。

配置ESP32的PWM通道

在Arduino 编程中的使用“analogWrite()”函数即可生成PWM信号。而 ESP32 的 LED PWM 中的几乎所有内容都是需要用户配置的(通道、分辨率和频率),因此我们将使用一组不同的(且专用的)函数来配置 ESP32 中的 PWM,而不是使用“analogWrite()”函数。

以下是驱动程序公开的所有 LEDC API 的列表。这些函数是为 ESP32 的 Arduino IDE 端口编写的。

  • ledcSetup(通道、频率、分辨率位);
  • ledcAttachPin(引脚,通道);
  • ledcWrite(通道,占空比);
  • ledcRead(通道);
  • ledcWriteTone(通道,频率)
  • ledcWriteNote(通道、音符、八度);
  • ledcReadFreq(通道);
  • ledcDetachPin(引脚);

在 8 个函数中,我们将重点关注前三个,因为它们对于生成 PWM 更有用(也是最低要求)。

在 ESP32 中配置 PWM 通道时需要记住的一些要点:

  • 由于有 16 个 PWM 通道,因此“通道”参数可以采用 0 到 15 之间的任意值。
  • 接下来是 PWM 信号的频率。您可以根据需要设置频率,例如 1 KHz、5 KHz、8 KHz 和 10 KHz。
  • PWM 的分辨率也是可配置的,ESP32 PWM 可以在 1 位到 16 位分辨率之间的任何位置进行编程。
  • PWM 频率和分辨率成反比,并且取决于时钟源。因此,选择频率和分辨率值时要小心。
  • 最后,为 PWM 输出分配 GPIO 引脚。您可以分配任何 GPIO 引脚,但分配时要小心(不要使用已经使用的 GPIO 引脚,如UART、SPI 等)。

下表显示了一些常用的 PWM 频率和分辨率。

LEDC 时钟源 LEDC 脉宽调制频率 脉宽调制分辨率
80 MHz APB_CLK 1KHz 16位
80 MHz APB_CLK 5KHz 14位
80 MHz APB_CLK 10KHz 13位
8 MHz RTC8M_CLK 1KHz 13位
8 MHz RTC8M_CLK 8KHz 10位
1 MHz REF_Tick 1KHz 10位

实现效果

本次实验将使用的ESP32开发板上的LED灯作为受PWM控制的LED灯,从而实现呼吸的效果。

所以请确保你的ESP32开发板上有LED灯,并且可通过GPIO 2控制

BOM表

  • ESP32 x1
    (需要开发板上有LED灯,并且受GPIO 2控制)

程序代码

// welcome to lingshunlab.com

const int LEDPin = 2;  /* GPIO16 */

int dutyCycle;
/* Setting PWM Properties */
const int PWMFreq = 5000; /* 5 KHz */
const int PWMChannel = 0;
const int PWMResolution = 10;
const int MAX_DUTY_CYCLE = (int)(pow(2, PWMResolution) - 1);

void setup()
{  
  // 配置PWM通道,频率,分辨率
  ledcSetup(PWMChannel, PWMFreq, PWMResolution);
  // 把配置好的PWM通道,分配引脚
  ledcAttachPin(LEDPin, PWMChannel);
}

void loop()
{
  // 用PWM增加LED亮度
  for(dutyCycle = 0; dutyCycle <= MAX_DUTY_CYCLE; dutyCycle++)
  {
    ledcWrite(PWMChannel, dutyCycle);
    delay(3);
  }
  // 用PWM降低LED亮度
  for(dutyCycle = MAX_DUTY_CYCLE; dutyCycle >= 0; dutyCycle--)
  {
    ledcWrite(PWMChannel, dutyCycle);
    delay(3);
  }
}

在ESP32 中 PWM 的重要特性之一是所有 16 个通道都可以独立配置,即每个通道可以有自己的分辨率和频率。