Symptom
A script that toggled relays or read buttons on a Pi 4 fails on a Pi 5, typically at startup when the GPIO library initialises, or gpiozero complains that no pin factory could be loaded.
Why
gpiozero talks to the hardware through a pin factory. According to the gpiozero documentation, only lgpio works on Raspberry Pi 5; the rpigpio (RPi.GPIO), pigpio and native factories do not support it. Code written directly against RPi.GPIO has the same problem.
By default gpiozero tries lgpio, rpigpio, pigpio, native in that order, so plain gpiozero code usually just works on a current Raspberry Pi OS. Forcing another factory with GPIOZERO_PIN_FACTORY breaks it on a Pi 5.
Fix: write GPIO code against gpiozero
from signal import pause
from gpiozero import LED, Button
relay = LED(17) # GPIO17 (BCM numbering), drives a relay module input
button = Button(2) # GPIO2 has a fixed pull-up on the board
button.when_pressed = relay.toggle
pause()
- gpiozero ships with Raspberry Pi OS. Inside a virtual environment, either install it with pip or create the venv with
--system-site-packages(see the Python item). - Don't set
GPIOZERO_PIN_FACTORYunless you know the target board supports that factory. - The command
pinout(from gpiozero) prints the header layout for the board you are on.
Electrical limits (all models)
- GPIO is 3.3 V; never feed 5 V into a GPIO pin. Use level shifters for 5 V devices.
- Max 16 mA per pin, 50 mA across all GPIO pins. Drive relays, motors and LED strips through transistors, driver boards or relay modules with their own supply.
- LEDs need a series resistor.
- The user running the code must be in the
gpiogroup (sudo usermod -a -G gpio <user>); the default user already is. Matters for services running as dedicated users.