8. PWM

1. BiBoard(ESP32)PWM功能简介

BiBoard使用的ESP32和UNO用的328P有所不同。ESP32的PWM因为使用了矩阵总线的缘故,可以使用在非特定的引脚上。

ESP32的PWM被称作LED控制器(LEDC),LED PWM 控制器主要用于控制 LED,也可产生 PWM 信号用于其他设备的控制。该控制器有 8个定时器,对应8个高速通道和8个低速通道,合计16通道。

相比UNO直接使用“analogWrite()” 输入0-255之间任意的占空比。BiBoard上ESP32的PWM控制要略麻烦一些。需要控制的参数如下:

  1. 人工选择PWM通道(0-15),也提高了引脚的使用灵活性

  2. PWM波形的位数,决定了PWM波形占空比的分辨率,位数越高精度越高。

  3. PWM波形的频率,决定了PWM波形的速度,频率越高速度越快。

PWM波形的频率和位数是相对的,位数越高频率越低。以下例子引用自ESP32编程手册:

比如,PWM 频率为 5 kHz 时,占空比分辨率最大可为 13 位。这意味着占空比可为 0 至 100% 之间的任意值,分辨率为 ~0.012%(2 ** 13 = 8192 LED 亮度的离散电平)。

LED PWM 控制器可用于生成频率较高的信号,足以为数码相机模组等其他设备计时。此时,最大频率可为 40 MHz,占空比分辨率为 1 位。也就是说,占空比固定为 50%,无法调整。

LED PWM 控制器 API 可在设定的频率和占空比分辨率超过 LED PWM 控制器硬件范围时报错。例如,试图将频率设置为 20 MHz、占空比分辨率设置为 3 位时,串行端口监视器上会报错。

2. Arduino配置BiBoard频率

如上文所示,我们需要配置通道、频率和位数,同时选择输出引脚。

第一步:配置PWM控制器

const int freq = 5000; // PWM frequency
const int ledcChannel = 0; // ledc channel, 0-15
const int resolution = 8; // resolution of PWM,8bit(0~255)
ledcSetup(ledcChannel, freq, resolution);

第二步:配置PWM输出引脚

ledcAttachPin(ledPin, ledcChannel);

第三步:输出PWM波形

ledcWrite(ledcChannel, dutyCycle);

例程中我们选择IO2作为输出引脚,连接IO2至一个LED,可以观察到LED呼吸灯的效果。

3. 完整的代码:

/* In this demo, we show how to use PWM in BiBoard(ESP32)
* It's different from the Arduino UNO based on the ATMega328P
*/

// define the PWM pin
const int ledPin = 2;  // 16 corresponds to GPIO16

// setting PWM properties
const int freq = 5000;          // PWM frequency
const int ledcChannel = 0;      // ledc channel, in ESP32 there're 16 ledc(PWM) channels
const int resolution = 8;       // resolution of PWM
 
void setup(){
  // configure ledc functionalitites
  // channels 0-15, resolution 1-16 bits, freq limits depend on resolution
  // ledcSetup(uint8_t channel, uint32_t freq, uint8_t resolution_bits);
  ledcSetup(ledcChannel, freq, resolution);     
  
  // attach the channel to the GPIO to be controlled
  ledcAttachPin(ledPin, ledcChannel);
}
 
void loop(){
  // increase the LED brightness
  for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){   
    // changing the LED brightness with PWM
    ledcWrite(ledcChannel, dutyCycle);
    delay(15);
  }

  // decrease the LED brightness
  for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle--){
    // changing the LED brightness with PWM
    ledcWrite(ledcChannel, dutyCycle);   
    delay(15);
  }
}

Last updated