Pulse width modulation is used in a variety of applications particularly for control. It can be used for the dimming of LEDs, varying speed of motors  and controlling the angle of servo motors

In ESP32 PWM can be initiated on all output-enabled pins.

Image 5

pwm_Image 4


PWM is digital, which means that it has two states: on and off.The amount of current that flows to a device like LED can be controlled by varying the time each pulse stays ON.

The longer each pulse is on, the brighter the LED will be.

DUTY CYCLE refers the amount of time the pulse  is ON.

For a square wave the DUTY cycle is 50 % , the pulse is ON for 50% of the time and OFF for 50%

If duty cycle is 100% then the output is equal to Vcc ( 3.3v here) and LED will be full lit.

If duty cycle is 0% , the signal is flat and equal to Gnd voltage 0.


Connect an LED at GPIO 15.

Short lead of LED goes to Gnd through  a Resistor 1k.



We shall use THONNY PYTHON IDE to test and upload python code on to ESP32.

Refer to my previous blog on how to use Thonny Python


Let us use the interpreter of Thonny Python to test the code.

First import from machine module the Pin & PWM classes.

Pin module is to control the GPIO pins.



Then create a PWM object called led and pass on the GPIO Pin 15.

Once the led object is created you can use the methods like duty to set the duty cycle and freq to set the frequency.

Duty cycle can be from 0 to 1023.

512 represents 50% , and 1023 = 100%. duty cycle.

led.freq(1) makes the LED flash once per second.



You can create the PWM object and pass on the duty,freq in a single line of code.


To stop PWM use the method deinit().





Now let us give the LED a fade effect using PWM.

Micropython executes boot.py file on power on.

Then it looks out for main.py file to execute.

In case you need your own naming for file , then create that file and import  the module and place a call for the function inside main.py.

Though boot.py file has nothing to execute inside , this file exists by default in Micropython.

Image 1

Inside main.py file

import fadeled


fadeled is the module we have to create

& ledpwm() is the function in that module.

Without creating this new module we could have named the file as main.py and write the complete code inside main.py

Image 2

In the never ending loop while True: , we change the duty cycle from 0 to 1023

using in range function.

This gives a fading effect on LED.

Note the indentation after each colon : in python code.

This space or indentation represents braces.

Image 3

Click on File  –> Save as

and select Micropython device to save.

Save the file as fadeled.py

Like this save the main.py file also to ESP32.



Now click on F5 or the green arrow button on top to execute.

You can see the LED fading effect.

The PWM method can be used  to position the SERVO motor from 0 to 180 degrees.

All servo motors have 3 wires.Red to 5v, Black or Brown to Gnd

Orange wire is Signal (pwm)


Connect the Servo signal pin at GPIO 23.

As servo requires 5V we use an external power source of 5 Volt.

The Gnd of 5V source and the Gnd of ESP 32 must be made common i.e connected together.This is a must while using 2 different power sources.



Frequency (1/period) is specific to controlling a servo.

A typical servo motor expects to be updated every 20 ms with a pulse between 1 ms and 2 ms, or in other words, between a 5 and 10% duty cycle on a 50 Hz waveform.

So frequency of 50 hz is a must to control most Servos .This gives a 20 msec pulse.

With a 1.5 ms pulse, the servo motor will be at the natural 90 degree position. With a 1 ms pulse, the servo will be at the 0 degree position, and with a 2 ms pulse, the servo will be at 180 degrees.

Duty cycle from 20 to 120 facilitates position of servo fro 0 to 180 degrees.


servo object is created by passing on PWM Pin as GPIO 23 and frequency as 50

1/50hz = 0.02 = 20 msec which is required to update most servos.

We set the duty cycle to 20  to position servo at 9 degree.

duty 70 –>  90 degree

duty 120 – > 180 degree