asyncio. Aprenderás a ejecutar múltiples tareas de forma concurrente, creando la ilusión de multitarea y evitando bloquear tu código durante tareas de larga duración.

Por ejemplo, tu programa puede estar esperando la respuesta de un servidor y, al mismo tiempo, ser capaz de realizar otras tareas como comprobar si se ha presionado un botón o hacer parpadear un LED.
La programación asincrónica es sumamente útil en proyectos que incluyen: interactuar con bases de datos, comunicarse a través de redes (como al solicitar datos de un servidor o cuando la Pico actúa como servidor web), leer datos de sensores, mostrar información en una pantalla, recibir entradas de usuarios y mucho más.
Requisitos Previos
Antes de continuar, asegúrate de cumplir con los siguientes requisitos:
Firmware de MicroPython
Para seguir este tutorial, es necesario que tengas instalado el firmware de MicroPython en tu placa Raspberry Pi Pico. También necesitarás un IDE (Entorno de Desarrollo Integrado) para escribir y cargar el código en tu placa.

El IDE recomendado para trabajar con MicroPython en la Raspberry Pi Pico es Thonny IDE. Es ligero, gratuito y está diseñado específicamente para principiantes en microcontroladores.
Puedes seguir este tutorial básico si aún no tienes todo configurado:
Introducción a la Programación Asincrónica
La programación asincrónica es una técnica que permite que tu programa inicie una tarea que podría durar mucho tiempo y, aun así, siga respondiendo a otros eventos mientras esa tarea se ejecuta, en lugar de tener que esperar a que la tarea finalice.
Esto se logra ejecutando las tareas de manera no bloqueante y utilizando funciones (como las corrutinas en MicroPython) para manejar los resultados. De esta forma, el programa puede continuar ejecutando otras tareas mientras espera los resultados de la tarea asincrónica. Por el contrario, en la programación sincrónica, cada tarea debe esperar a que la anterior se complete antes de comenzar.
En resumen…
| Característica | Programación Sincrónica | Programación Asincrónica |
| Arquitectura | Bloqueante: Cada operación espera a que termine la anterior. | No bloqueante: La ejecución de una tarea no depende de otra. |
| Orden | Estrictamente secuencial. | Las tareas pueden avanzar de forma concurrente. |
| Eficiencia | Menor; el procesador “desperdicia” tiempo esperando. | Mayor; el procesador aprovecha los tiempos de espera. |
| Respuesta | El sistema puede parecer “congelado” durante tareas largas. | El sistema se mantiene responsivo (ej. detecta botones siempre). |

