PIR motion sensor
The HC-SR501 is a passive-infrared motion module for $4. A pyroelectric detector behind a Fresnel lens senses the infrared change when a warm body moves, and the module's own comparator turns that into a clean digital signal. Despite running from 5 V, its OUT pin swings to 3.3 V, so it connects straight to a GPIO. Two trimmers set the sensitivity (3–7 m) and the hold time, and a jumper chooses single-shot or repeatable triggering.
Pins
| Pin | What it is | Type |
|---|---|---|
| VCC | Supply 4.5–20 V (5 V from the Pi) | power |
| OUT | Output: 3.3 V high on motion | io |
| GND | Ground | ground |
| Setting | Type | Range | Default |
|---|---|---|---|
trigger | enum | repeat, single | repeat |
holdS | number | 3–300 | 5 |
In circuit.py:
PIR()— PIR motion sensor — $4- Pins: 3
The trigger setting matches the module's jumper: repeat keeps OUT high while motion continues (and for the hold time after), single gives one fixed pulse. holdS is the delay trimmer, 3–300 s.
Wiring it in circuit.py
from wiring import *
pi = Pi()
pir = PIR()
pi.V5 >> pir.vcc # 5 V supply
pir.gnd >> pi.GND
pir.out >> pi.GPIO17 # 3.3 V output: safe on a GPIOThree wires, no divider: that is the whole appeal of this module. Power it from the 5 V rail as if it were a bare detector, read OUT like a button. The only subtlety is that OUT needs no external pull-up — the module drives it actively.
Driving it in main.py
from gpiozero import MotionSensor
from time import sleep
pir = MotionSensor(17, pull_up=None, active_state=True)
while True:
print("motion!" if pir.motion_detected else "all quiet")
sleep(1)pull_up=None tells gpiozero not to add its own pull — the module already drives the line. motion_detected is true while OUT is high; pir.when_motion and pir.wait_for_motion() fire on the rising edge. Because OUT stays high for the whole hold time, a loop like the one above prints "motion!" repeatedly — count edges if you want one event per visitor.
Electrical notes
- Supply is 4.5–20 V; 5 V from the Pi is ideal. Quiescent current is about 65 µA, so it can stay on all day.
OUTis an active driven output at 3.3 V logic high. No pull-up or divider is needed; do not add a pull-up to 5 V on this pin.- Detection: up to 7 m within a 120° cone, adjusted by the sensitivity trimmer. Horizontal movement across the lens is detected best; walking straight at it is weakest.
- After power-on the module needs up to a minute to settle and may trigger by itself while it does. After each pulse it ignores motion for about 2.5 s (the block time) — the hold time is 3–300 s.
- The 3.3 V output is why this 5 V module is safe on a Pi without level shifting, unlike the HC-SR04's echo.
Simulator vs real hardware
- Motion comes from the feed: by default random visits (about 40 an hour, 4 s each), or a schedule, a wave or a button in the Lab. The canvas lights when
OUTis high. warmUpSis a knob (5 s by default) during which the output can fire spuriously; the real module wants up to a minute, so raise the knob if your code assumes a long warm-up.triggerandholdSare part settings, not jumpers:repeatextends the high time while motion continues,singledoes not, and both respect the 2.5 s block time.- The comparator is sampled every 100 ms rather than continuously, so a body that crosses the lens within a single 100 ms tick may not register. There is no false-trigger modelling from sun, drafts or pets — only the fields you feed it.
Going deeper
- Primer: GPIO and the 40-pin header — why a 3.3 V output matters.
- Fired by presence like the HC-SR04; switched from Python like a push button.
- Recipe: the door alarm watches one of these.
Further reading
- HC-SR501 PIR motion detector datasheet — hold time, block time, trigger modes and warm-up.
- gpiozero: MotionSensor —
motion_detected,when_motionandwait_for_motion. - Adafruit: PIR passive infrared motion sensor — aiming the lens and adjusting the trimmers.