Most legacy tutorials instruct you to wire the data pin of an HC-SR501 PIR sensor directly to a Raspberry Pi GPIO pin. If you are using a Raspberry Pi 5 (or even a Pi 4), doing this will inject 5V into a 3.3V-tolerant pin, permanently damaging the SoC. The direct answer for a safe, reliable build: you must drop the PIR's 5V output down to 3.0V using a simple two-resistor voltage divider, or use a native 3.3V sensor like the AM312.

This guide targets the Raspberry Pi 5 (4GB/8GB) and Pi 4 Model B running Raspberry Pi OS (Bookworm or later). We will use the officially supported gpiozero library, which relies on the lgpio backend in modern Pi OS releases, bypassing the deprecated RPi.GPIO library entirely.

The 3.3V Logic Trap: Choosing Your PIR Sensor

Not all PIR sensors are created equal when interfacing with modern single-board computers. The core issue is the logic HIGH voltage on the sensor's OUT pin. If the sensor is powered by 5V, its OUT pin will output 5V when motion is detected. The Raspberry Pi GPIO pins have an absolute maximum rating of 3.3V. Exceeding this by even 0.5V can degrade the pin; exceeding it by 1.7V will fry the internal ESD diodes and potentially kill the CPU.

Sensor ModelOperating VoltageLogic HIGH OutputRangeVerdict for Raspberry Pi
HC-SR5015V - 20VEqual to VCC (5V)~7 metersDefault Pick. Requires a voltage divider on the OUT pin.
HC-SR5054.5V - 20VEqual to VCC (5V)~3 metersAvoid. Still requires level shifting, but offers less range than the 501.
AM3122.7V - 12VEqual to VCC (3.3V)~3 metersSimplest Pick. Power it from the Pi's 3.3V rail. Direct GPIO connection.

The Decision: If you need maximum range and adjustable delay/ sensitivity potentiometers, buy the HC-SR501 and build a $0.10 voltage divider. If you want a plug-and-play direct connection and don't mind a shorter 3-meter range, buy the AM312. For this build, we will proceed with the HC-SR501 and a voltage divider, as it is the most common module in maker kits and teaches critical signal conditioning.

Parts List and Spec Sheet

  • Microcontroller: Raspberry Pi 5 (4GB or 8GB) or Pi 4 Model B
  • Sensor: HC-SR501 PIR Motion Sensor module
  • Resistors: One 2.2kΩ (Red-Red-Red-Gold) and one 3.3kΩ (Orange-Orange-Red-Gold) 1/4W carbon film
  • Wiring: 4x Female-to-Male jumper wires, half-size breadboard
  • Power: Official 27W USB-C PD power supply (for Pi 5)

Pin Mapping Table (BCM Numbering)

The Raspberry Pi uses BCM (Broadcom) GPIO numbering in software, which differs from the physical pin numbers on the header. Always use BCM in your code.

HC-SR501 PinDestinationPi Physical PinNotes
VCC5V PowerPin 2 or 4Provides 5V to the sensor and the voltage divider.
OUTVoltage Divider InputN/AConnects to the junction of the 2.2kΩ and 3.3kΩ resistors.
GNDGroundPin 6, 9, 14, etc.Common ground with the Pi and the bottom of the voltage divider.
Voltage Divider OutGPIO 4 (BCM)Pin 7The stepped-down 3.0V signal enters the Pi here.

Step-by-Step Wiring Procedure

SAFETY WARNING: Never connect a 5V logic output directly to a Raspberry Pi 5 GPIO pin. Always verify your voltage divider output with a multimeter before connecting it to the Pi.
  1. Build the Voltage Divider: Insert the 2.2kΩ and 3.3kΩ resistors into the breadboard so they share a common center row. This center row is your Signal Out.
  2. Wire the Sensor Power: Connect the HC-SR501 VCC pin to the breadboard's 5V rail. Connect the sensor GND pin to the breadboard's GND rail.
  3. Wire the Sensor Data: Connect the HC-SR501 OUT pin to the free end of the 2.2kΩ resistor.
  4. Complete the Divider: Connect the free end of the 3.3kΩ resistor to the breadboard GND rail.
  5. Connect to the Pi:
    • Pi 5V (Pin 2) to breadboard 5V rail.
    • Pi GND (Pin 6) to breadboard GND rail.
    • Pi GPIO 4 (Pin 7) to the center row of the voltage divider (the junction between the two resistors).
  6. Verify with Multimeter: Power on the Pi. Set your multimeter to DC Voltage. Probe the center row of the voltage divider. When the PIR is idle, it should read ~0.0V. Trigger the PIR by waving your hand; it should jump to ~3.0V. If it reads 5V, your wiring is wrong. Disconnect immediately.

Python Code: Detection with gpiozero

In Raspberry Pi OS Bookworm, the legacy RPi.GPIO library is deprecated and often fails on the Pi 5 due to the new RP1 southbridge chip. We use gpiozero, which automatically routes through the lgpio C-backend for hardware access.

Save the following code as pir_monitor.py. This script includes proper logging, pin definitions, and exception handling to prevent orphaned GPIO states if the script crashes.

#!/usr/bin/env python3
import logging
from signal import pause
from gpiozero import MotionSensor
from gpiozero.exc import PinFactoryFallback, GPIOZeroError

# Configure logging for clear terminal output
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    datefmt='%Y-%m-%d %H:%M:%S'
)

# BCM Pin Definition
PIR_GPIO_PIN = 4