El Módulo asyncio de MicroPython
MicroPython proporciona el módulo asyncio, el cual es un framework de E/S asincrónica ligero inspirado en el módulo asyncio de Python. Puedes consultar todos los detalles sobre este módulo de MicroPython en el siguiente enlace:
Echemos un vistazo rápido a algunos conceptos básicos que necesitas saber para empezar a usar asyncio para la programación asincrónica:
-
Event Loop (Bucle de eventos): es un bucle que comprueba continuamente eventos (tareas o corrutinas) y los ejecuta.
-
Tasks (Tareas): unidades individuales de trabajo o corrutinas que están programadas para ejecutarse de forma concurrente dentro del bucle de eventos.
-
Asynchronous Functions (Funciones asincrónicas): también conocidas como corrutinas, estas son funciones que pueden ser pausadas y reanudadas sin bloquear otras operaciones, permitiendo la ejecución concurrente de múltiples tareas.
-
await: es una palabra clave utilizada dentro de las corrutinas para pausar la ejecución de la corrutina actual hasta que un evento u operación específica se complete, permitiendo que otras corrutinas se ejecuten mientras tanto.
Ahora, veamos con más detalle cada uno de esos conceptos, el flujo de trabajo y los métodos del módulo asyncio para escribir un programa asincrónico.
Event Loop (Bucle de eventos)
Un bucle de eventos es el núcleo de la programación asincrónica. Es un bucle que comprueba continuamente eventos (tareas o corrutinas) y los ejecuta. En asyncio, creas un bucle de eventos utilizando asyncio.get_event_loop().
La siguiente línea crea una instancia del bucle de eventos llamada loop. Puedes usar ese bucle para gestionar y programar tareas asincrónicas.
loop = asyncio.get_event_loop()Creación de Tareas
En la programación asincrónica, las tareas representan unidades de trabajo. Creas tareas para ejecutar corrutinas de forma concurrente. Las corrutinas son funciones definidas con la palabra clave async, que pueden ser pausadas y reanudadas, permitiendo la programación asincrónica.
Por ejemplo:
async def blink_led():
# Código para parpadear un LEDLuego, podemos usar loop.create_task() para programar esta corrutina como una tarea para ser ejecutada por el bucle de eventos.
loop.create_task(blink_led())Ejecución del Bucle de Eventos
Una vez que hayas creado las tareas, inicias el bucle de eventos para ejecutarlas. El bucle comprobará continuamente las tareas programadas y las ejecutará. La siguiente línea inicia el bucle de eventos, como hemos visto anteriormente.
loop = asyncio.get_event_loop()Después, loop.run_forever() hace que se ejecute indefinidamente, comprobando constantemente si hay tareas para ejecutar.
loop.run_forever()Funciones Asincrónicas – async def
Una función asincrónica se define utilizando la sintaxis async def. Estas funciones, también conocidas como corrutinas, pueden ser pausadas con la palabra clave await, permitiendo que otras corrutinas se ejecuten mientras tanto. Por ejemplo:
async def blink_led():
while True:
led.toggle() # Cambia el estado del LED
await asyncio.sleep(1)Aquí, blink_led() es una función asincrónica. Alterna un LED y luego se pausa durante 1 segundo usando await asyncio.sleep(1). Durante esta pausa, otras tareas pueden ejecutarse.
Retraso Asincrónico – asyncio.sleep()
asyncio.sleep() es una corrutina proporcionada por el módulo asyncio y se utiliza para introducir un retraso en la ejecución de una corrutina por una duración especificada sin bloquear todo el bucle de eventos. Por lo tanto, para crear una función asincrónica, debes reemplazar todos tus time.sleep() con asyncio.sleep().
-
Cuando se llama a
asyncio.sleep()dentro de una corrutina, se suspende temporalmente la ejecución de esa corrutina, permitiendo que otras corrutinas se ejecuten mientras tanto. -
El bucle de eventos continúa ejecutándose mientras la corrutina está pausada, comprobando otras tareas y eventos.
-
Después de la duración especificada (segundos), la corrutina pausada reanuda la ejecución desde el punto donde se llamó a
asyncio.sleep().
await asyncio.sleep() es una forma no bloqueante de ceder el control a otras corrutinas en el bucle de eventos sin introducir ningún retraso real. Permite efectivamente que otras corrutinas se ejecuten de inmediato.
await
La palabra clave await se utiliza dentro de las corrutinas para indicar un punto donde la corrutina puede ser suspendida temporalmente hasta que se complete un evento específico.
En el siguiente ejemplo, la corrutina se pausa durante 1 segundo sin bloquear todo el bucle de eventos.
await asyncio.sleep(1)
En Resumen…
Cuando ejecutas un programa asincrónico, el bucle de eventos se ejecuta continuamente, procesando las tareas programadas de forma concurrente. Cada corrutina tiene su turno para ejecutarse, y las sentencias await permiten que el bucle de eventos cambie entre tareas, creando la apariencia de paralelismo.
Como resultado, puedes realizar múltiples tareas de forma concurrente sin tener que esperar a que cada una se complete antes de pasar a la siguiente.
Ejemplo Básico de un Programa Asincrónico
Ahora que conoces los conceptos básicos de la programación asincrónica y los métodos básicos del módulo asyncio, vamos a crear un ejemplo sencillo para aplicar los conceptos aprendidos.
Crearemos dos corrutinas diferentes. Cada corrutina hará parpadear un LED diferente a un ritmo diferente.
-
LED Verde Pasto: GPIO 20 >> parpadea cada dos segundos;
-
LED Azul Marino: GPIO 19 >> parpadea cada medio segundo.
Para comprobar visualmente el resultado final, conecta dos LEDs a la Raspberry Pi Pico, uno al GPIO 20 y otro al GPIO 19.

