Cubriremos interrupciones externas y de temporizador.

Introducción a las interrupciones
Las interrupciones son útiles para que ciertas acciones ocurran automáticamente en programas de microcontroladores y ayudan a resolver problemas de sincronización. Permiten que la Raspberry Pi Pico responda rápido a eventos externos sin tener que estar revisando constantemente (polling) el estado de un pin o variable.
¿Qué son las interrupciones?
Las interrupciones son señales que detienen temporalmente el flujo normal de ejecución de un programa para atender un evento específico. Cuando ocurre una interrupción, el procesador pausa el programa principal para ejecutar una tarea específica y luego vuelve a la ejecución normal.
Esa tarea se conoce también como rutina de manejo de interrupciones, como muestra la figura siguiente.

Usar interrupciones es especialmente útil para disparar una acción justo cuando se detecta movimiento o se presiona un botón, sin tener que estar revisando constantemente su estado. También sirve para hacer que algo ocurra periódicamente sin estar chequeando el tiempo todo el rato.
Tipos de interrupciones
Interrupciones externas en MicroPython
def handle_interrupt(pin):interrupt_pin = Pin(21, Pin.IN)interrupt_pin.irq(handler=tu_funcion_interrupcion, trigger=Pin.IRQ_FALLING)
Interrupciones externas con un botón (Ejemplos)
Para mostrar cómo manejar interrupciones, vamos a armar proyectos simples con un botón pulsador y un LED. Conecta el botón al GPIO 21 y el LED al GPIO 20.
Materiales que necesitas para estos ejemplos:
-
Raspberry Pi Pico o Raspberry Pi Pico 2
-
LED de 5 mm
-
Resistencia de 220 Ω
-
Botón pulsador
-
Protoboard (breadboard)
-
Cables jumper
Puedes usar los enlaces anteriores o ir directo a nuestra tienda MCIELECTRONICS para encontra todos los componentes.
Diagrama del circuito

Ejemplo 1: Detectar la presión de un botón pulsador
Este es uno de los ejemplos más simples para mostrar cómo funcionan las interrupciones. Copia el siguiente código en Thonny IDE.# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-interrupts-micropython/
from machine import Pin
button = Pin(21, Pin.IN, Pin.PULL_DOWN)
def button_pressed(pin):
print("Button Pressed!")
# Attach the interrupt to the button's rising edge
button.irq(trigger=Pin.IRQ_RISING, handler=button_pressed)button = Pin(21, Pin.IN, Pin.PULL_DOWN)Luego, agregas una interrupción a ese pin así:
button.irq(trigger=Pin.IRQ_RISING, handler=button_pressed)def button_pressed(pin):
print("Button Pressed!")Fíjate que la definición de la función va antes de crear la interrupción. En MicroPython, cualquier función que definas debe estar declarada antes de ser llamada.
Probando el código
Ejecuta el código en tu Raspberry Pi Pico. Cada vez que presiones el botón, verás un mensaje en la consola (Shell).


Ejemplo 2: Contar la cantidad de veces que se presiona el botón
En este ejemplo, vamos a contar cuántas veces se presiona el botón usando una variable global. Esto te ayudará a entender mejor cómo funcionan las variables globales.
# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-interrupts-micropython/
from machine import Pin
button = Pin(21, Pin.IN, Pin.PULL_DOWN)
counter = 0 # Initialize the button press count
def button_pressed(pin):
global counter # Declare variable as global
counter +=1
print("Button Pressed! Count: ", counter)
# Attach the interrupt to the button's rising edge
button.irq(trigger=Pin.IRQ_RISING, handler=button_pressed)En este ejemplo, creamos una variable global llamada counter — que se declara e inicializa fuera de la función button_pressed.
counter = 0 # Initialize the button press countPara usar esa variable dentro de la función, debemos usar la palabra clave global dentro de la función — así, la variable counter se define como global, lo que permite accederla y modificarla tanto dentro como fuera de la función.
Cuando se presiona el botón y se llama a la función button_pressed, la variable global counter se incrementa y se imprime su valor actualizado.
global counter # Declare variable as global
counter +=1
print("Button Pressed! Count: ", counter)NOTA : counter +=1 es una abreviación counter = counter +1
Probando el código
Ejecuta el código anterior en tu Raspberry Pi Pico. Fíjate que en la consola (Shell) se imprimirá la cantidad de veces que presionaste el botón.
Ejemplo 3: Alternar un LED con cada presión del botón
Es parecido al ejemplo anterior, pero además de contar las pulsaciones, aquí también prendemos y apagamos un LED cada vez que presionas el botón.
# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-interrupts-micropython/
from machine import Pin
led = Pin(20, Pin.OUT)
button = Pin(21, Pin.IN, Pin.PULL_DOWN)
counter = 0 # Initialize the button press count
def button_pressed(pin):
global counter # Declare variable as global
counter +=1
print("Button Pressed! Count: ", counter)
# Toggle the LED on each button press
led.value(not led.value())
# Attach the interrupt to the button's rising edge
button.irq(trigger=Pin.IRQ_RISING, handler=button_pressed)led = Pin(20, Pin.OUT)Luego, dentro de la función button_pressed, agregas la instrucción para alternar el estado del LED:
También existen otros sensores como detectores de humo, sensores de lluvia, de nivel de agua y de sonido, entre otros, que envían una señal digital cuando sus lecturas superan cierto umbral.
Detectar cuándo el sensor envía esa señal también se puede lograr con interrupciones, porque así podemos captar ese estado sin necesidad de estar revisando constantemente el valor en un pin GPIO.
Interrupciones de temporizador
Usar interrupciones de temporizador es ideal para que algo ocurra periódicamente o después de un tiempo definido, sin tener que estar chequeando constantemente cuánto tiempo ha pasado.