def on_motion_detected():
    logging.warning('INTRUSION: Motion detected in sensor field!')
    # Extension point: Trigger Pi Camera, send MQTT payload, or sound buzzer

def on_motion_cleared():
    logging.info('Zone clear. Sensor idle.')

def main():
    try:
        logging.info(f'Initializing PIR sensor on BCM GPIO {PIR_GPIO_PIN}...')
        # queue_len=1 ensures immediate trigger without software debouncing delays
        pir = MotionSensor(PIR_GPIO_PIN, queue_len=1, pull_up=False)
        
        pir.when_motion = on_motion_detected
        pir.when_no_motion = on_motion_cleared
        
        logging.info('Monitoring active. Press CTRL+C to exit.')
        pause() # Keeps the script running efficiently
        
    except KeyboardInterrupt:
        logging.info('Script terminated by user (SIGINT).')
    except PinFactoryFallback as e:
        logging.error(f'GPIO Backend Error: {e}')
        logging.error('Fix: Run `sudo apt install python3-lgpio` and ensure RPi.GPIO is uninstalled.')
    except GPIOZeroError as e:
        logging.error(f'Hardware initialization failed: {e}')
    except Exception as e:
        logging.critical(f'Unexpected fatal error: {e}')

if __name__ == '__main__':
    main()

Debugging: First Three Things to Check When It Fails

When your PIR build fails, it usually manifests in one of three ways. Follow this ranked troubleshooting path before replacing hardware.

1. The Script Crashes on Launch

Exact Error String: RuntimeError: Cannot determine SOC peripheral base address or gpiozero.exc.PinFactoryFallback.

The Cause: You are trying to use the legacy RPi.GPIO library, or gpiozero is falling back to it because lgpio is missing. The Pi 5's RP1 chip uses a completely different memory map than the Pi 4's BCM2711.

The Fix: Open your terminal and run: sudo apt remove python3-rpi.gpio sudo apt install python3-lgpio python3-gpiozero Restart your script. It will now use the correct hardware backend.

2. The Sensor Never Triggers (Always reads LOW)

Symptom: The script runs, but waving your hand produces no log output. The multimeter reads 0V at the voltage divider junction even when triggered.

The Cause: The HC-SR501 has a 'startup lockout' period. When first powered on, the sensor calibrates its ambient infrared baseline. During this time (typically 15 to 30 seconds), the OUT pin is held LOW. Alternatively, the potentiometers on the board are tuned to minimums.

The Fix: Wait 30 seconds after applying power. If it still fails, locate the two orange trimpots on the HC-SR501. Turn the Delay Time pot (usually on the left) fully clockwise to maximize the HIGH output duration. Turn the Sensitivity pot (right) clockwise to increase the detection field.

3. Phantom Triggers (Fires when no one is there)

Symptom: The log shows motion detected every few minutes in an empty room.

The Cause: PIR sensors detect changes in infrared radiation, not just presence. HVAC vents, sunlight shifting across a wall, or even RF interference from a nearby Wi-Fi router can induce voltage spikes on the high-impedance OUT pin.

The Fix:

  • Solder a 100µF electrolytic capacitor across the VCC and GND pins directly on the PIR sensor PCB. This filters power supply ripple that causes false logic HIGHs.
  • Ensure the sensor is not pointed at a window, heat register, or reflective surface.
  • In software, add a software debounce if physical filtering isn't enough: change queue_len=1 to queue_len=3 in the MotionSensor initialization to require three consecutive HIGH reads before triggering.

Extending and Simplifying the Build

Pro-Tip: The Voltage Divider Math
The formula for a voltage divider is V_out = V_in * (R2 / (R1 + R2)). With a 5V input, a 2.2kΩ R1, and a 3.3kΩ R2, the output is 5 * (3.3 / 5.5) = 3.0V. This is perfectly safe for the Pi's 3.3V pins, and comfortably above the 1.8V threshold the Pi requires to register a logic HIGH.

How to Extend: Adding a Camera Payload

A motion sensor is rarely useful in isolation. The most common extension is capturing an image when motion is detected. Using the picamera2 library (the modern replacement for the deprecated picamera), you can update the on_motion_detected function:

from picamera2 import Picamera2
import time

cam = Picamera2()
cam.configure(cam.create_still_configuration())
cam.start()

def on_motion_detected():
    timestamp = time.strftime('%Y%m%d-%H%M%S')
    filepath = f'/home/pi/motion_captures/intruder_{timestamp}.jpg'
    cam.capture_file(filepath)
    logging.warning(f'Motion captured and saved to {filepath}')

Note: Ensure you create the motion_captures directory and grant write permissions before running.

How to Simplify: Downgrading to an ESP32

If your end goal is simply to push an MQTT message to Home Assistant when motion is detected, do not use a Raspberry Pi. A Pi 5 idles at roughly 4W to 6W and costs upwards of $60. An ESP32-C3 SuperMini costs about $3, idles at milliamps, and can run the exact same HC-SR501 sensor (the ESP32 is natively 3.3V, but its pins are often 5V tolerant, though a voltage divider is still best practice for longevity).

For pure IoT motion endpoints, simplify the build by flashing ESPHome onto an ESP32. You can define the PIR in YAML in three lines, completely eliminating the need to maintain a Python environment, manage OS updates, or worry about SD card corruption on a headless Pi.

By respecting the 3.3V logic boundaries of modern ARM boards and utilizing the correct hardware backends in Python, your Raspberry Pi PIR projects will transition from fragile breadboard experiments to reliable, always-on security nodes.