Project Overview & Difficulty Rating
A reliable raspberry pi security alarm system bridges the gap between simple hobby electronics and practical home automation. By pairing a passive infrared (PIR) sensor with the Pi's GPIO and an MQTT broker, you can create a localized motion detector that triggers a physical siren while simultaneously pushing state changes to a dashboard like Home Assistant or Node-RED.
| Parameter | Value |
|---|---|
| Target Board | Raspberry Pi 4 Model B (4GB) or Pi 5 |
| OS Requirement | Raspberry Pi OS (64-bit, Bookworm or newer) |
| Difficulty | Intermediate |
| Estimated Build Time | 2 Hours |
| Primary Language | Python 3.11+ |
This guide targets the Raspberry Pi 4 Model B (4GB) running the 64-bit Bookworm release. The code is fully forward-compatible with the Raspberry Pi 5, provided you address the legacy GPIO library dependencies detailed in the debugging section.
Hardware BOM & Pin Mapping
Sourcing the right components prevents the most common failure modes in DIY alarm builds. The HC-SR501 is the industry-standard hobbyist PIR, but its 3.3V logic output requires careful handling when interfacing with the Pi's GPIO.
Bill of Materials
- Raspberry Pi 4 Model B (4GB) (~$55) - The 4GB variant provides enough headroom to run a local MQTT broker (Mosquitto) alongside the alarm script.
- HC-SR501 PIR Motion Sensor (~$3) - Ensure you get the version with the BISS0001 IC.
- 5V Active Piezo Buzzer (~$2) - Must be active (built-in oscillator). A passive buzzer will only click.
- Logic Level Converter or 10kΩ/22kΩ Resistor Divider - The HC-SR501 outputs 3.3V natively on some boards, but up to 5V on others. A voltage divider protects the Pi's GPIO.
- Half-size Breadboard & Jumper Wires - 22 AWG solid core.
GPIO Pin Mapping (BCM Numbering)
| Component | Component Pin | Pi 4 Physical Pin | Pi BCM GPIO | Notes |
|---|---|---|---|---|
| HC-SR501 | VCC | 2 | 5V Power | Requires 4.5V - 20V input |
| HC-SR501 | OUT | 11 | GPIO 17 | Route through voltage divider if OUT > 3.3V |
| HC-SR501 | GND | 6 | Ground | Common ground with Pi |
| Piezo Buzzer | VCC (+) | 13 | GPIO 27 | Drive via NPN transistor if drawing >16mA |
| Piezo Buzzer | GND (-) | 9 | Ground | Common ground |
Wiring the PIR Sensor and Piezo Buzzer
- De-energize the Pi. Unplug the USB-C power supply before touching the GPIO header. Backfeeding 5V into a GPIO pin while the board is live can fry the SoC.
- Mount the HC-SR501. Remove the white Fresnel lens dome. Connect the 5V, GND, and OUT pins. Replace the dome.
- Build the Voltage Divider. If your multimeter reads >3.3V on the PIR OUT pin when triggered, place a 10kΩ resistor between PIR OUT and GPIO 17, and a 22kΩ resistor between GPIO 17 and GND. This drops a 5V signal down to a safe ~3.4V.
- Wire the Buzzer. Connect the buzzer's positive lead to GPIO 27 and the negative lead to GND. Note: Most 5V active buzzers draw 30mA, which exceeds the safe continuous draw of a single Pi GPIO pin (16mA recommended). For a permanent install, switch the buzzer via a 2N2222 NPN transistor with a 1kΩ base resistor.
- Verify Connections. Double-check physical pin numbers against the BCM mapping table above. Physical Pin 11 is BCM 17; Physical Pin 13 is BCM 27.
Python Control Script with MQTT Integration
This script uses RPi.GPIO for hardware interrupts and paho-mqtt for network alerts. We use edge-detection interrupts (add_event_detect) rather than a blocking while True polling loop, which keeps CPU usage near zero.
import RPi.GPIO as GPIO
import paho.mqtt.client as mqtt
import time
import sys
import logging
# --- Configuration & Pin Definitions ---
PIR_PIN = 17 # BCM 17 (Physical 11)
BUZZER_PIN = 27 # BCM 27 (Physical 13)
ALARM_DURATION = 3 # Seconds to sound buzzer
MQTT_BROKER = '192.168.1.50'
MQTT_PORT = 1883
MQTT_TOPIC = 'home/security/motion'
# --- Logging Setup ---
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
# --- MQTT Client Initialization (Handles Paho v1 and v2 API changes) ---
try:
# Paho MQTT v2.0+
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id='pi_alarm_01')
except AttributeError:
# Paho MQTT v1.x fallback
client = mqtt.Client(client_id='pi_alarm_01')
def on_connect(client, userdata, flags, rc, properties=None):
if rc == 0:
logging.info('Connected to MQTT Broker')
client.publish(MQTT_TOPIC, 'ONLINE', qos=1, retain=True)
else:
logging.error(f'MQTT Connection failed with code {rc}')
def setup_hardware():
GPIO.setmode(GPIO.BCM)
GPIO.setup(PIR_PIN, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(BUZZER_PIN, GPIO.OUT, initial=GPIO.LOW)
def motion_callback(channel):
"""Interrupt-driven callback for PIR HIGH state."""
if GPIO.input(PIR_PIN):
logging.warning('Motion Detected! Triggering alarm.')
GPIO.output(BUZZER_PIN, GPIO.HIGH)
# Publish to MQTT with QoS 1 to ensure delivery
try:
client.publish(MQTT_TOPIC, 'TRIGGERED', qos=1)
except Exception as e:
logging.error(f'MQTT Publish failed: {e}')
time.sleep(ALARM_DURATION)
GPIO.output(BUZZER_PIN, GPIO.LOW)
client.publish(MQTT_TOPIC, 'CLEAR', qos=1)
def main():
setup_hardware()
client.on_connect = on_connect
try:
client.connect(MQTT_BROKER, MQTT_PORT, 60)
client.loop_start()
except Exception as e:
logging.error(f'Could not connect to MQTT broker: {e}')
logging.info('Running in local-only mode.')
# Attach hardware interrupt (Rising edge)
GPIO.add_event_detect(PIR_PIN, GPIO.RISING, callback=motion_callback, bouncetime=3000)
logging.info('Alarm system armed. Waiting for motion...')
try:
while True:
time.sleep(1) # Keep main thread alive
except KeyboardInterrupt:
logging.info('System disarmed by user.')
finally:
GPIO.cleanup()
client.loop_stop()
client.disconnect()
if __name__ == '__main__':
main()
Debugging: 'RuntimeError: Cannot determine SOC peripheral base address'
When deploying GPIO scripts on newer Raspberry Pi OS versions or the Pi 5, you will likely hit this exact error string:
RuntimeError: Cannot determine SOC peripheral base address
The First Three Things to Check When It Fails
- Are you running a Pi 5 with legacy RPi.GPIO? The Pi 5 uses the RP1 southbridge chip, changing the memory map. Legacy versions of
RPi.GPIO(pre-0.7.1) cannot find the peripheral addresses. - Is the user in the 'gpio' group? If you aren't running the script with
sudo, your user must be in thegpioanddialoutgroups to access/dev/gpiomem. - Is SPI/I2C conflicting in raspi-config? Rarely, enabling certain hardware interfaces via
raspi-configcan lock out base memory access for user-space GPIO libraries.
Ranked Causes and Fixes
- Cause 1: Outdated RPi.GPIO on Pi 5 / Bookworm.
Fix: Upgrade the library via pip. Runsudo apt update && sudo apt install python3-rpi-lgpio. Therpi-lgpiopackage acts as a drop-in replacement that uses the modernlibgpiodbackend, completely bypassing the legacy memory-mapping issue while keeping the exact same Python syntax. - Cause 2: Missing /dev/gpiomem permissions.
Fix: Add your user to the gpio group:sudo usermod -aG gpio $USER, then log out and log back in. Avoid running alarm scripts asrootviasudoin production, as it creates a security risk if the MQTT payload is ever compromised. - Cause 3: Corrupted Device Tree Blob (DTB).
Fix: If the OS was cloned from a Pi 3/4 SD card to a Pi 5 without updating the bootloader, the DTB won't map the RP1 chip. Runsudo rpi-eeprom-update -aand reboot.
Scaling the Build: Extensions and Simplifications
Not every deployment needs a full MQTT stack, and some need much more. Here is how to adapt the architecture.
How to Simplify the Build
If you don't have a home automation hub, strip out the paho-mqtt dependency entirely. Replace the hardware interrupt logic with the gpiozero library, which is pre-installed on Raspberry Pi OS and handles the Pi 5 RP1 chip natively without throwing the peripheral base address error.
from gpiozero import MotionSensor, Buzzer
from signal import pause
pir = MotionSensor(17)
buzzer = Buzzer(27)
pir.when_motion = buzzer.on
pir.when_no_motion = buzzer.off
pause()
How to Extend the Build
- Add Visual Verification: Wire a Raspberry Pi Camera Module 3 to the CSI port. Import
libcamerain the motion callback to snap a 1080p JPEG and push it via MQTT to a Telegram bot or Home Assistant notification. - Multi-Zone Perimeter: Add MC-38 magnetic reed switches to doors and windows. Wire them to GPIO pins with internal pull-up resistors enabled (
pull_up_down=GPIO.PUD_UP) to detect open circuits. - UPS Integration: A security system is useless if the power is cut. Add a Raspberry Pi UPS HAT with a LiFePO4 battery pack to maintain operations during grid outages.
Raspberry Pi Security Alarm System FAQ
Can a Raspberry Pi security alarm system work without internet?
Yes. The system described above operates entirely on your Local Area Network (LAN). The MQTT broker (like Mosquitto) can be hosted locally on the Pi itself or another local server. If the internet goes down, the PIR sensor will still trigger the local piezo buzzer, and local MQTT clients (like a wall-mounted tablet running Home Assistant) will still receive the alert. To send external SMS or email alerts without internet, you would need to attach a 4G LTE HAT with a SIM card.
How do I prevent false triggers from pets in a Raspberry Pi security alarm system?
The HC-SR501 sensor detects infrared heat signatures and cannot natively distinguish between a human and a large dog. To pet-proof the system:
1. Mount the sensor upside down or at ceiling height, angling the Fresnel lens upward so the detection zone bypasses the floor.
2. Apply a piece of electrical tape over the lower facets of the Fresnel lens to block the downward field of view.
3. For software filtering, add a camera and use a lightweight local AI model like TensorFlow Lite with a person-detection model to verify the PIR trigger before sounding the main siren.
Is a Raspberry Pi security alarm system reliable enough for a main home security panel?
For a hobbyist, a shed, or a secondary outbuilding, it is highly effective. However, for a primary residence, it lacks the UL-listing, cellular backup, and tamper-proof housing required by insurance companies and professional monitoring standards. SD card corruption is the most common point of failure for Pi-based alarms. If you rely on it for primary home security, you must boot the Pi from an external SSD via USB 3.0 and implement a watchdog timer circuit to automatically hard-reboot the board if the Python script hangs.






