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 GPIO Pins – LEDs and Buttons

Posted on 29. January 202523. May 2025 by Stefan Draeger

After demonstrating how to flash the ESP32 for MicroPython and introducing the programming language’s structure, we will now control LEDs and buttons via GPIO pins.

MicroPython & ESP32 - GPIO-Pins steuern – LEDs und Taster
Watch this video on YouTube.

For this series, I am using the ESP32 D1 R32 along with the Rich Shield Two from Open Smart. If you don’t have this shield, I’ll provide guidance on how to set up the circuit on a breadboard.

ESP32 D1 R32
ESP32 D1 R32
ESP32 D1 R32 with Rich Shield by Open Smart
ESP32 D1 R32 with Rich Shield by Open Smart
ESP-WROOM-32 Chip on ESP32 D1 R32
ESP-WROOM-32 Chip on ESP32 D1 R32

Table of Contents

  • LEDs on the Rich Shield from Open Smart
    • Circuit without Rich Shield
    • Controlling the GPIO Pins of the LEDs
    • Making the LED Blink
      • Blinking the LED a Specific Number of Times
      • Blinking the LED for a Specific Duration
      • Making the LED Blink Indefinitely
    • Programming a Running Light
    • Reading Button States
      • Circuit without Rich Shield
    • Reading the Status of Buttons
    • Activating an LED with a Button
    • Toggling an LED with a Single Button
    • Conclusion & Outlook

LEDs on the Rich Shield from Open Smart

The LEDs on the Rich Shield from Open Smart are connected to the following pins:

LEDESP32 D1 R32Arduino UNO R3
LED1 (red)IO17D4
LED2 (green)IO16D5
LED3 (blue)IO27D6
LED4 (yellow)IO14D7
Rich Shield from Open Smart on the ESP32 D1 R32
Rich Shield from Open Smart on the ESP32 D1 R32
Rich Shield with activated LEDs
Rich Shield with activated LEDs

Circuit without Rich Shield

If you don’t have the Rich Shield from Open Smart, you can build the circuit on a breadboard as shown below:

Circuit - ESP32 D1 R32 with LEDs
Circuit – ESP32 D1 R32 with LEDs

Controlling the GPIO Pins of the LEDs

A GPIO pin can serve as both input and output. An LED is an output device (in this case, light), so the pin is defined as Pin.OUT. If we had a button, it would be defined as Pin.IN.

To introduce a small delay in the code, we need to import the time module. This module offers many functions, one of which is time.sleep(<seconds>), where the parameter is the number of seconds. (Unlike the Arduino IDE’s delay function, which expects milliseconds.)

# Module for accessing GPIO pins
import machine
# Module for functions like introducing a pause in the code
import time

# Create a variable for GPIO17 as output
led1 = machine.Pin(17, machine.Pin.OUT)
led1.value(1)  # Activate the pin
time.sleep(1)  # Pause for 1 second
led1.value(0)  # Deactivate the pin

When we run the code, LED1 (red) will be activated for 1 second and then deactivated. The program then terminates automatically.

Making the LED Blink

In the post “MicroPython with ESP32: Programming basics” I introduced loops. With a loop, we can now make the LED blink. We can make it blink a specific number of times, for a specific duration, or indefinitely.

Blinking the LED a Specific Number of Times

To blink an LED a certain number of times, we use a for loop to count from/to a specified range. In the code below, I count from 1 to 5, without using the loop variable i.

# Module for accessing GPIO pins
import machine
# Module for functions like introducing a pause in the code
import time

# Pause duration in the loop
pause = 0.250

# Create a variable for GPIO17 as output
led1 = machine.Pin(17, machine.Pin.OUT)

# Loop from 1 to 5
for i in range(1, 6):
    led1.value(1)  # Activate the pin
    time.sleep(pause)  # Pause
    led1.value(0)  # Deactivate the pin
    time.sleep(pause)  # Pause

In the video, you can see the small red 5mm LED blink a total of 5 times. If we adjust the range in the for loop to range(1, 11), it would blink 10 times.

Blinking the LED for a Specific Duration

To make the LEDs blink for a specific duration, we need the current timestamp and the desired duration. Simple mathematics and a while loop help us achieve this.

# Module for accessing GPIO pins
import machine
# Module for functions like introducing a pause in the code
import time

# Pause duration in the loop
pause = 0.250

# Create a variable for GPIO17 as output
led1 = machine.Pin(17, machine.Pin.OUT)

# Current milliseconds since the program started
currentTimestamp = time.ticks_ms()
# Duration for which the LED should blink
duration = 5000

# Blink the LED for a specific duration
# The function ticks_ms() returns the current milliseconds since the program started.
while time.ticks_ms() < (currentTimestamp + duration):
    led1.value(1)  # Activate the pin
    time.sleep(pause)  # Pause
    led1.value(0)  # Deactivate the pin
    time.sleep(pause)  # Pause

In the video, I let the LED blink for 2 seconds; with a pause of 0.25 seconds each, it blinks 4 times.

