- Learn Linux
- Learn Electronics
- Raspberry Pi
- LPI certification
- News & Reviews
16 December 2013
For my latest Raspberry Pi project I wanted to be able to detect when a person was in the room. I happened to have a Zilog PIR sensor from SK Pang that I'd bought, but not used. This provides details to get the PIR sensor working with the Raspberry Pi.
The data sheet for the PIR sensor is available from Sparkfun, although they no longer stock this particular sensor.
The Zilog PIR sensor has some on-board processing which allows it to be used in two different modes. The hardware mode provides a signal on one of the pins to indicate whenever the sensor is activated. The other mode is serial interface mode which allows us to connect via a serial interface and ask if the sensor has been activated. In this case we are going to use the serial mode using the serial pins on the GPIO connector.
The Zilog PIR sensor can be used with a 3.3V power supply or a 5V power supply. Although the supply voltage for the Raspberry Pi is 5V the serial connections on the GPIO run at 3.3V so this is connected using the 3.3V power supply.
The sensor should be connected as below:
Zilog port Raspberry Pi GPIO ---------- ----------------- pin 1 (GND) to pin 6 (GND) pin 2 (VDD) to pin 1 (3V3) pin 3 (RXD) to pin 8 (TDX) pin 4 (TXD) to pin 10 (RXD) pin 6 (LG) to pin 1 (3V3) – Unused in serial mode and needs to be connected to supply voltage pin 8 (GND) to pin 6 (GND)
Pin 4 also needs to be connected to the supply voltage through a 100k pull-up resistor. When powered on the PIR sensor sees the pull-up resistor as an indicate that it should use serial mode.
There is one problem with using the Serial port on the Raspberry Pi GPIO, which is that it is already in use. By default the serial port is configured as a console terminal port, which can be useful if you want to connect to the Raspberry Pi headless, but is not required for this.
To disable this
edit the file /etc/inittab (as root - ie. using sudo)
Comment out the console on the serial port by adding a # at the start of the getty line below
#Spawn a getty on Raspberry Pi serial line T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
Then edit /boot/cmdline.txt (as root)
Change the line which should read:
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p6 rootfstype=ext4 elevator=deadline rootwait
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p6 rootfstype=ext4 elevator=deadline rootwait
Note that I have just removed the one entry "console=ttyAMA0,115200".
After saving the changes reboot.
It's a good idea to test the sensor is working by using a serial console. First install the screen utility using:
sudo apt-get install screen
screen /dev/ttyAMA0 9600
which will use the screen program to connect to the terminal port ttyAMA0 (which is the port on the processor, connected to the GPIO).
Press the ‘a’ key after which you should get a character back from the sensor. It will return a 'Y' to indicate the sensor triggered or a 'N' to indicate not triggered. A 'U' returned means that the status is unavailable, which is usually seen within a few seconds of applying power to the module.
After testing use CTRL-a k to quit
From a bit of testing we can see that coming into the sensor range from a distance typically issues one Y. There are also some occasional false Y responses even when nobody is near. Moving closer to the sensor and we see two Y responses. We can use that later as a simple way to adjust the sensitivity. Note that the sensitivity can also be adjusted through issuing control serial commands to the module, but this basic test is sufficient for our needs.
The python code uses the pyserial module, which can be installed using
sudo apt-get install python-serial
The code is listed below, note the warnings that this doesn't include any error checking.
import serial, time # PIRSensor class # This is a crude way of detecting if a Zilog PIR sensor is triggered on the Raspberry Pi # It has been created for the Reindeer project http://www.penguintutor.com/electronics/reindeer # There is little in the way of handling any errors or checking # This is suitable for basic toy type detection, but would need further development for a more robust solution class PIRSensor: '''Class for reading PIR sensor''' # Commands issued to the PIR module STATUS_CMD = 'a' SENS_CMD = 's' # Not using this in the current version DELAY = 0.5 # Time in seconds between each sample def __init__(self): self.connect_status = 0 def connect(self): self.serial = serial.Serial("/dev/ttyAMA0", baudrate=9600) # Note no checking to see if this has worked (would be a good idea for future) # set internal status to connected self.connect_status = 1 print "Connected" def disconnect(self): ''' just set status to disconnected ''' self.connect_status = 0 # Gets a single value for status of PIR sensor # returns directly Y = Yes, N = No, U = Unavaialble (eg. not yet initialised) def getstatus(self): if self.connect_status == 1 : self.serial.write(self.STATUS_CMD) data = self.serial.read() return data else : return 0 def detect(self, pirsample, pirreq): ''' pirsample is number of samples to take, pirreq is number of Y required to return a Y - otherwise return a N''' yes_count = 0 for i in range(0, pirsample) : if (self.getstatus() == 'Y'): yes_count +=1 time.sleep(self.DELAY) # wait before trying again if (yes_count >= pirreq): return True else : return False
To use this in your own code add
# import the pirsensor module import pirsensor # These values determine the sensitivity of the sensor # PIRSAMPLE is the number of times we check for a detection # PIRREQ is the number of times that it must provide a Y in the sample # Suggested values - PIRSAMPLE = 5, PIRREQ =2 # More sensitive use PIRSAMPLE = 2, PIRREQ = 1 (only needs 1 Y to trigger) PIRSAMPLE = 5 PIRREQ = 2 # Create a sensor object and connect to the serial port pir = pirsensor.PIRSensor() pir.connect(); # if (pir.detect(PIRSAMPLE, PIRREQ)) : print "Motion detected"
You will see that there are some constants used to define how sensitive the sensor is. Instead of looking for a single Y from the PIR sensor it looks for PIRREQ number of Y's out of PIRSAMPLE samples. This is basic, but works.
This has given details of how to use the Zilog PIR sensor with the Raspberry Pi. It uses the PIR sensor in the serial mode. It has provided details on how to connect it to the GPIO connector on the Raspberry Pi and how to detect movement using a python program. It also includes a basic way to adjust the sensitivity.
The code is good for a basic sensor, but would need additional error checking and handling to use in a more critical application.