In this Device Kit, we’ll be attaching a PIR (passive infrared) motion sensor to a Raspberry Pi and sending its output to Avimesa.Live in order to trigger an alert. We’ll be using an Avimesa Gadget client on the Raspberry Pi to relay our sensor’s output to Avimesa.Live.
To successfully set up this Device Kit, a rudimentary knowledge of electronics, the Linux command line interface (CLI), and the Python (3) programming language is (probably) required. Our PIR motion sensor will require nothing more than GPIO to give us the readings we require. On the Raspberry Pi, we’ll be using the Python programming language to drive (or control) Gadget as well as to read our PIR motion sensor’s output. To be more specific, we’ll make extensive use of two Python modules: the standard library subprocess module and the third party gpiozero module to, respectively, drive Gadget and deal with the Raspberry Pi’s peripherals (in our case, GPIO). The gpiozero module is the recommended Python module for controlling the Raspberry Pi’s peripherals.
Components
- a Raspberry Pi – (1) I’m using this Raspbian (Stretch) Lite image
- an Avimesa Gadget installation
- a valid set of Avimesa device credentials. Get a free Avimesa.Live account here and learn more about what device credentials are here
- Python 3 – This comes pre-installed on most relevant Raspbian images
- a (2) Python 3 gpiozero installation
- This PIR motion sensor by Adafruit Industries
- a breadboard and wiring (female and male)
Initial Setup
(1) Once you download a desirable Raspbian image, you can use Etcher to quickly copy it to your microSD.
(2) To install the Python module gpiozero, you’ll first want to make sure your repository list is up to date by running sudo apt update
. Second, install the module for Python (3) using the following command: sudo apt install python3-gpiozero
. If you run into any issues, please visit here for help troubleshooting.
Hardware Setup
Following is a table that should help in wiring up the PIR motion sensor to the Raspberry Pi. This link contains a great representation of the Raspberry Pi 40 pinout header and the associated Broadcom connections for assistance in determining what connections to make.
Raspberry Pi | PIR Motion Sensor |
---|---|
P2 – 5V | +5V |
P6 – Ground | GND |
P11 – GPIO17 | OUT |
Avimesa.Live Setup
First, you’ll need an active Avimesa.Live account.
Second, you’ll need to obtain a valid set of Avimesa device credentials:
Software
Let’s use this script first to make sure everything is working (copy the following into something like pir_sense_test.py
, insert your valid device credentials, and run using python3 pir_sense_test.py
):
import subprocess
from time import sleep
from gpiozero import MotionSensor
def send_message(motion_detected):
gdgt_args = ['/usr/local/bin/avmsagadget',
'-i',
'deadbeefdeadbeefdeadbeefdeadbeef', # DEVICE ID
'deadbeefdeadbeefdeadbeefdeadbeef'] # DEVICE AUTHENTICATION KEY
gdgt_timeout = 5
gdgt_input = ('{{"ch_idx":0,"ch_data":[{{"data_idx":0,'
'"units":1,"val":{0}}}]}}\nrun\n'
'exit\n').format(motion_detected)
gdgt_input = gdgt_input.encode()
try:
gdgt_complete = subprocess.run(args=gdgt_args,
input=gdgt_input,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
timeout=gdgt_timeout)
print("STDOUT:\n" + gdgt_complete.stdout.decode())
print("STDERR:\n" + gdgt_complete.stderr.decode())
except subprocess.TimeoutExpired:
print('Gadget timed out after {0} seconds!'.format(gdgt_timeout))
except subprocess.CalledProcessError as E:
print('Gadget exited with non-zero return code {0}'.format(E.returncode))
print('STDERR:\n' + E.stderr.decode())
if __name__ == '__main__':
pir = MotionSensor(17)
while True:
try:
pir.wait_for_motion()
send_message(1.0)
pir.wait_for_no_motion()
send_message(0.0)
except KeyboardInterrupt:
break
pir.close()
If everything is wired up correctly, you should be able to wave your hand (or dance if you’re feeling froggy…) in front of the sensor and a message should be sent off to the cloud. You’ll see Gadget>>> Message transmission successful!
if everything is truly correct. If you’re interested in what’s going on in this script, you can check out the MotionSensor Python class here for more information. If you’re having trouble, check the wiring of your sensor and make sure you’ve input your device credentials into the script.
Now let’s really get this thing set up: let’s turn it into a service. First, copy the following into something like pir_sense
:
#!/usr/bin/python3
import subprocess
from time import sleep
from gpiozero import MotionSensor
def send_message(motion_detected):
gdgt_args = ['/usr/local/bin/avmsagadget',
'-i',
'deadbeefdeadbeefdeadbeefdeadbeef', # DEVICE ID
'deadbeefdeadbeefdeadbeefdeadbeef'] # DEVICE AUTHENTICATION KEY
gdgt_timeout = 5
gdgt_input = ('{{"ch_idx":0,"ch_data":[{{"data_idx":0,'
'"units":1,"val":{0}}}]}}\nrun\n'
'exit\n').format(motion_detected)
gdgt_input = gdgt_input.encode()
try:
gdgt_complete = subprocess.run(args=gdgt_args,
input=gdgt_input,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
timeout=gdgt_timeout)
except subprocess.TimeoutExpired:
pass
except subprocess.CalledProcessError as E:
pass
if __name__ == '__main__':
pir = MotionSensor(17)
while True:
try:
pir.wait_for_motion()
send_message(1.0)
pir.wait_for_no_motion()
send_message(0.0)
except:
break
pir.close()
Move it to /usr/local/bin
using mv pir_sense /usr/local/bin
and change its permissions using sudo chmod 755 /usr/local/bin/pir_sense
.
We’ll also need to create the following file ~/.config/systemd/user/pir_sense.service
:
[Unit]
Description=PIR Sensing Service
[Service]
ExecStart=/usr/local/bin/pir_sense
Restart=on-failure
[Install]
WantedBy=default.target
This file is used by systemd to manage services (we’ll be installing our service under a non-root user). Here is a lovely little beginner’s guide on installing and managing services in Linux.
Once our service files are in place, let’s run this first to allow our service to run without our system requiring us to login:
sudo loginctl enable-linger $USER
Next, we’ll need to run the following to make systemd
aware of our .service
file:
systemctl --user daemon-reload
Finally, let’s enable our service to start on system start-up and also start our service:
systemctl --user enable pir_sense
systemctl --user start pir_sense
We can also check on our service with:
systemctl --user status pir_sense
Avimesa.Live Integration
First, let’s add our sensor in Avimesa.Live:
And finally, let’s add an alert to let us know whenever our sensor has detected motion:
NOTE: Make sure you have an email and / or phone number registered to your Avimesa.Live account!