Skip to content

HW-456 PIR Motion Sensor Module

A test of the HW-456 PIR motion sensor module connected to a Raspberry Pi Pico.

PIR Motion Sensor Module

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 ModuleRaspberry 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)