La clase Timer en MicroPython
El módulomachine de MicroPython incluye una clase llamada Timer que ofrece métodos para ejecutar una función callback periódicamente en un intervalo de tiempo dado, o una sola vez tras un retardo predefinido. Esto es muy útil para programar eventos o tareas periódicas sin tener que estar revisando el tiempo constantemente.
Creando un Timer
my_timer = Timer()Luego, inicializas el temporizador usando el método init() del objeto Timer(), pasando como argumentos el modo, el periodo y la función callback. Ejemplo:
my_timer.init(mode=Timer.PERIODIC, period=1000, callback=timer_callback)Esto crea un temporizador periódico que ejecuta la función timer_callback cada 1000 milisegundos (1 segundo). Puedes cambiar el valor de period por el intervalo que necesites.
Si en lugar de ejecutar la función periódicamente quieres que se ejecute solo una vez después de un tiempo definido, usas el modo Timer.ONE_SHOT así:
my_timer.init(mode=Timer.ONE_SHOT, period=1000, callback=timer_callback)Ejemplo 1: Parpadeo de un LED con un temporizador
En este ejemplo aprenderás a hacer parpadear un LED usando un Timer, para entender cómo funcionan los temporizadores periódicos.
Vamos a hacer parpadear un LED conectado al GPIO 20. Así que conecta un LED en ese pin de tu Raspberry Pi Pico.
Puedes usar este diagrama como referencia:

para hacer parpadear un LED cada medio segundo.
# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-interrupts-micropython/
from machine import Pin, Timer
from time import sleep
# LED pin
led_pin = 20
led = Pin(led_pin, Pin.OUT)
# Callback function for the timer
def toggle_led(timer):
led.value(not led.value()) # Toggle the LED state (ON/OFF)
# Create a periodic timer
blink_timer = Timer()
blink_timer.init(mode=Timer.PERIODIC, period=500, callback=toggle_led) # Timer repeats every half second
# Main loop (optional)
while True:
print('Main Loop is running')
sleep(2)En este código, primero creamos un temporizador llamado blink_timer:
blink_timer = Timer()Luego, inicializamos el temporizador con estos parámetros:
blink_timer.init(mode=Timer.PERIODIC, period=500, callback=toggle_led)Esto significa que el timer llamará a la función toggle_led cada 500 milisegundos, de forma indefinida (o hasta que detengas el programa).
La función toggle_led, como su nombre indica, alterna el estado del LED:



