Skip to content

Technik Blog

Programmieren | Arduino | ESP32 | MicroPython | Python | Raspberry Pi | Raspberry Pi Pico

Menu
  • About me
  • Contact
  • Deutsch
  • English
Menu

MicroPython with ESP32: Controlling LED Brightness with PWM

Posted on 5. February 202523. January 2025 by Stefan Draeger

In this post, you’ll learn how to use Pulse Width Modulation (PWM) with the ESP32 D1 R32 and MicroPython. PWM is a versatile technique widely used in many applications, from LED dimming to motor control. With the ESP32 and MicroPython, generating and controlling PWM signals is straightforward.

MicroPython & ESP32 - Helligkeitsregelung von LEDs mit PWM
Watch this video on YouTube.

n a previous post, MicroPython with ESP32: Introduction to the ESP32 D1 R32, I showed you how to prepare the microcontroller for programming in MicroPython. In another post, MicroPython with ESP32: Controlling GPIO Pins – LEDs and Buttons, I demonstrated how to control buttons and LEDs. However, the section on dimming LEDs was missing, which I would like to cover here.

Table of Contents

  • What is PWM?
  • Generating a PWM Signal on the ESP32 in MicroPython
    • Step 1 – Importing the Required Modules
    • Step 2 – Initializing a GPIO Pin
    • Step 3 – Configuring the PWM Signal
    • Step 4 – Setting the PWM Value
    • Step 5 – Deinitializing the GPIO Pin
  • Programming a Fade Effect on an LED
  • Controlling LED Brightness with Buttons
  • Outlook

What is PWM?

PWM stands for Pulse Width Modulation. It’s a method to control analog devices using digital signals. The signal is rapidly turned on and off, with the duration of the on and off states being varied. An example is controlling the brightness of an LED or the speed of a motor.

Generating a PWM Signal on the ESP32 in MicroPython

Let’s dive in and generate a PWM signal on the ESP32 D1 R32 using MicroPython.

Rich Shield with activated LEDs
Rich Shield with activated LEDs
Circuit - ESP32 D1 R32 with LEDs
Circuit – ESP32 D1 R32 with LEDs

If you don’t have the Rich Shield from Open Smart, you can easily replicate this circuit on a breadboard.

Let’s take a closer look at the source code for generating a PWM signal on an LED:

Step 1 – Importing the Required Modules

To control a GPIO pin and later generate a PWM signal on the ESP32, we need the Pin and PWM modules from machine. We’ll also import the sleep function from time to introduce delays in the code.

# Modules for controlling GPIO pins
from machine import Pin, PWM
# Module for introducing delays in the code
from time import sleep

Step 2 – Initializing a GPIO Pin

In this case, I want to use the red LED1 on the Rich Shield, which is connected to GPIO 17. This pin should be set as an output.

# Initialize a PWM pin
led = PWM(Pin(17, Pin.OUT))

Step 3 – Configuring the PWM Signal

For an LED, setting the frequency to 5 kHz is sufficient.

Setting the PWM frequency to 5 kHz (kilohertz) has several reasons, mainly related to the desired application and the characteristics of the devices being controlled. Here are some key points explaining why 5 kHz can be a good choice:

  • Avoiding Flicker in LEDs: At lower PWM frequencies, LEDs can produce flicker that is visible and distracting to the human eye. A frequency of 5 kHz is well above the perception threshold, effectively preventing flicker.
  • Efficiency in Motor Control: When controlling DC motors, a higher PWM frequency can lead to smoother and more consistent movement. A frequency of 5 kHz ensures that motors operate more efficiently with less vibration.
  • General Compatibility: A frequency of 5 kHz is suitable for many PWM applications, whether for LEDs, motors, or other devices. It offers a good balance between performance and compatibility.
  • Avoiding Noise: In some applications, lower frequencies can produce audible noises (e.g., humming in motors or buzzing in speakers). A frequency of 5 kHz is outside the audible range for most people, preventing these noises.
# Set frequency to 5 kHz
led.freq(5000)

Step 4 – Setting the PWM Value

Using the duty function on the PWM object, we set the brightness of the LED. We can input values between 0 and 1023.

# Set brightness to 1/4 (0..1023)
led.duty(256)

Step 5 – Deinitializing the GPIO Pin

Finally, it’s generally a good idea to deactivate the used pins, as otherwise, the connected actuators (LEDs, motors, etc.) will continue to operate. In the case of an LED, it would simply remain lit.

# Deinitialize the pin
led.deinit()

Programming a Fade Effect on an LED

Next, I’d like to show you how to program a fade effect. This effect gradually makes an LED light up and dim down.

For this effect, we start a for-loop ranging from 0 to 1023 and use the index as the brightness value for the LED. It’s important to include a small 15 ms delay so we can actually see the effect.

# Loop from 0 to 1023
for value in range(0, 1024):
    # Set the current value of the index
    # as the brightness level
    led.duty(value)
    # Pause for 15 ms
    sleep(0.015)

Here is the complete code:

# Modules for controlling GPIO pins
from machine import Pin, PWM
# Module for introducing delays in the code
from time import sleep

