The GPIO pins on Raspberry Pi 5 represent a major architectural shift from previous generations. Because the Pi 5 offloads peripheral control to the new RP1 southbridge chip, legacy libraries like RPi.GPIO are largely deprecated, and the default logic level behavior for pull-up/pull-down resistors has changed. If you are wiring sensors or relays in 2026, you must use the lgpio backend (via gpiozero) and account for the Pi 5's strict 3.3V logic thresholds.

This guide cuts through the outdated tutorials. We will walk through a concrete decision framework for board selection, map out a PIR-triggered relay build, provide production-ready Python code, and debug the exact RP1-specific errors you will encounter on the bench.

The 2026 Decision Tree: Which Board for GPIO Projects?

Before stripping wire, you need to match your project's I/O demands to the right silicon. The Pi 5 is not always the correct tool for a simple GPIO toggle.

Criteria Raspberry Pi 5 (8GB) Raspberry Pi 4 Model B (4GB) Raspberry Pi Zero 2 W
GPIO Count 26 usable (40-pin header) 26 usable (40-pin header) 26 usable (40-pin header)
I2C/SPI Buses Multiple (via RP1 routing) 2x I2C, 2x SPI (standard) 1x I2C, 1x SPI (limited)
5V Pin Current Capacity Up to 5A (via USB-C PD) ~1.2A typical limit Highly restricted (~0.5A)
GPIO Library Backend lgpio (Mandatory) RPI.GPIO or lgpio RPI.GPIO or lgpio
Best Application Multi-bus, high-power 5V rail, CV Standard home automation Headless, single-sensor nodes
The Default Pick: If your project requires driving multiple 5V relay modules directly from the board's 5V rail while reading 3.3V I2C sensors, choose the Raspberry Pi 5 (8GB). Its upgraded power delivery and RP1 chip handle complex bus routing without the voltage sag seen on the Pi 4. If you only need to read a single digital sensor and transmit via WiFi, downgrade to the Pi Zero 2 W to save $45 and reduce idle power draw.

Hardware Spec Sheet: Parts List and Pin Mapping

For this build, we are creating a PIR-triggered security relay. The HC-SR501 PIR sensor outputs 3.3V when triggered (perfect for Pi logic), and we are using a 3.3V-specific relay to avoid back-EMF frying the RP1 chip.

Exact Parts List

  • Compute: Raspberry Pi 5 (8GB variant, SKU: SC1142) running Raspberry Pi OS Bookworm.
  • Sensor: HC-SR501 PIR Motion Sensor (adjusted to 3.3V output via onboard jumper or logic level).
  • Actuator: Songle SRD-03VDC-SL-C (3.3V DC coil) Relay Module with optocoupler isolation.
  • Wiring: 24 AWG solid core jumper wires (Dupont connectors).

Pin Mapping Table

Always use BCM (Broadcom) numbering in your code, not physical pin numbers. Reference pinout.xyz for visual confirmation.

Component Physical Pin BCM GPIO Wire Color Function
PIR VCC Pin 2 5V Power Red Sensor power (requires 5V for HC-SR501 internal regulator)
PIR OUT Pin 11 GPIO 17 Yellow Digital HIGH (3.3V) on motion detect
Relay VCC Pin 1 3.3V Power Orange Relay coil power (Must be 3.3V for this specific module)
Relay IN Pin 13 GPIO 27 Green Trigger signal (Active LOW)
Common GND Pin 6 Ground Black Shared ground for Pi, PIR, and Relay

Step-by-Step Build: PIR-Triggered Security Relay

Safety Warning: The relay will switch mains voltage (120V/240V AC) for a security light. Ensure the mains side of the relay is wired in a proper junction box with strain relief. Never leave exposed mains terminals on a breadboard. De-energize and verify dead with a multimeter before terminating AC wires.
  1. Prep the OS: Flash Raspberry Pi OS Bookworm (64-bit). Boot, open terminal, and run sudo raspi-config. Navigate to Interface Options > I2C and enable it (good practice to enable standard buses). Reboot.
  2. Install Dependencies: The Pi 5 requires the lgpio C library for Python GPIO access. Run:
    sudo apt update && sudo apt install python3-gpiozero python3-lgpio
  3. Wire the DC Side: Connect the PIR VCC to Pin 2 (5V). Connect the PIR OUT to Pin 11 (GPIO 17). Connect the Relay VCC to Pin 1 (3.3V) and Relay IN to Pin 13 (GPIO 27). Tie all GNDs to Pin 6.
  4. Calibrate the PIR: Use a small Phillips screwdriver to adjust the "Time Delay" potentiometer on the HC-SR501 fully counter-clockwise (minimum ~3 seconds) for testing. Leave the "Trigger" jumper on single-trigger mode (H).
  5. Verify Logic Levels: Before connecting AC, use your multimeter to probe the Relay IN pin while running the test script. You should see it drop from 3.3V to near 0V when motion is detected (active LOW).

Complete Python Control Code (Target: Raspberry Pi 5)