Ejemplo 2: Parpadeo de múltiples LEDs a diferentes frecuencias
Después de probar el ejemplo anterior, ya es fácil entender que si creas varios timers, puedes ejecutar múltiples tareas a diferentes ritmos. En este ejemplo, haremos parpadear dos LEDs distintos: uno cada medio segundo y otro cada dos segundos.
Diagrama del circuito
Conecta dos LEDs a la Raspberry Pi Pico (para distinguirlos, usaremos colores diferentes):
-
LED azul: GPIO 19 → parpadea cada medio segundo.
-
LED verde: GPIO 20 → parpadea cada dos segundos.
Puedes usar el siguiente diagrama como referencia para armar el circuito.
Código
El siguiente código utiliza timers para hacer parpadear dos LEDs distintos a diferentes frecuencias.
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-interrupts-micropython/
from machine import Pin, Timer
from time import sleep
# LEDs
green_led_pin = 19
green_led = Pin(green_led_pin, Pin.OUT)
blue_led_pin = 20
blue_led = Pin(blue_led_pin, Pin.OUT)
# Callback function for the green timer
def toggle_green_led(timer):
green_led.toggle() # Toggle the LED state (ON/OFF)
print('Green LED is: ', green_led.value())
# Callback function for the blue timer
def toggle_blue_led(timer):
blue_led.toggle() # Toggle the LED state (ON/OFF)
print('Blue LED is: ', blue_led.value())
# Create periodic timers
green_timer = Timer()
blue_timer = Timer()
# Init the timers
green_timer.init(mode=Timer.PERIODIC, period=500, callback=toggle_green_led) # Timer repeats every 0.5 second
blue_timer.init(mode=Timer.PERIODIC, period=2000, callback=toggle_blue_led) # Timer repeats every 2 seconds
# Main loop (optional)
while True:
print('Main Loop is running')
sleep(2)green_timer = Timer()
blue_timer = Timer()# El temporizador se repite cada 0.5 segundos
green_timer.init(mode=Timer.PERIODIC, period=500, callback=toggle_green_led)
# El temporizador se repite cada 2 segundos
blue_timer.init(mode=Timer.PERIODIC, period=2000, callback=toggle_blue_led)# Función de callback para el temporizador del LED verde
def toggle_green_led(timer):
green_led.toggle() # Cambia el estado del LED (ENCENDIDO/APAGADO)
print('El LED verde está: ', green_led.value())
# Función de callback para el temporizador del LED azul
def toggle_blue_led(timer):
blue_led.toggle() # Cambia el estado del LED (ENCENDIDO/APAGADO)
print('El LED azul está: ', blue_led.value())Probando el código
Ejecuta el código anterior en la Raspberry Pi Pico. Notarás que los dos LEDs parpadearán a diferentes frecuencias.




Ejemplo 3: Eliminar el rebote de un botón usando un temporizador
Como mencionamos antes, podemos usar temporizadores para eliminar el rebote de un botón y así evitar que se registren pulsaciones falsas. Hay muchas formas de hacer debounce en un botón, y el ejemplo que sigue es solo una de varias posibilidades.# Rui Santos & Sara Santos - Random Nerd Tutorials
# Complete project details at https://RandomNerdTutorials.com/raspberry-pi-pico-interrupts-micropython/
from machine import Pin, Timer
led = Pin(20, Pin.OUT)
button = Pin(21, Pin.IN, Pin.PULL_DOWN)
counter = 0 # Initialize the button press count
debounce_timer = None
def button_pressed(pin):
global counter, debounce_timer # Declare variables as global
if debounce_timer is None:
counter += 1
print("Button Pressed! Count: ", counter)
# Toggle the LED on each button press
led.toggle()
# Start a timer for debounce period (e.g., 200 milliseconds)
debounce_timer = Timer()
debounce_timer.init(mode=Timer.ONE_SHOT, period=200, callback=debounce_callback)
def debounce_callback(timer):
global debounce_timer
debounce_timer = None
# Attach the interrupt to the button's rising edge
button.irq(trigger=Pin.IRQ_RISING, handler=button_pressed)Como ya conoces la mayor parte del código, nos enfocaremos solo en las partes relevantes para este ejemplo.
Este ejemplo usa un timer one-shot llamado debounce_timer, que se inicia cada vez que se presiona el botón, con un período de debounce de 200 milisegundos.
debounce_timer.init(mode=Timer.ONE_SHOT, period=200, callback=debounce_callback)Como en ejemplos anteriores, asociamos una interrupción al pin del botón que dispara la función button_pressed en modo rising (cuando se presiona el botón):
button.irq(trigger=Pin.IRQ_RISING, handler=button_pressed)button_pressed, que incrementa el contador, alterna el LED y arranca el timer one-shot para debounce:
counter += 1
print("Button Pressed! Count: ", counter)
led.toggle() # Alterna el LED con cada pulsación
debounce_timer = Timer()
debounce_timer.init(mode=Timer.ONE_SHOT, period=200, callback=debounce_callback)La función debounce_callback se llama cuando expira el timer one-shot, y reinicia el valor de debounce_timer a None:
Ejecuta el código en tu Raspberry Pi Pico y presiona el botón varias veces. Verás que ya no se registran pulsaciones falsas. Si siguen apareciendo, aumenta el período de debounce (por ejemplo, a 300 ms):
Ejemplo 4: Interrupciones y temporizadores con un sensor de movimiento PIREn este ejemplo, ejemplificaremos el uso de temporizadores de un solo disparo (single-shot) con un sensor de movimiento PIR.
Construiremos un proyecto simple con un sensor PIR. Cada vez que se detecte movimiento, se encenderá un LED durante 20 segundos. Pasado ese tiempo, el LED se apagará.