Making the LED Blink Indefinitely

To make the LED blink indefinitely, we simply set our while loop to an infinite loop by passing True.

# Module for accessing GPIO pins
import machine
# Module for functions like introducing a pause in the code
import time

# Pause duration in the loop
pause = 0.250

# Create a variable for GPIO17 as output
led1 = machine.Pin(17, machine.Pin.OUT)

# Start the infinite loop
while True:
    led1.value(1)  # Activate the pin
    time.sleep(pause)  # Pause
    led1.value(0)  # Deactivate the pin
    time.sleep(pause)  # Pause

Programming a Running Light

By activating and deactivating the LEDs sequentially, we can create a simple running light effect.

To reduce the amount of code and keep it concise, I create an additional function to set the status of the LEDs.

# Module for accessing GPIO pins
import machine
# Module for accessing functions like introducing a pause
import time

# Pause duration in the loop
pause = 0.130

# Creating variables for the LEDs as outputs
led1 = machine.Pin(17, machine.Pin.OUT)
led2 = machine.Pin(16, machine.Pin.OUT)
led3 = machine.Pin(27, machine.Pin.OUT)
led4 = machine.Pin(14, machine.Pin.OUT)

# Function to set the LED statuses
def ledLightUp(led1Status, led2Status, led3Status, led4Status):
    led1.value(led1Status)
    led2.value(led2Status)
    led3.value(led3Status)
    led4.value(led4Status)
    time.sleep(pause)  # Pause

# Start the infinite loop
while True:
    # Call the ledLightUp function with the new LED status as parameters
    ledLightUp(1, 0, 0, 0)  # Red LED on
    ledLightUp(0, 0, 0, 0)  # All LEDs off
    ledLightUp(0, 1, 0, 0)  # Green LED on
    ledLightUp(0, 0, 0, 0)  # All LEDs off
    ledLightUp(0, 0, 1, 0)  # Blue LED on
    ledLightUp(0, 0, 0, 0)  # All LEDs off
    ledLightUp(0, 0, 0, 1)  # Yellow LED on
    ledLightUp(0, 0, 0, 0)  # All LEDs off

Reading Button States

The small shield includes two additional buttons, which we will use to activate LEDs and start various programs.

Buttons K1 & K2 on the Rich Shield from Open Smart
Buttons K1 & K2 on the Rich Shield from Open Smart
ButtonESP32 D1 R32Arduino UNO R3
K1IO12D8
K2IO13D9

Circuit without Rich Shield

Here’s the circuit setup on a 400-pin breadboard:

Circuit - ESP32 D1 R32 with LEDs & button
Circuit – ESP32 D1 R32 with LEDs & button

Reading the Status of Buttons

To read the button status, we need an infinite loop. Without it, the program wouldn’t be able to evaluate button actions.

# Module for accessing GPIO pins
import machine
# Module for accessing functions like introducing a pause
import time

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

# Start the infinite loop
while True:
    # Check if button K1 is pressed
    if not k1.value():
        print("Button K1 pressed!")  # Print to console
        time.sleep(0.25)  # Debounce delay
    
    # Check if button K2 is pressed
    if not k2.value():
        print("Button K2 pressed!")
        time.sleep(0.25)  # Debounce delay

When pressing one of the buttons, the message “Button K1 pressed!” or “Button K2 pressed!” will appear on the console. A small delay of 0.25 seconds prevents button bouncing.

Activating an LED with a Button

Now, using the knowledge of LEDs and buttons, we can control LEDs with button presses.

# Module for accessing GPIO pins
import machine
# Module for accessing functions like introducing a pause
import time

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

# LED1 (red)
led1 = machine.Pin(17, machine.Pin.OUT)

# Start the infinite loop
while True:
    # Activate LED1 when K1 is pressed
    if not k1.value():
        led1.value(1)
        time.sleep(0.25)
    
    # Deactivate LED1 when K2 is pressed
    if not k2.value():
        led1.value(0)
        time.sleep(0.25)

Toggling an LED with a Single Button

Using a single button, we can both activate and deactivate an LED by checking its current status.

# Module for accessing GPIO pins
import machine
# Module for accessing functions like introducing a pause
import time

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

# LED1 (red)
led1 = machine.Pin(17, machine.Pin.OUT)
# LED2 (green)
led2 = machine.Pin(16, machine.Pin.OUT)

# Start the infinite loop
while True:
    # Toggle LED1 when K1 is pressed
    if not k1.value():
        if not led1.value():
            led1.value(1)  # Turn on
        else:
            led1.value(0)  # Turn off
        time.sleep(0.25)  # Debounce delay
    
    # Toggle LED2 when K2 is pressed
    if not k2.value():
        if not led2.value():
            led2.value(1)  # Turn on
        else:
            led2.value(0)  # Turn off
        time.sleep(0.25)  # Debounce delay

Now, we can use the two buttons to control the red and green LEDs.

Conclusion & Outlook

This concludes the small post. In the next article, I’ll show you how to read the analog rotary potentiometer and map the values to 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}