Este es el código de ejemplo:
# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/micropython-raspberry-pi-pico-asynchronous-programming/
import asyncio
from machine import Pin
green_led_pin = 20
green_led = Pin(green_led_pin, Pin.OUT)
blue_led_pin = 19
blue_led = Pin(blue_led_pin, Pin.OUT)
# Define coroutine function
async def blink_green_led():
while True:
green_led.toggle()
await asyncio.sleep(2)
# Define coroutine function
async def blink_blue_led():
while True:
blue_led.toggle()
await asyncio.sleep(0.5)
# Define the main function to run the event loop
async def main():
# Create tasks for blinking two LEDs concurrently
asyncio.create_task(blink_green_led())
asyncio.create_task(blink_blue_led())
# Create and run the event loop
loop = asyncio.get_event_loop()
loop.create_task(main()) # Create a task to run the main function
loop.run_forever() # Run the event loop indefinitelyComo funciona el código
Echemos un vistazo rápido al código.
Creamos dos corrutinas. Una para cada LED:
# Definir la función de la corrutina
async def blink_green_led():
while True:
green_led.toggle()
await asyncio.sleep(2)
# Definir la función de la corrutina
async def blink_blue_led():
while True:
blue_led.toggle()
await asyncio.sleep(0.5)await asyncio.sleep(0.5).
Creamos otra corrutina llamada main() que sirve como un punto central donde puedes organizar y coordinar la ejecución de esas tareas.
En la corrutina main(), creamos tareas para las funciones blink_green_led() y blink_blue_led() para que se ejecuten de forma concurrente.
# Definir la función principal para ejecutar el bucle de eventos
async def main():
# Crear tareas para hacer parpadear dos LEDs concurrentemente
asyncio.create_task(blink_green_led())
asyncio.create_task(blink_blue_led()Luego, creamos un bucle de eventos (event loop).
loop = asyncio.get_event_loop()El loop.create_task(main()) crea una tarea para ejecutar la función de corrutina main().
loop.create_task(main()) # Crear una tarea para ejecutar la función principalFinalmente, el método run_forever() comenzará a ejecutar el bucle de eventos indefinidamente. El bucle de eventos comprueba continuamente las tareas para ejecutar, las ejecuta de forma concurrente y gestiona su ejecución.
loop.run_forever() # Ejecutar el bucle de eventos indefinidamenteProbando el código
Ejecuta el código anterior en tu Raspberry Pi Pico. El resultado serán dos LEDs parpadeando a ritmos diferentes.




Conclusión
Este es solo un ejemplo sencillo para mostrarte cómo escribir un programa asincrónico. Ahora, deberías entender que, en lugar de simplemente hacer parpadear un LED, puedes realizar tareas más complejas como leer un archivo, solicitar datos de internet, gestionar un servidor web con múltiples clientes y mucho más.
Preguntas frecuentes
¿Qué es la programación asincrónica en MicroPython?
Es una forma de ejecutar varias tareas de manera concurrente, creando la ilusión de multitarea y evitando que el programa se bloquee durante operaciones largas. En MicroPython se implementa con el módulo asyncio.
¿Para qué sirve asyncio en la Raspberry Pi Pico?
Para que el programa pueda estar esperando la respuesta de un servidor y al mismo tiempo comprobar si se presionó un botón o hacer parpadear un LED, en lugar de quedarse detenido hasta que llegue la respuesta.
¿Qué es el event loop?
Es el bucle de eventos que coordina las tareas asincrónicas: decide cuál se ejecuta en cada momento y les va cediendo el control a medida que unas quedan esperando. Es el corazón de asyncio.
¿Cómo se define una función asincrónica?
Con async def en lugar de def. Dentro de ella se usan retrasos asincrónicos en vez de los bloqueantes, de modo que mientras esa función espera, el bucle de eventos pueda ejecutar otras tareas.
¿Es lo mismo asincrónico que multinúcleo?
No. La programación asincrónica reparte el tiempo de un mismo núcleo entre varias tareas que pasan buena parte del tiempo esperando; no ejecuta código en paralelo real. Por eso se habla de la "ilusión" de multitarea.
Aprende esto en un curso
Si prefieres verlo en vivo y con alguien que resuelva tus dudas, estos cursos presenciales de MCI Educación cubren el tema de este tutorial:
- uPython y Electrónica Creativa con Raspberry Pi Pico — nivel inicial, 15 horas presenciales en Santiago
- Domina la Raspberry Pi: Sistemas y Conectividad — nivel intermedio, 18 horas presenciales en Santiago