Project 4.5: "PIR Motion Alarm"
What you’ll learn
- Goal 1: Detect motion using a PIR sensor as a digital input pin.
- Goal 2: Trigger visual and audible alarms with onboard LED and MIDI music blocks.
- Goal 3: Adjust activation time (how long the alarm stays active) with simple timing.
- Goal 4: Run continuous monitoring without freezing the loop.
- Goal 5: Send notification messages via Bluetooth when motion is detected.
Blocks glossary
- InOut → machine.Pin(pin, machine.Pin.IN): Configura un pin como entrada digital para leer el PIR.
- InOut → machine.Pin(pin, machine.Pin.OUT), .value(v): Controla el LED u otros actuadores visuales.
- external actuador → music.MIDI(pin): Crea salida de audio;
midi.play(...)ymidi.pitch_time(freq, ms)para alarma. - bluetooth → ble_peripheral.BLESimplePeripheral(name): Envía mensajes de notificación.
- serial port → print(…): Registra eventos en el monitor serial.
- control → while True: / if: / time.sleep_ms(ms): Estructura el bucle y los tiempos de activación.
What you need
| Part | How many? | Pin connection (R32) |
|---|---|---|
| D1 R32 | 1 | USB cable |
| PIR motion sensor | 1 | Signal → Pin 26, VCC 5V, GND |
| LED (onboard or external) | 1 | Onboard LED → Pin 13 (example) |
| Buzzer (audio via MIDI pin) | 1 | Signal → Pin 26 (example MIDI) |
| Bluetooth (built‑in) | 1 | Internal |
- Share GND between the R32 and the PIR sensor.
- Place the PIR facing the area to monitor; avoid direct sunlight for reliability.
Before you start
- Connect the PIR signal to Pin 26, LED to Pin 13 if external (or use onboard LED), and buzzer to the chosen MIDI pin (example 26).
- Open the serial monitor to see printed logs.
- Quick test:
print("Ready!") # Confirmar que el sistema está listo en el monitor serial
Microprojects 1–5
Microproject 4.5.1 – Basic motion detection
import machine # Bloque: importar librería de pines
import time # Bloque: importar tiempo para pausas
pir = machine.Pin(26, machine.Pin.IN) # Bloque: configurar pin 26 como entrada para PIR
print("[PIR] Entrada en pin 26 lista") # Bloque: confirmar configuración en serial
state = pir.value() # Bloque: leer estado actual (0 sin movimiento, 1 movimiento)
print("[PIR] Estado inicial:", state) # Bloque: mostrar lectura inicial
time.sleep_ms(300) # Bloque: pequeña pausa para estabilidad del sensor
state = pir.value() # Bloque: leer nuevamente para confirmar
print("[PIR] Estado tras pausa:", state) # Bloque: mostrar segunda lectura
Reflection: Confirmaste que el PIR entrega 0/1 y que la lectura es estable con una pequeña pausa.
Challenge: Imprime “MOTION” cuando sea 1 y “CLEAR” cuando sea 0.
Microproject 4.5.2 – Visual and audible alarm
import machine # Bloque: importar pines para LED
import music # Bloque: importar módulo de música MIDI
import time # Bloque: importar tiempo
pir = machine.Pin(26, machine.Pin.IN) # Bloque: PIR en pin 26 como entrada
led = machine.Pin(13, machine.Pin.OUT) # Bloque: LED en pin 13 como salida (visual)
midi = music.MIDI(26) # Bloque: salida MIDI en pin 26 (audio del buzzer)
print("[Alarm] PIR=26 LED=13 MIDI=26") # Bloque: confirmar conexiones
if pir.value() == 1: # Bloque: si hay movimiento
led.value(1) # Bloque: encender LED (alarma visual)
midi.play(midi.DADADADUM) # Bloque: reproducir patrón musical de alarma
print("[Alarm] Movimiento detectado!") # Bloque: log de evento
else: # Bloque: si no hay movimiento
led.value(0) # Bloque: apagar LED (sin alarma)
print("[Alarm] Área despejada") # Bloque: log de estado
Reflection: Conectaste la detección a una alarma visual y sonora inmediata.
Challenge: Si detección es 1, añade también un pitido corto: midi.pitch_time(880, 300).
Microproject 4.5.3 – Adjustable activation time
import machine # Bloque: importar pines
import music # Bloque: importar música
import time # Bloque: importar tiempo
pir = machine.Pin(26, machine.Pin.IN) # Bloque: PIR en pin 26 (entrada)
led = machine.Pin(13, machine.Pin.OUT) # Bloque: LED en pin 13 (salida)
midi = music.MIDI(26) # Bloque: MIDI en pin 26 (buzzer)
ACTIVATION_MS = 3000 # Bloque: duración de la alarma en milisegundos
if pir.value() == 1: # Bloque: si hay movimiento
led.value(1) # Bloque: encender LED
midi.pitch_time(660, 300) # Bloque: pitido de inicio
print("[Alarm] Activada por", ACTIVATION_MS, "ms") # Bloque: log de activación
time.sleep_ms(ACTIVATION_MS) # Bloque: mantener alarma activa por el tiempo definido
led.value(0) # Bloque: apagar LED tras la duración
print("[Alarm] Desactivada") # Bloque: log de fin de alarma
else: # Bloque: si no hay movimiento
led.value(0) # Bloque: asegurar LED apagado
print("[Alarm] Sin movimiento") # Bloque: log de estado
Reflection: Aprendiste a controlar cuánto tiempo permanece activa la alarma después de detectar.
Challenge: Cambia ACTIVATION_MS a 1000/5000 y observa la diferencia en reacción y duración.
Microproject 4.5.4 – Continuous monitoring mode
import machine # Bloque: importar pines
import time # Bloque: importar tiempo
pir = machine.Pin(26, machine.Pin.IN) # Bloque: PIR en pin 26 entrada
led = machine.Pin(13, machine.Pin.OUT) # Bloque: LED en pin 13 salida
print("[Monitor] Iniciando vigilancia continua") # Bloque: log de arranque
while True: # Bloque: bucle infinito
if pir.value() == 1: # Bloque: si detecta movimiento
led.value(1) # Bloque: encender LED
print("[Monitor] Movimiento!") # Bloque: log de evento
time.sleep_ms(300) # Bloque: breve pausa para no saturar
else: # Bloque: si no detecta movimiento
led.value(0) # Bloque: apagar LED
time.sleep_ms(150) # Bloque: pausa más corta para ahorrar energía
Reflection: Mantienes una vigilancia estable sin inundar el serial ni bloquear el sistema.
Challenge: Agrega un “heartbeat” cada 2 s: imprime “[Monitor] OK” periódicamente.
Microproject 4.5.5 – Integration with notification system
import machine # Bloque: importar pines
import ble_peripheral # Bloque: importar periférico Bluetooth
import time # Bloque: importar tiempo
pir = machine.Pin(26, machine.Pin.IN) # Bloque: PIR en pin 26 entrada
ble_p = ble_peripheral.BLESimplePeripheral("PIR-R32") # Bloque: crear periférico BLE con nombre
print("[Notify] BLE 'PIR-R32' listo") # Bloque: confirmar BLE
while True: # Bloque: bucle continuo
if pir.value() == 1: # Bloque: si hay movimiento
ble_p.send("EVENT:MOTION") # Bloque: enviar notificación al teléfono/PC
print("[Notify] EVENT:MOTION") # Bloque: reflejar en serial
time.sleep_ms(500) # Bloque: pausa para evitar spam
else: # Bloque: si no hay movimiento
time.sleep_ms(200) # Bloque: pequeña pausa de vigilancia
Reflection: Tu sistema ahora avisa por Bluetooth cuando detecta movimiento.
Challenge: Envía también “EVENT:CLEAR” tras 2 segundos sin detección.
Main project
PIR motion alarm with visual/audio alerts, adjustable timing, continuous monitoring, and Bluetooth notifications
- Detection: PIR como entrada digital en Pin 26.
- Alarms: LED y buzzer con bloques oficiales.
- Timing: Activación ajustable para duración de la alarma.
- Monitoring: Bucle continuo que no bloquea.
- Notifications: Mensajes BLE al teléfono/PC en cada evento.
import machine # Bloque: importar pines y hardware
import music # Bloque: importar módulo de música MIDI
import ble_peripheral # Bloque: importar periférico Bluetooth
import time # Bloque: importar tiempo
pir = machine.Pin(26, machine.Pin.IN) # Bloque: PIR en pin 26 como entrada
led = machine.Pin(13, machine.Pin.OUT) # Bloque: LED en pin 13 como salida
midi = music.MIDI(26) # Bloque: salida MIDI en pin 26 (buzzer)
ble_p = ble_peripheral.BLESimplePeripheral("PIR-R32") # Bloque: periférico BLE con nombre
print("[Main] PIR=26 LED=13 MIDI=26 BLE=PIR-R32") # Bloque: resumen de conexiones
ACTIVATION_MS = 3000 # Bloque: duración de alarma en ms (ajustable)
while True: # Bloque: bucle principal
if pir.value() == 1: # Bloque: si el PIR detecta movimiento
led.value(1) # Bloque: encender LED (alarma visual)
midi.pitch_time(880, 300) # Bloque: pitido corto de alarma
ble_p.send("EVENT:MOTION") # Bloque: enviar notificación Bluetooth
print("[Main] Motion! Alarm for", ACTIVATION_MS, "ms") # Bloque: log detallado
time.sleep_ms(ACTIVATION_MS) # Bloque: mantener alarma durante ACTIVATION_MS
led.value(0) # Bloque: apagar LED tras periodo de activación
print("[Main] Alarm cleared") # Bloque: log de fin de alarma
time.sleep_ms(300) # Bloque: breve pausa para evitar reactivación inmediata
else: # Bloque: si no hay movimiento
led.value(0) # Bloque: asegurar LED apagado
time.sleep_ms(150) # Bloque: cadencia de vigilancia ligera
External explanation
Este proyecto usa solo bloques oficiales: el PIR como entrada digital, LED como salida, MIDI para sonido y BLE para notificaciones. La duración de la alarma se controla con pausas temporales, y el monitoreo continuo evita saturar el sistema. Los logs por serial explican cada estado para que el estudiante nunca se pierda.
Story time
Tu robot se convierte en un guardián amable: cuando alguien pasa, enciende su luz, emite un pitido y te avisa. Cuando todo vuelve a estar tranquilo, respira y sigue vigilando en silencio.
Debugging (2)
Debugging 4.5.A – False detections
# Usa una pequeña pausa de confirmación antes de activar la alarma
import time # Bloque: importar tiempo
# Ejemplo de confirmación:
# if pir.value() == 1:
# time.sleep_ms(200) # Bloque: esperar 200 ms
# if pir.value() == 1: # Bloque: segunda verificación
# # activar alarma # Bloque: solo si persiste
print("[Debug] Doble verificación aplicada") # Bloque: informar en serial
Debugging 4.5.B – It does not detect movement
# Revisa alimentación y orientación del PIR
# Asegura que el pin esté correctamente configurado como entrada
import machine # Bloque: importar pines
pir = machine.Pin(26, machine.Pin.IN) # Bloque: configurar entrada
print("[Debug] PIR en 26, prueba lectura:", pir.value()) # Bloque: lectura de prueba
# Ubica el PIR sin luz directa del sol y con campo visual despejado
Final checklist
- El PIR lee 0/1 correctamente en el pin 26.
- La alarma visual (LED) y sonora (MIDI) se activan ante movimiento.
- La duración de activación se ajusta con una variable en milisegundos.
- El monitoreo continuo mantiene el sistema estable.
- Las notificaciones BLE se envían cuando hay movimiento.
Extras
- Student tip: Ajusta ACTIVATION_MS para diferentes escenarios (puerta vs pasillo).
- Instructor tip: Pide a los alumnos que diseñen mensajes BLE claros (EVENT:MOTION, EVENT:CLEAR).
- Glossary:
- PIR: Sensor de infrarrojo pasivo que detecta cambios en movimiento/calor.
- MIDI: Bloques de música para emitir tonos y patrones.
- BLE: Bluetooth de baja energía para notificaciones.
- Mini tips:
- Evita colocar el PIR frente a ventanas soleadas.
- Usa pausas cortas tras la alarma para evitar activaciones encadenadas.
- Mantén los mensajes de BLE breves para que sean fáciles de leer.

