In this post we shall see how PWM is implemented on ESP32 & used to fade an LED or control speed of a motor.

In Arduino or ESP8266 Nodemcu we used the analogWrite() function to achieve PWM.

But Analog Write function is not yet implemented in ESP32 Arduino version.

Instead a new Function called ledcWrite() is introduced.

As the analogWrite()  function is not yet available for the ESP32 , we will need to go to lower level functions.We will also have more control and flexibility in the PWM functionality, which is good.


Image 15

In this example let us fade the inbuilt LED onboard. It is mapped to GPIO2 pin.

We declare some variables to start with. GPIO2 pin is assigned to a byte variable led_pin as 2.

2 more integer variables used to store brightness & fadevalue.

Image 2

Inside SETUP first thing is , we need to attach a channel ( channels available from 0 to 15) to a GPIO pin  where we want the PWM signal to be generated.

Any GPIO pin can be used , but certain pins which are only INPUTS like GPIO 14,15,16 & 19 CANNOT BE ATTACHED.


GPIO OUTPUT capable pins can only be attached. The function used here is


In this example, we’ll get the signal in the led_Pin GPIO, that corresponds to GPIO 2 ( inbuilt LED). The channel that generates the signal is the ledChannel, that we assign  to channel 0. There are 16 PWM channels from 0 to 15 in ESP32 & one of them is attached to a GPIO pin.


Next , PWM characteristics are then defined using function


e.g ledSetup(0,12000,8);

Here the first parameter is the channel number  (channel 0 is used here)

2nd parameter is the PWM Frequency ,here it is 5000 ( 5kHz) which is idle to fade an LED

3rd parameter is resolution in bits .Upto 16 bits accepted. Here we use 8 bits , so the maximum analog value is 255 ( 0 to 255 = 256)

We’ll use 8-bit resolution, which means you can control the LED brightness using a value from 0 to 255.


Finally, to control the LED brightness using PWM, you use the following function:

ledcWrite(channel, dutycycle)

This function accepts 2 arguments a channel number & an analog value (duty cycle)

Note that we use the channel that is generating the signal, and not the GPIO

Although the duty cycle is  specified as a percentage, this function receives a value between 0 and another value different from 100.We can pass a value between 0 (wave always with a value of GND) and 1023 (wave always with a value of VCC for 8 bit resolution) for the duty cycle.



const byte led_pin = 2;

int brightness=0;

int fadevalue = 5;

void setup() {

ledcAttachPin (led_pin,0);

ledcSetup(0,5000,8); // channel 0, pwm freq 5 khz, Resolution 8 bits


void loop() {



if(brightness <=0 || brightness >= 255) {

fadevalue = -fadevalue;






Inside the loop we vary the duty cycle from 0 to 255 to increase brightness of LED gradually & when it reaches vaLue 255 , we decrease it thus fading down the LED.

Now upload the code.Press & Hold the Boot button for a smooth upload.

Once code is uploaded , you can see the inbuilt blue LED fading.


In the second example let us add a potentiometer ( 10k value) to GPIO4.

One end of pot is connected to +3.3v , the other end to GND.

Center pin of pot is connected to GPIO4.

LED connected to GPIO15 is faded according to pot variation.





Image 3





const byte led_pin = 15;

const byte pot_pin = 4;

void setup() {

ledcAttachPin (led_pin,0);

ledcSetup(0,5000,8); // channel 0, pwm freq 5 khz, Resolution 8 bits


void loop() {




Inside loop() function we use the ledcWrite() function , so that according to pot variation LED brightness varies.

With the same code uploaded , we can control the speed of a motor.



Potentiometer is connected to GPIO 4 as in 2nd example.

To control a motor we need L293 driver board.As the motor used is a BO motor of 6v we need a separate power source for L293. A 6v battery is used for L293 Board.




L293 board can control 2 DC motors & it sources 500ma current.For control of each motor 2 set of control pins are provided.

IN1,IN2,EN1 for 1st motor & IN2,IN3,EN2 for second motor.In this example we use only one motor.So the first set of control pins are used.

For forward control of motor IN1 is connected to LOW  , 0 , & IN2 is connected to HIGH  (1) .

A built in 5v regulator is on board L293. This 5v pin can be used as HIGH & GND pin is used as LOW.

Ensure that GND pin of L293, Negative of 6v battery & GND pin of ESP32 all are made common & connected together.

EN1 is the enable pin which can also be used by PWM to control speed.If this pin is pulled High , then the motor will rotate at fixed speed.To vary speed we connect this EN1 pin to PWM pin of ESP32

, which is GPIO15 in our example.





Now you can vary the potentiometer & control the speed of motor.