El sensor de movimiento PIR
Un sensor de movimiento infrarrojo pasivo (PIR) está diseñado para detectar la radiación infrarroja emitida por objetos dentro de su campo de visión.
Los sensores PIR detectan cambios en la radiación infrarroja, principalmente emitida por seres vivos. Cuando hay movimiento dentro del rango del sensor, se producen fluctuaciones en la radiación infrarroja detectada.
La siguiente imagen muestra el popular sensor de movimiento HC-SR501.

El sensor emite una señal HIGH si detecta movimiento, o LOW si no detecta nada.
La salida digital del sensor PIR puede ser leída por un pin GPIO de la Raspberry Pi Pico, lo que te permite programar acciones específicas según el estado del sensor. En este ejemplo, simplemente encenderemos un LED, pero en la práctica se puede usar para cosas útiles como enviar un correo, activar una alarma, etc.
Un concepto importante sobre los sensores PIR es el tiempo de permanencia (también llamado tiempo de reinicio o retardo del sensor): es la duración durante la cual la salida del sensor se mantiene en HIGH tras detectar movimiento, antes de volver a LOW.

Partes requeridas
Para este ejemplo, usaremos los siguientes componentes:-
Raspberry Pi Pico o Raspberry Pi Pico 2
-
LED de 5 mm
-
Resistor de 220 Ω
-
Sensor de movimiento PIR (Mini AM312)
-
Protoboard (breadboard)
-
Cables jumper
Nota: El sensor Mini AM312 que usamos en este proyecto funciona a 3.3V.
Si usas otro sensor PIR como el HC-SR501, éste funciona a 5V. Puedes modificarlo para operar a 3.3V o alimentarlo desde el pin VBUS, que entrega 5V cuando la Raspberry Pi Pico está conectada por USB a 5V.
Este ejemplo también se puede hacer con un botón en lugar del sensor PIR.
En la siguiente figura mostramos el pinout del sensor Mini AM312. Si usas otro sensor de movimiento, revisa su pinout antes de armar el circuito.

