HW-456 PIR Motion Sensor Module
A test of the HW-456 PIR motion sensor module connected to a Raspberry Pi Pico.
Module Description
The HW-456-SR505 PIR Motion Sensor Module uses passive infrared to detect changes in heat emitted by surrounding objects. Response times to detected motion are almost immediate. When motion is detected, the module emits a high (3.3v) signal from the center pin. Once motion is no longer detected, the signal returns to low (0v) after a non-adjustable 8-second delay.
Hardware
- Raspberry Pi Pico
- HW-456-SR505 PIR Motion Sensor Module
- 3x Dupont Jumper Wires (F-F)
Specifications
- Operating Voltage: 4.5V - 20V
- Current Drain: 60uA
- Sensing Angle: 100°
- Sensing Distance: 3m
- 3 Pin Header: VCC, OUT, GND
- Cost: $1.00 USD
Wiring
Wire the PIR motion sensor module to the Raspberry Pi Pico as follows:
PIR Motion Sensor Module | Raspberry Pi Pico |
---|---|
+ (Positive power supply) | VBUS (Pin 40) |
S (Signal Output) | GPIO 0 (Pin 0) |
- (Ground) | GND (Pin 38) |
The VBUS pin is the only option for 5V power on the Raspberry Pi Pico. The PIR motion sensor needs at least 4.5V to operate, and the VBUS draws power directly from the USB connection, so it has the necessary voltage.
Code
The following MicroPython code will print the current time and a message when motion is detected. The signal pin is checked every second, and the message is printed when the signal is high. When the signal is low, a series of dashes is printed to indicate no motion detected.
Let's walk through the code:
Import dependencies
Lines 1 - 2
import the necessary dependencies for the code to run.
- The Pin module lets our code communicate with the hardware.
- The sleep function lets us pause the code for a specified number of seconds.
- The localtime function lets us get the current time as an 8-tuple.
from machine import Pin
from time import sleep, localtime
signalPin = Pin(0, Pin.IN)
def formatTime(timeArray):
h = timeArray[3]
m = timeArray[4]
s = timeArray[5]
return ":".join([str(h),str(m),str(s)])
while True:
if signalPin.value()==1:
print(formatTime(localtime()), "Movement detected.")
else:
print("------")
sleep(1)
Instantiate the signal pin
Line 4
instantiates the signalPin
object which is how the Pico and the HW-456 will communicate.
The first argument is the pin number on the Pico. In this example we use pin 0
, which refers to
GP0 on the Pico (physical pin 1). You can use any GPIO pin you want, just make sure to reference the
correct pin number in the code. Here's the
pinout diagram
The second argument is the mode of the pin. In this case, we want to read the signal from the HW-456,
so we set the mode to Pin.IN
.
from machine import Pin
from time import sleep, localtime
signalPin = Pin(0, Pin.IN)
def formatTime(timeArray):
h = timeArray[3]
m = timeArray[4]
s = timeArray[5]
return ":".join([str(h),str(m),str(s)])
while True:
if signalPin.value()==1:
print(formatTime(localtime()), "Movement detected.")
else:
print("------")
sleep(1)
Format the time
Lines 6 - 10
define a function called formatTime
which takes an 8-tuple as an argument and
returns a string in the format HH:MM:SS
.
This is not strictly necessary for the function of this code, but I wanted to see time stamps to help differentiate the otherwise identical and repetitive messages.
There may be a more elegant way to do this, but Python is not my expertise.
from machine import Pin
from time import sleep, localtime
signalPin = Pin(0, Pin.IN)
def formatTime(timeArray):
h = timeArray[3]
m = timeArray[4]
s = timeArray[5]
return ":".join([str(h),str(m),str(s)])
while True:
if signalPin.value()==1:
print(formatTime(localtime()), "Movement detected.")
else:
print("------")
sleep(1)
Check the signal
Lines 12 - 16
use an infinite while
loop to check the value of the signal pin every second. It
will run indefinitely until you terminate the code manually.
Each iteration of the loop checks the value of the signal pin using the value()
method. If the value
is 1
, the code prints the current time and a message indicating motion was detected.
If no motion is detected, then the value of the signal pin is 0
, and the else
block prints a series
of dashes to indicate no motion was detected. This else
block is not strictly necessary, but I wanted
to see a visual indication of the lack of motion.
Finally line 17
pauses the code for 1 second before the next iteration of the loop. You can adjust
this value to make the code run faster or slower to suit your needs.
from machine import Pin
from time import sleep, localtime
signalPin = Pin(0, Pin.IN)
def formatTime(timeArray):
h = timeArray[3]
m = timeArray[4]
s = timeArray[5]
return ":".join([str(h),str(m),str(s)])
while True:
if signalPin.value()==1:
print(formatTime(localtime()), "Movement detected.")
else:
print("------")
sleep(1)