ESP32/ESP8266 PWM with MicroPython – Dim LED

This tutorial shows how to generate PWM signals with the ESP32 and ESP8266 boards using MicroPython firmware. As an example, we’ll dim the brightness of an LED by changing the duty cycle over time.

ESP32/ESP8266 PWM with MicroPython Dim LED

Prerequisites

To follow this tutorial you need to have MicroPython firmware installed in your ESP32 or ESP8266 boards. You also need an IDE to write and upload the code to your board. We suggest using Thonny IDE or uPyCraft IDE:

Schematic

For this example, wire an LED to your ESP board. We’ll wire the LED to GPIO 5 in both boards, but you can choose another suitable PWM pin. See the best pins to use in our ESP32 Pinout Reference Guide.

Parts required

Here’s a list of the parts you need to build the circuit:

You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!

Schematic – ESP32

Follow the next schematic diagram if you’re using an ESP32 board:

ESP32 PWM with MicroPython circuit to fade Dim LED

Schematic – ESP8266

Follow the next schematic diagram if you’re using an ESP8266 board:

ESP8266 PWM with MicroPython circuit to fade Dim LED

Script

Here’s the script that changes the LED brightness over time by increasing the duty cycle. This script works with the ESP32 and ESP8266.

# Complete project details at https://RandomNerdTutorials.com

from machine import Pin, PWM
from time import sleep

frequency = 5000
led = PWM(Pin(5), frequency)

while True:
  for duty_cycle in range(0, 1024):
    led.duty(duty_cycle)
    sleep(0.005)

View raw code

How the code works

To create a PWM pin, import the PWM class in addition to the Pin class from the machine module.

from machine import Pin, PWM

Then, create a PWM object called led.

led = PWM(Pin(5), frequency)

To create a PWM object, you need to pass as parameters, the pin it is connected to, the signal frequency and the duty cycle.

  • Frequency: The frequency can be a value between 0 and 78125. A frequency of 5000 Hz can be used to control the LED brightness.
  • Duty cycle: The duty cycle can be a value between 0 and 1023. In which 1023 corresponds to 100% duty cycle (full brightness), and 0 corresponds to 0% duty cycle (unlit LED).

We’ll just set the duty cycle on the while loop, so we don’t need to pass the duty cycle parameter. If you don’t set the duty cycle when instantiating the PWM object, it will be 0 by default.

To set the duty cycle use the duty() method on the PWM object and pass the duty cycle as an argument:

led.duty(duty_cycle)

Inside the while loop, we create a for loop that increases the duty cycle by 1 in each loop with an interval of 5 ms between each change.

for duty_cycle in range(0, 1024):
    led.duty(duty_cycle)
    sleep(0.005)

The range() function has the following syntax:

range(start, stop, step)
  • Start: a number that specifies at which position to start. We want to start with 0 duty cycle;
  • Stop: a number that specifies at which position we want to stop, excluding that value. The maximum duty cycle is 1023, because we are incrementing 1 in each loop, the last value should be 1023+1. So, we’ll use 1024.
  • Step: an integer number that specifies the incrementation. By default, incrementation is 1.

In each for loop, we set the LED’s duty cycle to the current duty_cycle value:

led.duty(duty_cycle)

After that, the duty_cycle variable is incremented by 1.

Demonstration

Save the code to your ESP board using Thonny IDE or uPyCraft IDE. The LED attached to GPIO 5 should increase brightness over time.

ESP32/ESP8266 PWM with MicroPython circuit to fade Dim LED

Wrapping Up

We hope you’ve found this MicroPython tutorial useful. If you want to learn more about MicroPython, make sure you take a look at our eBook: MicroPython Programming with ESP32 and ESP8266.

If you like MicroPython, you may also like:

Thanks for reading.



Build Web Server projects with the ESP32 and ESP8266 boards to control outputs and monitor sensors remotely. Learn HTML, CSS, JavaScript and client-server communication protocols DOWNLOAD »

Build Web Server projects with the ESP32 and ESP8266 boards to control outputs and monitor sensors remotely. Learn HTML, CSS, JavaScript and client-server communication protocols DOWNLOAD »


Enjoyed this project? Stay updated by subscribing our weekly newsletter!

5 thoughts on “ESP32/ESP8266 PWM with MicroPython – Dim LED”

  1. Hello, I have some trouble with multiple PWM frequencies:
    from machine import PWM, Pin
    ledR = PWM(Pin(13), freq = 5000, duty = 200)
    ledY = PWM(Pin(12), freq = 5000, duty = 200)
    ledG = PWM(Pin(14), freq = 5000, duty = 200)
    ledB = PWM(Pin(2), freq = 5, duty = 50)

    Last line is setting frequency for all the LEDs. It seems like they share the same frequency. Is there a way to solve it?

    Reply
      • I have tested completely all GPIOs. It seems like MicroPython (my version esp32-idf4-20200902-v1.13.bin) on ESP32 is using just 8 PWM channels (on 9th says: “out of PWM channels”), but sharing just one timer for all of them. Or maybe I am doing something wrong? You can try this:

        from machine import Pin, PWM
        from time import sleep

        def TestPWM(pins):
        pwm = []
        print(“Setting PWM:”)
        for pin in pins:
        print(“*”, pin, end = “: “)
        pwm.append(PWM(Pin(pin), freq = pin, duty = 500 + pin))
        sleep(0.5)
        print(pwm[-1])

        print("After that:")
        for p in pwm:
        print("*", p)

        print("Frequencies:")
        for i in range(len(pwm)):
        pwm[i].freq(10 + i)
        print("* setting one to", 10 + i, end = ": ")
        for p in pwm:
        print(p.freq(), end = " ")
        print()

        for p in pwm:
        p.deinit()

        TestPWM((2, 3, 4, 5, 12, 13, 14, 15))
        TestPWM((14, 15, 16, 17, 18, 19, 21, 22))
        TestPWM((21, 22, 23, 25, 26, 27, 32, 33))
        print(“OK”)

        Reply
        • Now I have tested different versions of MicroPython (1.9, 1.13 IDF3) and also ESP8266 – it is all the same. :-/ It means that I have to use machine.Timer() with 4 channels available and create my own pwm class?

          For higher frequencies it is also possible to use 8× RMTs on ESP32, but it is not so easy to set precise frequency. We may use it for LEDs:
          import esp32
          from machine import Pin, PWM
          ledR = esp32.RMT(0, pin = Pin(13))
          ledR.loop(True)
          ledY = esp32.RMT(1, pin = Pin(12))
          ledY.loop(True)
          ledG = esp32.RMT(2, pin = Pin(14))
          ledG.loop(True)

          duties:

          ledR.write_pulses((50, 50)) # 50:50 = 50 %
          ledY.write_pulses((10, 90)) # 10:90 = 10 %
          ledG.write_pulses((100, 0)) # 100:0 = 100 %
          ledB = PWM(Pin(2), freq = 5, duty = 50)

          In fact those write_pulses values are number of clock ticks (by default 100 ns) for output value 1 and 0.

          Lowest possible frequency is cca 5 Hz:
          * maximum value for write_pulses is 32767
          * source clock frequency is 80 MHz
          * maximum frequency divider is 255 => minimal clock frequency 314 kHz
          => one pulse time is 0.1 s at most
          => whole 1:1 period is 0.2 s = 5 Hz

          Reply

Leave a Comment

Download our Free eBooks and Resources

Get instant access to our FREE eBooks, Resources, and Exclusive Electronics Projects by entering your email address below.