This script targets the Raspberry Pi 5 (8GB) using the gpiozero library, which automatically routes through the lgpio backend on Bookworm. It includes explicit pin definitions, state tracking, and a finally block to ensure the relay disengages if the script crashes.

#!/usr/bin/env python3
"""
PIR-Triggered Security Relay for Raspberry Pi 5
Requires: python3-gpiozero, python3-lgpio
"""

from gpiozero import MotionSensor, OutputDevice
from signal import pause
import time
import sys

# --- PIN DEFINITIONS (BCM Numbering) ---
PIR_PIN = 17      # Physical Pin 11
RELAY_PIN = 27    # Physical Pin 13

# --- HARDWARE CONFIGURATION ---
# HC-SR501 outputs HIGH (3.3V) on motion
pir = MotionSensor(PIR_PIN, queue_len=1, pull_up=False)

# Relay module is Active LOW (trigger on 0V)
# active_high=False tells gpiozero to invert the logic safely
relay = OutputDevice(RELAY_PIN, active_high=False, initial_value=False)

def system_startup():
    print(f"[INIT] GPIO Pins on Raspberry Pi initialized.")
    print(f"[INIT] Monitoring PIR on BCM {PIR_PIN}, controlling Relay on BCM {RELAY_PIN}.")
    # Ensure relay is OFF on startup
    relay.off()

def on_motion_detected():
    print(f"[{time.strftime('%H:%M:%S')}] MOTION DETECTED: Engaging relay.")
    relay.on()

def on_motion_stopped():
    print(f"[{time.strftime('%H:%M:%S')}] MOTION CLEARED: Disengaging relay.")
    relay.off()

if __name__ == "__main__":
    try:
        system_startup()
        # Bind events
        pir.when_motion = on_motion_detected
        pir.when_no_motion = on_motion_stopped
        
        print("[RUN] System active. Press Ctrl+C to exit.")
        pause() # Keeps script running efficiently
        
    except KeyboardInterrupt:
        print("\n[EXIT] Manual interrupt received.")
    except Exception as e:
        print(f"[FATAL] Unexpected error: {e}", file=sys.stderr)
    finally:
        # CRITICAL: Hardware cleanup to prevent relay sticking on crash
        print("[CLEANUP] Forcing relay OFF and releasing GPIO pins.")
        relay.off()
        relay.close()
        pir.close()

Debugging GPIO Failures: Exact Errors and Ranked Fixes

When working with the RP1 chip on the Pi 5, you will encounter specific errors that older forums cannot solve. Here are the exact error strings and how to fix them.

Error 1: RuntimeError: Cannot determine SOC peripheral base address

The Cause: You are trying to use the legacy RPi.GPIO library on a Raspberry Pi 5. The Pi 5's memory map is entirely different, and RPi.GPIO cannot find the old BCM2835/2711 peripheral addresses.

The Fix: 1. Uninstall the legacy library: pip3 uninstall RPi.GPIO
2. Ensure lgpio is installed: sudo apt install python3-lgpio
3. Use gpiozero (as shown in the code above), which automatically uses lgpio as its backend on the Pi 5.

Error 2: OSError: [Errno 121] Remote I/O error (If adding I2C sensors later)

The Cause: The Pi 5's RP1 chip handles I2C pull-up resistors differently. If your sensor module lacks physical 4.7kΩ pull-up resistors on the SDA/SCL lines, the bus will float and throw this error.

The Fix: Solder 4.7kΩ pull-up resistors between the 3.3V line and both SDA and SCL on your sensor breakout board. Do not rely on the Pi 5's internal software pull-ups for I2C.

The First 3 Things to Check When GPIO Fails

  1. Numbering Scheme Mismatch: Did you wire to Physical Pin 13 but define RELAY_PIN = 13 in code? Physical Pin 13 is BCM GPIO 27. Always map physical to BCM using pinout.xyz.
  2. Backend Verification: Run python3 -c "import gpiozero; print(gpiozero.Device._default_pin_factory)". It should output lgpio. If it outputs rpigpio, your environment is misconfigured for Pi 5.
  3. Voltage Starvation: Measure the 3.3V rail (Pin 1) under load with a multimeter. If it drops below 3.1V when the relay triggers, your power supply is browning out the Pi. Use an official 27W USB-C PD power supply.

Extending and Simplifying the Build

To Simplify: If you don't need to switch AC mains and just want a visual indicator, strip out the relay module entirely. Replace the OutputDevice with a LED object from gpiozero, wire a standard 5mm LED with a 220Ω current-limiting resistor to GPIO 27, and reduce the hardware footprint to a single breadboard.

To Extend: To make this a true IoT node, integrate the paho-mqtt library. Add an MQTT publish call inside the on_motion_detected function to send a JSON payload {"event": "motion", "state": 1, "ts": time.time()} to a local Mosquitto broker. This allows Home Assistant to ingest the Pi 5's GPIO state natively over your network without polling, turning a standalone bench project into a permanent smart-home fixture.