ESP32 PWM Tutorial: Controlling the Brightness of LED

Published  June 16, 2020   1
ESP32 Development Board Tutorial

Pulse Width Modulation (PWM) is a technique that varies the width of a pulse while keeping the wave frequency constant. The PWM technique mainly used to control the brightness of the LED, speed of DC motor, controlling a servo motor, or in other cases, where have to generate an analog signal using a digital source. We explained the PWM in detail in the previous article.

In this tutorial, we are going to talk about PWM (pulse width modulation) pins of the ESP32 development board. All GPIO pins of ESP32 development board (Except Power, GND, Tx, Rx, and EN) can be used to get the PWM signal. As an ESP32 PWM example, we’ll build a simple circuit that changes the LED brightness according to PWM signals.

Components Required

  • ESP32
  • LED
  • 330 Ω Resistor
  • 10k Pot
  • Breadboard

PWM Generation

Before explaining the PWM generation on ESP32, let’s discuss some terms associated with PWM.

TON (On Time): The duration of time when the signal is high.

TOFF (Off Time): The duration of time when the signal is low.

Period: It is the sum of on time and off time of the PWM signal.

TotalPeriod = TON + TOFF

Duty Cycle: The percentage of time when the signal was high during the period of the PWM signal.

Duty Cycle = TON /TTotal * 100

For example, if a pulse with a total period of 10ms remains ON (high) for 5ms. Then, the duty cycle will be:

Duty Cycle = 5/10 * 100 = 50% Duty Cycle

Frequency of a PWM: The frequency of a PWM signal determines how fast a PWM completes one period. One Period is complete ON and OFF of a PWM signal as shown in the above figure.

We also created PWM tutorials with many other popular Microcontrollers like Arduino, Raspberry Pi, MSP430 etc:

Check all the PWM related projects here.

PWM Generation on ESP32

In Arduino and NodeMCU, we use the analogWrite() function to "write" value between 0 and 254 to the LED pin. But the ESP32 development board does not support the analogWrite() function. So instead of analogWrite(), we will use another function i.e. the ledcWrite() function. The ledcWrite() is very similar to analogWrite(). It also requires two parameters: The PWM channel that we want to "write" a PWM value to and the PWM value which we want to write to the selected channel. ESP32 has 16 PWM channels, and you can use any GPIO to generate PWM output. The ESP32 provides three functions to assign a PWM channel to a pin and to configure the resolution, frequency, and duty cycle of PWM signals. These functions are:

ledcAttachPin(gpio, channel)
ledcSetup(channel, frequency, resolution)
ledcWrite(channel, dutycycle)

Circuit Diagram

The circuit diagram for ESP32 PWM is given below.

ESP32 PWM Circuit Diagram

The circuit contains a single LED, a resistor, and a 10K potentiometer. The negative pin of LED is connected to the GND of ESP32 through a 330 Ω resistor. You can use any resistor value between 230 Ω and 500 Ω. Connect the LED positive pin to GPIO 16 and signal pin of Pot to ADC1 (VP) pin of ESP32.

Code Explanation for ESP32 PWM

The complete code is given at the end of the page.

This code doesn’t require any library, so start your code by defining the pin, the LED is attached to. In my case, I used GPIO 16 to connect the LED.

const int ledPin = 16;  // 16 corresponds to GPIO16

After that, set the PWM signal properties in the next lines. I set the PWM frequency to 9000, and the resolution to 10, you can change it to generate different PWM signals. ESP32 boards support PWM resolution from 1 bit to 16 bits. You also need to choose a PWM channel. ESP32 has a total of 16 (0 to 15) PWM channels. 

const int freq = 9000;
const int ledChannel = 0;
const int resolution = 10;

Now inside the void setup() function, configure the LED PWM with the properties you set earlier by using the ledcSetup() function. In the next line, define the GPIO pin where the LED is connected. The ledcAttachPin() function is used to define the GPIO pin and the channel that is generating the signal. In my case, I used the ledPin that is GPIO 16 and ledChannel that corresponds to channel 0.

void setup(){
  Serial.begin(9600);
  ledcSetup(ledChannel, freq, resolution);
  ledcAttachPin(ledPin, ledChannel);
}

In the void loop, read the Analog pin where the Pot is connected and store the reading in a variable called ‘dutyCycle’. The LED brightness will increase or decrease according to the rotation of potentiometer. The ledcWrite() is very similar to analogWrite().

void loop(){
   dutyCycle =  analogRead(A0);
   ledcWrite(ledChannel, dutyCycle);
   delay(15);
  }

Testing the ESP32 PWM Signals

To test the ESP32 PWM signals, connect the LED and potentiometer as per the circuit diagram, and upload the code to your ESP32. Make sure you have the right board and COM port selected. Now rotate the potentiometer to increase or decrease the LED brightness.

ESP32 Development Board

Complete working is shown in the video given below. Also, check other ESP32 based projects by following the link.

Code
const int ledPin = 16;  // 16 corresponds to GPIO16
uint16_t dutyCycle;
// setting PWM properties
const int freq = 15000;
const int ledChannel = 0;
const int resolution = 13;
void setup(){
  Serial.begin(9600);
  // configure LED PWM functionalitites
  ledcSetup(ledChannel, freq, resolution);
  // attach the channel to the GPIO to be controlled
  ledcAttachPin(ledPin, ledChannel);
}
void loop(){
   dutyCycle =  analogRead(A0); 
   Serial.print(dutyCycle);
   // changing the LED brightness with PWM
   ledcWrite(ledChannel, dutyCycle);
   delay(15);
  }
Video

Have any question realated to this Article?

Ask Our Community Members

Comments

This doesn't work on a Heltec ESP32 WiFi Kit.  Use the onboard PWMExample sketch instead.

ESP32PWM::allocateTimer(0);

pwm.attachPin(APin, freq,10);  //1KHz 8 bit

void loop() {

pwm.writeScaled(brightness);

delay(2);