In this tutorial, we’ll show you how to use the Arduino IDE to generate PWM signals with the ESP32. We’ll use the ESP32’s LED PWM controller to build a simple circuit that dims an LED as an example. We’ll also demonstrate how to use the same PWM signal on multiple GPIOs at the same time.
You should have the ESP32 add-on installed in your Arduino IDE before starting this tutorial. If you haven’t already, install the ESP32 on the Arduino IDE using one of the tutorials below.
Parts Required
To follow this tutorial, you need these parts:
- ESP32 DOIT DEVKIT V1 Board — read best ESP32 development boards
- 3x 5 mm LED
- 3x 330 Ohm resistor
- Breadboard
- Jumper wires
You can use the preceding links to find all the parts for your projects at the best price!
ESP32 LED PWM Controller
The ESP32 has a 16-channel LED PWM controller that can be configured to generate PWM signals with various properties.
The following are the steps to dim an LED with PWM using the Arduino IDE:
1. Firstly, you need to select a PWM channel. There are 16 channels in total, ranging from 0 to 15.
2. The PWM signal frequency must then be set. A frequency of 5000 Hz is suitable for an LED.
3. You must also set the duty cycle resolution for the signal, which ranges from 1 to 16 bits. We’ll use an 8-bit resolution, which means you can adjust the brightness of the LEDs with a value ranging from 0 to 255.
4. Following that, you must specify which GPIO or GPIOs the signal will appear on. You’ll use the following function for this:
ledcAttachPin(GPIO, channel)
This function accepts two arguments. The first is the GPIO that will output the signal, and the second is the channel that will generate the signal.
5. Finally, to control the LED brightness using PWM, you use the following function:
ledcWrite(channel, dutycycle)
This function accepts as arguments the channel that is generating the PWM signal, and the duty cycle.
Dimming an LED
Let’s look at a simple example of how to use the Arduino IDE with the ESP32 LED PWM controller.
Schematic
Connect an LED to your ESP32 as shown in the schematic diagram. The LED should be connected to GPIO 16.
(This schematic uses the ESP32 DEVKIT V1 module version with 30 GPIOs – if you’re using another model, please check the pinout for the board you’re using.)
Note: you can use any pin you want, as long as it can act as an output. All pins that can act as outputs can be used as PWM pins.
Code
Open your Arduino IDE and copy the following code.
// the number of the LED pin
const int ledPin = 16; // 16 corresponds to GPIO16
// setting PWM properties
const int freq = 5000;
const int ledChannel = 0;
const int resolution = 8;
void setup(){
// configure LED PWM functionalitites
ledcSetup(ledChannel, freq, resolution);
// attach the channel to the GPIO to be controlled
ledcAttachPin(ledPin, ledChannel);
}
void loop(){
// increase the LED brightness
for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){
// changing the LED brightness with PWM
ledcWrite(ledChannel, dutyCycle);
delay(15);
}
// decrease the LED brightness
for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle–){
// changing the LED brightness with PWM
ledcWrite(ledChannel, dutyCycle);
delay(15);
}
}
You start by defining the pin the LED is attached to. In this case, the LED is attached to GPIO 16.
const int ledPin = 16; // 16 corresponds to GPIO16
The PWM signal properties are then set. You choose to generate the signal on channel 0 with a resolution of 8 bits and a frequency of 5000 Hz. To generate different PWM signals, you can choose properties other than these.
const int freq = 5000;
const int ledChannel = 0;
const int resolution = 8;
You must configure LED PWM with the properties you defined earlier in setup () using the LEDcSetup () function, which accepts as arguments the LEDChannel, frequency, and resolution:
ledcSetup(ledChannel, freq, resolution);
The next step is to select the GPIO from which you will receive the signal. Use the LEDcAttachPin () function, which accepts two arguments: the GPIO from which the signal is to be obtained and the channel from which the signal is generated. In this example, we’ll use GPIO 16 to get the signal from the ledPin GPIO. The ledChannel, which corresponds to channel 0, is the channel that generates the signal.
ledcAttachPin(ledPin, ledChannel);
In the loop, you’ll vary the duty cycle between 0 and 255 to increase the LED brightness.
for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){
// changing the LED brightness with PWM
ledcWrite(ledChannel, dutyCycle);
delay(15);
}
And then, between 255 and 0 to decrease the brightness.
for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle–){
// changing the LED brightness with PWM
ledcWrite(ledChannel, dutyCycle);
delay(15);
}
To control the brightness of the LED, simply call the ledcWrite() function, which takes two arguments: the signal’s channel and the duty cycle.
ledcWrite(ledChannel, dutyCycle);
Because we’re working with an 8-bit resolution, the duty cycle will be controlled by a number between 0 and 255. In the ledcWrite () function, we use the channel that is generating the signal rather than the GPIO.
Testing the Example
Upload the code to your ESP32. Make sure you have the right board and COM port selected. Look at your circuit. You should have a dimmer LED that increases and decreases brightness.
Getting the Same Signal on Different GPIOs
You can get the same signal from the same channel in different GPIOs. To accomplish this, simply connect those GPIOs to the same channel in the setup ().
Let’s extend the previous example by dimming three LEDs with the same PWM signal coming from the same channel.
Schematic
Add two more LEDs to your circuit by following the next schematic diagram:
(This schematic uses the ESP32 DEVKIT V1 module version with 30 GPIOs – if you’re using another model, please check the pinout for the board you’re using.)
Code
Copy the following code to your Arduino IDE.
// the number of the LED pin
const int ledPin = 16; // 16 corresponds to GPIO16
const int ledPin2 = 17; // 17 corresponds to GPIO17
const int ledPin3 = 5; // 5 corresponds to GPIO5
// setting PWM properties
const int freq = 5000;
const int ledChannel = 0;
const int resolution = 8;
void setup(){
// configure LED PWM functionalitites
ledcSetup(ledChannel, freq, resolution);
// attach the channel to the GPIO to be controlled
ledcAttachPin(ledPin, ledChannel);
ledcAttachPin(ledPin2, ledChannel);
ledcAttachPin(ledPin3, ledChannel);
}
void loop(){
// increase the LED brightness
for(int dutyCycle = 0; dutyCycle <= 255; dutyCycle++){
// changing the LED brightness with PWM
ledcWrite(ledChannel, dutyCycle);
delay(15);
}
// decrease the LED brightness
for(int dutyCycle = 255; dutyCycle >= 0; dutyCycle–){
// changing the LED brightness with PWM
ledcWrite(ledChannel, dutyCycle);
delay(15);
}
}
This is the same code as the previous one but with some modifications. We’ve defined two more variables for two new LEDs, that refer to GPIO 17 and GPIO 5.
const int ledPin2 = 17; // 17 corresponds to GPIO17
const int ledPin3 = 5; // 5 corresponds to GPIO5
Then we added the following lines to setup() to assign both GPIOs to channel 0. This means that we’ll get the same signal that is being generated on channel 0, on both GPIOs.
ledcAttachPin(ledPin2, ledChannel);
ledcAttachPin(ledPin3, ledChannel);
Testing the Project
Upload the new sketch to your ESP32. Make sure you’re using the correct board and COM port. Take a closer look at your circuit now:
The same PWM signal is sent out by all GPIOs. As a result, the brightness of all three LEDs rises and falls at the same time, producing a synchronized effect.
Wrapping Up
To summarize, you learned how to dim an LED using the ESP32’s LED PWM controller and the Arduino IDE in this post. By setting the right properties to the signal, the concepts learned can be used to control other outputs with PWM.