Project Overview & Difficulty Rating

Building a custom raspberry pi security alarm gives you granular control over motion detection logic, alert routing, and sensor calibration that off-the-shelf commercial systems lock behind proprietary apps. This build uses a passive infrared (PIR) sensor to detect intruders and triggers a local audible alarm while simultaneously publishing an MQTT payload to your home automation broker (like Home Assistant or Mosquitto).

Difficulty Rating: Intermediate (2.5/5)
Estimated Time: 45 minutes (hardware) + 30 minutes (software/config)
Target Board: Raspberry Pi 4 Model B (4GB) running Raspberry Pi OS Bookworm (64-bit). Code is fully forward-compatible with the Raspberry Pi 5.

Hardware Spec Sheet & Parts List

Sourcing the right variants matters here. The HC-SR501 is notorious for output voltage spikes that can fry a Pi's GPIO pins if wired directly. We use a voltage divider to step the logic HIGH signal down to a safe 3.0V.

Component Exact Variant / Spec Est. Cost (2026)
Microcontroller Raspberry Pi 4 Model B (4GB RAM) $55.00
Motion Sensor HC-SR501 PIR (with Fresnel lens dome) $2.50
Audible Alert KY-012 5V Active Buzzer module $1.50
Resistors 1x 1kΩ, 1x 2kΩ (1/4W carbon film) $0.10
Misc Half-size breadboard, 22 AWG jumper wires $5.00

Wiring the PIR Sensor and Buzzer

The HC-SR501 requires 5V for stable operation, but its OUT pin swings to roughly 4.5V when triggered. Feeding 4.5V into a Raspberry Pi GPIO pin (which expects 3.3V) will degrade the SoC over time or cause immediate latch-up failure. We solve this with a simple resistor voltage divider.

⚠️ Safety Callout: Always power down the Pi and disconnect the USB-C supply before modifying breadboard wiring. A slipped jumper wire bridging 5V to a GPIO pin while the system is live will instantly destroy the BCM2711 SoC.

Pin Mapping Table

Component Pin Raspberry Pi GPIO / Power Physical Pin #
PIR VCC 5V Power Pin 2
PIR GND Ground Pin 6
PIR OUT 1kΩ Resistor (in series) → Node Breadboard Rail
Voltage Divider Node GPIO 17 (with 2kΩ pull-down to GND) Pin 11
Buzzer + (VCC) GPIO 27 Pin 13
Buzzer - (GND) Ground Pin 14

Numbered Wiring Steps:

  1. Place the 1kΩ and 2kΩ resistors on the breadboard so they share a common center node.
  2. Connect the PIR OUT pin to the free leg of the 1kΩ resistor.
  3. Connect the free leg of the 2kΩ resistor to the Pi's Ground (Pin 6).
  4. Run a jumper from the center node (where the two resistors meet) to GPIO 17 (Pin 11). This yields Vout = 4.5V * (2000 / 3000) = 3.0V, perfectly safe for the Pi.
  5. Wire the KY-012 active buzzer signal pin to GPIO 27 (Pin 13) and its ground to Pin 14.
  6. Connect PIR VCC to Pin 2 (5V) and PIR GND to Pin 6.

Python Control Code with MQTT Fallback

This script uses the gpiozero library, which is the modern standard for Raspberry Pi OS Bookworm, replacing the deprecated RPi.GPIO. It also integrates Eclipse Paho for MQTT publishing. If your MQTT broker is unreachable, the script catches the exception and falls back to local logging so your local siren still functions.

#!/usr/bin/env python3
import time
import logging
import paho.mqtt.client as mqtt
from gpiozero import MotionSensor, Buzzer
from signal import pause

# --- Pin Definitions ---
PIR_PIN = 17
BUZZER_PIN = 27

# --- MQTT Configuration ---
MQTT_BROKER = '192.168.1.50'
MQTT_PORT = 1883
MQTT_TOPIC = 'home/security/alarm/status'

# Setup logging
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(message)s')

# Initialize Hardware
pir = MotionSensor(PIR_PIN, queue_len=5, threshold=0.6)
buzzer = Buzzer(BUZZER_PIN)

# Initialize MQTT Client
mqtt_client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2)
mqtt_connected = False

def on_connect(client, userdata, flags, reason_code, properties):
    global mqtt_connected
    if reason_code == 0:
        mqtt_connected = True
        logging.info('MQTT Connected to broker.')
    else:
        logging.warning(f'MQTT Connection failed with code {reason_code}')

def publish_alert(state):
    payload = 'TRIGGERED' if state else 'CLEAR'
    if mqtt_connected:
        mqtt_client.publish(MQTT_TOPIC, payload, retain=True)
        logging.info(f'MQTT Published: {payload}')
    else:
        logging.info(f'MQTT Fallback Local Log: {payload}')

def alarm_triggered():
    logging.warning('Motion Detected! Sounding alarm.')
    buzzer.on()
    publish_alert(True)

