Correo: [email protected] - Teléfono: +56979962128

En esta guía, te mostraremos cómo manejar interrupciones con la Raspberry Pi Pico usando MicroPython y cómo crear proyectos ejemplos con un botón pulsador y un sensor de movimiento PIR.
Cubriremos interrupciones externas y de temporizador.  
Raspberry Pi Pico with Interrupts: External and Timer Interrupts (MicroPython)
 

Requisitos previos – Firmware de MicroPython
Para seguir este tutorial, necesitas tener instalado el firmware de MicroPython en tu placa Raspberry Pi Pico.
También necesitas un IDE para escribir y cargar el código en la placa.

El IDE recomendado para MicroPython en la Raspberry Pi Pico es Thonny IDE.

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.

How interrupts work

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

 

Existen dos tipos principales: interrupciones externas e interrupciones temporizadas.

  • Interrupciones externas: Se activan por señales externas, como presionar un botón o detectar un sensor. Son hardware-based y están asociadas a un pin GPIO específico. Cuando cambia el estado del pin, se dispara una tarea.

  • Interrupciones temporizadas (timers): Se activan según intervalos de tiempo, permitiendo ejecutar acciones periódicas. Usan el temporizador hardware del RP2040 (o RP2350 según la versión de la Pico) para llamar funciones a intervalos regulares.

 

Interrupciones externas en MicroPython

 

Para configurar una interrupción en MicroPython, debes seguir estos pasos:

  1. Definir una función para manejar la interrupción

La función que maneja la interrupción debe ser lo más simple posible, para que el procesador vuelva rápido a la ejecución del programa principal. La mejor forma es usar una variable global que indique que la interrupción ocurrió.

Esta función debe aceptar un parámetro de tipo Pin, que es el pin GPIO que causó la interrupción. Este parámetro se pasa automáticamente a la función callback.

Estos conceptos se entenderán mejor cuando probemos ejemplos prácticos

def handle_interrupt(pin):
  2. Configura el pin de la interrupción como entrada. Por ejemplo:  
interrupt_pin = Pin(21, Pin.IN)
  3.Asocia una interrupción a ese pin llamando al método irq():  
interrupt_pin.irq(handler=tu_funcion_interrupcion, trigger=Pin.IRQ_FALLING)
  El método irq() acepta los siguientes argumentos:  

trigger: define el modo de activación de la interrupción. Hay 4 condiciones posibles:

  • Pin.IRQ_FALLING: la interrupción se activa cuando el pin cambia de ALTO a BAJO.

  • Pin.IRQ_RISING: la interrupción se activa cuando el pin cambia de BAJO a ALTO.

  • Pin.IRQ_LOW_LEVEL: la interrupción se activa mientras el pin esté en nivel BAJO.

  • Pin.IRQ_HIGH_LEVEL: la interrupción se activa mientras el pin esté en nivel ALTO.


handler: es la función que se llama cuando se detecta la interrupción, por ejemplo, una función llamada handle_interrupt().


La siguiente imagen te ayudará a entender mejor los diferentes modos de activación (trigger).

Interrupt modes

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

 
Raspberry Pi Pico Pushbutton LED Circuit
 

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)
  En este ejemplo, creas un objeto de entrada llamado button.
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)

Esto significa que cuando la señal del botón pase de BAJO a ALTO (flanco de subida), se ejecutará la función button_pressed.

La función button_pressed simplemente imprime en la consola (Shell) que el botón fue presionado.

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).

Raspberry Pi Pico Detect a Pushbutton Press
Raspberry Pi Pico Detect a Pushbutton Press - Micropython Shell Thonny IDE

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 count

Para 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.
pushbutton counter Raspberry Pi Pico Micropython Thonny IDE

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)
En este ejemplo, solo necesitas declarar un nuevo objeto Pin para el LED, en este caso en el GPIO 20:
led = Pin(20, Pin.OUT)
 

Luego, dentro de la función button_pressed, agregas la instrucción para alternar el estado del LED:

led.value(not led.value())
Raspberry Pi Pico Pushbutton LED on Rebote del botón (Button Bouncing)

Seguramente notaste que a veces, al presionar el botón una sola vez, el contador suma más de una pulsación. Esto se llama rebote mecánico y es súper común en botones físicos como los pushbuttons.

debounce a pushbutton

Esto sucede porque los contactos eléctricos dentro del botón se conectan y desconectan rápidamente antes de estabilizarse, lo que hace que el sistema registre múltiples eventos de pulsación, generando un conteo erróneo. Para evitar este problema, podemos aplicar técnicas de debounce usando retardos (delays) o interrupciones temporizadas (timer interrupts). Más adelante veremos cómo usar interrupciones de temporizador y eventos para hacer debounce en un botón.

Otras aplicaciones

Además de los botones, las interrupciones externas sirven para un montón de aplicaciones en la Raspberry Pi Pico, como entradas de sensores, codificadores rotativos y otros escenarios donde se necesitan respuestas en tiempo real.

Un caso muy común son los sensores de movimiento PIR. Estos sensores pasan a un estado activado (HIGH) por unos segundos después de detectar movimiento, así que usar una interrupción en modo rising es una excelente manera de detectar cuando el sensor detecta movimiento. Raspberry Pi Pico with a PIR motion sensor

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.

 
Timer Interrupts
   

La clase Timer en MicroPython

  El módulo machine 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