| PIR Motion Sensor | Raspberry Pi Pico |
| GND | GND |
| Data | Any digital pin (example GPIO 21) |
| 3.3V | 3V3(OUT) |
Diagrama del circuito
Conectaremos el pin de datos del sensor PIR al GPIO 21 y el LED al GPIO 20.
Código
El siguiente código configura el sensor de movimiento PIR como una interrupción. Cuando se detecta movimiento, se enciende un LED durante 20 segundos después de la última detección. Pasado ese tiempo, el LED se apaga y el sensor vuelve a estar listo para detectar movimiento nuevamente.
Con este ejemplo verás otra aplicación de los temporizadores one-shot, mientras aprendes a detectar movimiento con sensores PIR.
led_pin = 20
# Set up LED and PIR sensor
led = Pin(led_pin, Pin.OUT)
pir = Pin(pir_pin, Pin.IN)
# Create timer
motion_timer = Timer()
# Create timer
motion = False
motion_printed = False
def handle_motion(pin):
global motion
motion = True
motion_timer.init(mode=Timer.ONE_SHOT, period=20000, callback=turn_off_led)
def turn_off_led(timer):
global motion, motion_printed
led.off() # Turn off the LED
print('Motion stopped!')
motion = False
motion_printed = False
# Attach interrupt to the PIR motion sensor
pir.irq(trigger=Pin.IRQ_RISING, handler=handle_motion)
while True:
if motion and not motion_printed:
print('Motion detected!')
led.on() # Turn on the LED
motion_printed = True
elif not motion:
time.sleep(0.1)
# Other tasks that you might need to do in the loopCómo funciona el código
Comenzamos declarando el LED y el sensor de movimiento PIR en los pines GPIO a los que están conectados.# PIR sensor pin
pir_pin = 21
# LED pin
led_pin = 20
# Set up LED and PIR sensor
led = Pin(led_pin, Pin.OUT)
pir = Pin(pir_pin, Pin.IN)# Crear temporizador
motion_timer = Timer()Declaramos dos variables globales: motion y motion_printed.
-
motionsirve para indicar en todo el código si se detectó movimiento o no. -
motion_printednos permite verificar si el mensaje “¡Movimiento detectado!” ya fue impreso en la consola.
# Crear variables globales
motion = False
motion_printed = Falsehandle_motion
pir.irq(trigger=Pin.IRQ_RISING, handler=handle_motion)Las interrupciones se manejan dentro de las ISR, que es la función que corre cuando ocurre la interrupción (en nuestro caso, handle_motion). Cuando sucede una interrupción, el procesador pausa lo que está haciendo, ejecuta la ISR y luego vuelve al programa principal.
Es buena práctica mantener las ISR lo más pequeñas posibles para que el procesador vuelva rápido a la ejecución principal. La mejor estrategia es solo marcar con una bandera (flag) o contador que la interrupción ocurrió, y que el código principal haga las tareas que correspondan.
En este ejemplo usamos la variable motion como bandera para indicar que hubo movimiento. Luego, el código principal se encargará de prender el LED, imprimir mensajes, etc.
Más detalles sobre ISR los puedes encontrar aquí.
Sigamos con el código. Dentro de la función handle_motion, establecemos la variable global motion en True, para que en todo el código se sepa que se detectó movimiento. Además, inicializamos un timer one-shot que apagará el LED después de 20 segundos, llamando a la función turn_off_led().
def handle_motion(pin):
global motion
motion = True
motion_timer.init(mode=Timer.ONE_SHOT, period=20000, callback=turn_off_led)while, verificamos si se detectó movimiento. Si hubo movimiento y el mensaje aún no se ha imprimido en la consola, entonces imprimimos el mensaje, encendemos el LED y seteamos la variable motion_printed en True.
while True:
if motion and not motion_printed:
print('Motion detected!')
led.on() # Turn on the LED
motion_printed = Trueturn_off_led, que apagará el LED y pondrá las variables globales motion y motion_printed en False.
def turn_off_led(timer):
global motion, motion_printed
led.off() # Turn off the LED
print('Motion stopped!')
motion = False
motion_printed = FalseLa variable motion solo podrá volver a ser True si se detecta movimiento nuevamente y se llama a la función handle_motion.
Hay muchas formas de lograr el mismo resultado; este es solo un ejemplo para mostrarte cómo puedes usar temporizadores one-shot en tu código.
Probando el código
Ejecuta el código anterior en tu Raspberry Pi Pico. Mueve la mano frente al sensor de movimiento PIR.

Después de 20 segundos, el LED se apagará.

Para cerrar
En esta guía aprendiste sobre interrupciones en la Raspberry Pi Pico programada con MicroPython. Cubrimos interrupciones externas y temporizadores (timer interrupts).
Esperamos que esta guía y los ejemplos te hayan sido útiles y que puedas aplicar estos conceptos en tus proyectos.
Preguntas frecuentes
¿Qué es una interrupción en un microcontrolador?
Es un mecanismo que hace que el programa deje lo que está haciendo y atienda un evento de inmediato. Evita tener que consultar constantemente un pin para saber si pasó algo.
¿Qué tipos de interrupciones maneja la Raspberry Pi Pico?
Externas, que se disparan por un cambio en un pin —por ejemplo al presionar un botón o al activarse un sensor PIR—, y de temporizador, que se disparan cada cierto intervalo de tiempo.
¿Para qué sirve una interrupción con un sensor PIR?
Para que la placa reaccione en el momento exacto en que se detecta movimiento, sin tener que estar leyendo el sensor en cada vuelta del bucle principal. El código queda libre para hacer otras cosas.
¿Qué necesito para usar interrupciones en la Pico?
Tener el firmware de MicroPython instalado en la placa, y los componentes del ejemplo: un botón pulsador para las interrupciones externas y un sensor de movimiento PIR para el segundo caso.
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
Rebote del botón (Button Bouncing)