def alarm_cleared():
    logging.info('Motion cleared. Silencing alarm.')
    buzzer.off()
    publish_alert(False)

if __name__ == '__main__':
    try:
        # Attempt MQTT connection with a 3-second timeout
        mqtt_client.on_connect = on_connect
        mqtt_client.connect_async(MQTT_BROKER, MQTT_PORT, 3)
        mqtt_client.loop_start()
    except Exception as e:
        logging.error(f'MQTT Broker unreachable at startup: {e}. Running in local-only mode.')

    # Bind hardware events
    pir.when_motion = alarm_triggered
    pir.when_no_motion = alarm_cleared

    logging.info('Raspberry Pi Security Alarm armed. Waiting for motion...')
    
    try:
        pause()
    except KeyboardInterrupt:
        logging.info('System disarmed by user.')
    finally:
        buzzer.off()
        mqtt_client.loop_stop()
        pir.close()
        buzzer.close()

Debugging: First Three Things to Check

When migrating to Raspberry Pi OS Bookworm or setting up virtual environments, GPIO access behaves differently than it did on Bullseye. If your script crashes immediately, check these ranked causes.

Exact Error String:
gpiozero.exc.BadPinFactory: Unable to load any default pin factory!
  1. Missing Backend in Virtual Environment (Most Likely): If you are running this code inside a Python venv, gpiozero cannot access the system-level GPIO libraries by default. Fix: Activate your venv and install the lgpio backend: pip install rpi-lgpio.
  2. Running on Pi 5 without lgpio: The Raspberry Pi 5 uses a new RP1 southbridge chip. The legacy RPi.GPIO library physically cannot address it, and older pin factories will fail. Fix: Ensure your OS is fully updated (sudo apt update && sudo apt full-upgrade) and rely strictly on gpiozero with rpi-lgpio installed.
  3. Permissions / User Group Issue: Your current user lacks access to the /dev/gpiochip0 character device. Fix: Add your user to the gpio group: sudo usermod -aG gpio $USER, then log out and log back in. Do not run the script with sudo as a shortcut; it breaks MQTT networking and audio routing.

Extending and Simplifying the Build

Depending on your deployment environment, you may need to scale this raspberry pi security alarm up or down.

To Simplify (Desk/Office Alert):
Drop the MQTT broker requirement entirely. Remove the paho-mqtt imports and replace the publish_alert() function with a simple desktop notification using the plyer library (pip install plyer). This turns the build into a localized 'desk intruder' alarm that pops a notification on your Pi's connected monitor.

To Extend (Whole-Home Integration):
Swap the 5V active buzzer for a 5V relay module (like the Songle SRD-05VDC-SL-C). Wire the relay's COM and NO (Normally Open) terminals in series with a 12V commercial piezo siren (e.g., the Piezo Systems PK-EM100). This allows the Pi's low-voltage GPIO to switch a high-decibel, 12V dedicated alarm circuit powered by a separate 12V SLA battery backup, ensuring the siren sounds even if the Pi's 5V USB supply is cut.

Frequently Asked Questions

Can I use a Raspberry Pi Zero 2 W for this security alarm?

Yes, the Raspberry Pi Zero 2 W shares the same BCM2710A1 SoC architecture and GPIO pinout as the Pi 3B/4B. The Python code and wiring diagram remain identical. However, the Zero 2 W only has 512MB of RAM. If you plan to run a local Mosquitto broker and Home Assistant on the same board alongside this script, the 512MB limit will cause swapping and missed motion events. Use the Zero 2 W strictly as an edge node that publishes MQTT data to a more powerful central server.

How do I prevent false alarms from pets with the HC-SR501?

The HC-SR501 detects infrared heat signatures and movement, meaning a large dog walking past it will trigger the alarm just like a human. To solve this physically, mount the sensor upside down or tilt it upward toward the ceiling so the Fresnel lens grid focuses on a 4-to-6-foot height band, bypassing the floor level where pets roam. Alternatively, adjust the 'Sensitivity' potentiometer on the HC-SR501 board counter-clockwise to reduce the detection range from 7 meters down to 2 meters, keeping it focused on doorways rather than open floor space.

Is a Raspberry Pi security alarm reliable enough for a main home system?

For a DIY hobbyist monitoring a shed, garage, or specific interior room, it is highly effective. However, it should not replace a UL-listed, professionally monitored home security system for primary life-safety or insurance compliance. The Pi relies on a 5V USB power supply and standard SD card storage, both of which are vulnerable to power outages and SD card corruption over long-term 24/7 operation. If you deploy this as a primary system, you must add a Pi-specific UPS (like the PiJuice HAT) and configure the OS to boot to RAM or use an NVMe SSD via the PCIe HAT on a Pi 5 to eliminate SD card failure points. Always consult official Raspberry Pi hardware guidelines for industrial deployment limits.