# Initialize a PWM pin
led = PWM(Pin(17, Pin.OUT))
# Set frequency to 5 kHz
led.freq(5000)

# Loop from 0 to 1023
for value in range(0, 1024):
    # Set the current value of the index
    # as the brightness level
    led.duty(value)
    # Pause for 15 ms
    sleep(0.015)

# Deinitialize the pin
led.deinit()

Controlling LED Brightness with Buttons

On the Rich Shield by Open Smart, you’ll also find two buttons that can be used to control the brightness of the LED. Since adjusting all 1023 levels using buttons would be tedious, I’ll increment and decrement the brightness in steps of 100.

# Modules for controlling GPIO pins
from machine import Pin, PWM
# Module for introducing delays in the code
from time import sleep

# Define variables for the buttons
# Button K1 on GPIO12
k1 = Pin(12, Pin.IN, Pin.PULL_UP)
# Button K2 on GPIO13
k2 = Pin(13, Pin.IN, Pin.PULL_UP)

# Initialize a PWM pin
led = PWM(Pin(17, Pin.OUT))
# Set frequency to 5 kHz
led.freq(5000)

# Variable to store the brightness value
brightness = 0

# Function to set the brightness
def setLEDBrightness():
    global brightness
    # Print the brightness value to the console
    print("Brightness:", brightness)
    # Set the brightness on the LED
    led.duty(brightness)

# Try/Catch block
try:
    # Start an infinite loop
    while True:
        # If button K1 is pressed and brightness is below 1000
        if not k1.value() and brightness < 1000:
            # Increase brightness by 100
            brightness += 100
            # Set the new brightness level
            setLEDBrightness()
            # Pause for 300 ms
            sleep(0.3)

        # If button K2 is pressed and brightness is above 0
        if not k2.value() and brightness > 0:
            # Decrease brightness by 100
            brightness -= 100
            setLEDBrightness()
            # Pause for 300 ms
            sleep(0.3)

# Handle KeyboardInterrupt exception when the program is stopped
except KeyboardInterrupt:
    # Deinitialize the LED
    led.deinit()

Outlook

In the next post, we will explore the rotary potentiometer. I’ll show you how to read its values and use them to control the LEDs.

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Fragen oder Feedback?

Du hast eine Idee, brauchst Hilfe oder möchtest Feedback loswerden?
Support-Ticket erstellen

Newsletter abonnieren

Bleib auf dem Laufenden: Erhalte regelmäßig Updates zu neuen Projekten, Tutorials und Tipps rund um Arduino, ESP32 und mehr – direkt in dein Postfach.

Jetzt Newsletter abonnieren

Unterstütze meinen Blog

Wenn dir meine Inhalte gefallen, freue ich mich über deine Unterstützung auf Tipeee.
So hilfst du mit, den Blog am Leben zu halten und neue Beiträge zu ermöglichen.

draeger-it.blog auf Tipeee unterstützen

Vielen Dank für deinen Support!
– Stefan Draeger

Categories

Links

Blogverzeichnis Bloggerei.de TopBlogs.de das Original - Blogverzeichnis | Blog Top Liste Blogverzeichnis trusted-blogs.com

Stefan Draeger
Königsberger Str. 13
38364 Schöningen

Tel.: 01778501273
E-Mail: info@draeger-it.blog

Folge mir auf

  • Impressum
  • Datenschutzerklärung
  • Disclaimer
  • Cookie-Richtlinie (EU)
©2025 Technik Blog | Built using WordPress and Responsive Blogily theme by Superb
Cookie-Zustimmung verwalten
Wir verwenden Cookies, um unsere Website und unseren Service zu optimieren.
Funktional Always active
Die technische Speicherung oder der Zugang ist unbedingt erforderlich für den rechtmäßigen Zweck, die Nutzung eines bestimmten Dienstes zu ermöglichen, der vom Teilnehmer oder Nutzer ausdrücklich gewünscht wird, oder für den alleinigen Zweck, die Übertragung einer Nachricht über ein elektronisches Kommunikationsnetz durchzuführen.
Vorlieben
Die technische Speicherung oder der Zugriff ist für den rechtmäßigen Zweck der Speicherung von Präferenzen erforderlich, die nicht vom Abonnenten oder Benutzer angefordert wurden.
Statistiken
Die technische Speicherung oder der Zugriff, der ausschließlich zu statistischen Zwecken erfolgt. Die technische Speicherung oder der Zugriff, der ausschließlich zu anonymen statistischen Zwecken verwendet wird. Ohne eine Vorladung, die freiwillige Zustimmung deines Internetdienstanbieters oder zusätzliche Aufzeichnungen von Dritten können die zu diesem Zweck gespeicherten oder abgerufenen Informationen allein in der Regel nicht dazu verwendet werden, dich zu identifizieren.
Marketing
Die technische Speicherung oder der Zugriff ist erforderlich, um Nutzerprofile zu erstellen, um Werbung zu versenden oder um den Nutzer auf einer Website oder über mehrere Websites hinweg zu ähnlichen Marketingzwecken zu verfolgen.
Manage options Manage services Manage {vendor_count} vendors Read more about these purposes
Einstellungen anzeigen
{title} {title} {title}