Para crear un temporizador, llamas al constructor Timer() así:

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)
Esta línea configura el temporizador para que ejecute la función timer_callback una sola vez, tras 1000 milisegundos.

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.

Diagrama del circuito

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:

RPi Pico Connected to an LED - schematic diagram

Código

El siguiente ejemplo usa la clase Timer

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:

# Función callback para el timer
def toggle_led(timer):
led.value(not led.value()) # Cambia el estado del LED (ON/OFF)
Las funciones callback para eventos de timer deben aceptar un argumento (en este caso, timer), que es el objeto Timer que se pasa automáticamente cuando se dispara el evento. Aunque no uses ese argumento dentro de la función, debe estar presente. Con los timers, puedes ejecutar otras tareas en el loop principal sin que interfieran entre sí. Por ejemplo, aquí imprimiremos un mensaje cada dos segundos mientras el LED parpadea.
while True:
    print('Main Loop is running')
    sleep(2)
Probando el código

Con un LED conectado al GPIO 20, ejecuta el código anterior en tu placa.

Verás el mensaje “Main Loop is running” cada dos segundos en la consola (Shell), mientras el LED parpadea cada medio segundo simultáneamente.8

RPi Pico main loop running on Thonny IDE

RPi Pico Blinking LED 1RPi Pico Blinking LED 1

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.

Raspberry Pi Pico Wiring Two LEDs

 

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)
En este código, creamos dos temporizadores diferentes, uno para cada LED:
green_timer = Timer()
blue_timer = Timer()
 

Luego, llamamos a las funciones callback correspondientes en intervalos diferentes:

# 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)
 

Las funciones callback simplemente alternan el valor actual del 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())
La función toggle(): en MicroPython hay un método llamado toggle() que puedes usar en objetos Pin configurados como salida, como por ejemplo LEDs. Este cambia el estado de un pin digital de su estado actual al opuesto.

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.
RPi Pico LEDs blinking at different frequencies
RPi Pico LEDs blinking at different frequencies
     
RPi Pico LEDs blinking at different frequencies
RPi Pico LEDs blinking at different frequencies
          Al mismo tiempo, recibirás un mensaje del while loop cada dos segundos. Esto muestra que las otras tareas no interfieren con nuestro bucle.
RPi Pico multiple timers and loop running
     

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)
Cuando se presiona el botón, se ejecuta 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:

def debounce_callback(timer):
global debounce_timer
debounce_timer = None
Si el timer no ha expirado, y se detecta otra pulsación, no se contabilizará porque debounce_timer aún no es None:
if debounce_timer is None:
 

Uso de variables globales

Declaramos las variables como globales para poder acceder a ellas desde cualquier parte del código, incluyendo dentro de las funciones:

global counter, debounce_timer # Declarar variables como globales
 

¿Qué significa None?

En Python y MicroPython, None es un marcador para indicar la ausencia de un valor válido. Aquí lo usamos para manejar el estado del timer de debounce.

Al inicio:

debounce_timer = None
 

Esto indica que no hay un timer activo.

En la función button_pressed, esta condición verifica si no hay timer activo para procesar la pulsación:

if debounce_timer is None:
Si no hay timer activo, se ejecutan las acciones y se inicia uno nuevo:
debounce_timer = Timer()
debounce_timer.init(mode=Timer.ONE_SHOT, period=200, callback=debounce_callback)
Cuando el timer termina, se llama a debounce_callback que vuelve a poner el timer en None, indicando que el período de debounce terminó.
defdebounce_callback(timer):
    global debounce_timer
    debounce_timer =None
 
 

Probando el código

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):

debounce_timer.init(mode=Timer.ONE_SHOT, period=200, callback=debounce_callback)
Raspberry Pi Pico Pushbutton LED on RPi Pico Pushbutton Debounce with Timer

Ejemplo 4: Interrupciones y temporizadores con un sensor de movimiento PIR

En 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á.

Using a PIR motion sensor for LED control

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.

HC-SR501 PIR Motion Sensor

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.

PIR motion sensor how it works

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.

 

Mini pir motion sensor pinout
La siguiente tabla muestra las conexiones entre el sensor de movimiento PIR y la Raspberry Pi Pico:
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.
RPi Pico LED Pushbutton Circuit
 

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 loop
 

Có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)
  Creamos un temporizador que será responsable de apagar el LED después de 20 segundos desde que se detectó movimiento.  
# Crear temporizador
motion_timer = Timer()
 

Declaramos dos variables globales: motion y motion_printed.

  • motion sirve para indicar en todo el código si se detectó movimiento o no.

  • motion_printed nos permite verificar si el mensaje “¡Movimiento detectado!” ya fue impreso en la consola.

# Crear variables globales
motion = False
motion_printed = False
Adjuntamos una interrupción al sensor PIR en modo rising, lo que significa que cuando se detecta movimiento se ejecuta la función handle_motion
 
pir.irq(trigger=Pin.IRQ_RISING, handler=handle_motion)
 
Consideraciones al escribir ISR (rutinas de servicio de interrupción)

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)
En el bucle 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 = True
Después de los 20.000 milisegundos, se ejecutará la función turn_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 = False
 

La 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.
RPi Pico Testing a PIR Motion Sensor

Se imprimirá un mensaje en la consola y se encenderá un LED durante 20 segundos.

RPi Pico - Testing the PIR Motion Sensor - Thonny IDE Shell

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

RPi Pico Testing a PIR Motion Sensor

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: