Now our Raspberry Pi is up and running, let's add the necessary hardware.


Just joining us? Make sure you've got your Raspberry Pi set up correctly as described in part two of this how-to guide.

 

Attaching the hardware to Raspberry Pi

Now we have got our Raspberry Pi up to date, installed some required packages and created a mount point for our USB storage device we can now begin to add the peripheral hardware.

Make sure your Raspberry Pi is powered down.

sudo halt

Disconnect any power cables then connect the camera module to the Raspberry Pi using the camera's ribbon. To do this, gently open the CSI clip by pulling the plastic tab on each side out. They'll only pop out about 1mm. Then insert the ribbon so the contacts are facing down as far as it will go. Finally, push the clips back into position to secure the ribbon. Try and make sure the ribbon is inserted evenly at both sides. If needed, attach the other end of the ribbon to the camera module using the same style of mechanism.

With the camera in place, we can now add the PIR module. Here we will need our three jumper leads.

The PIR has 3 pins: Power, Signal and Ground which need to be connected to the corresponding pins on the Raspberry Pi. Most PIR sensors are configured in the same way but you may need to refer to the sensor's datasheet or the sensor's circuit board to make sure you can tell which pin is which.

On my sensor, with the pins at the top edge from left to right they read Ground, Signal, Power. The image shows how I've attached different coloured jumper leads to each pin.

Now we need to connect the jumpers to the correct pins on the Raspberry Pi.

Power (white): Pin 2

Signal (yellow): Pin 11

Ground (purple): Pin 14

See this diagram for a details illustration of the Pi's GPIO pins. It's important that these are wired correctly because doing it wrong can have cause problems!

Now attach a power cable and connect to the Raspberry Pi as before using SSH.

 

Setting up the motion detection program

Once logged into your Raspberry Pi, we can create a program using a language called Python that will control when the camera and the PIR sensor and then write the images or video footage to our USB stick. Don't worry, there's no need to get into the details of the program, you can just copy and paste it although it's fairly easy to see what's happening if you look at each of the commands.

Create a new file for the program

nano trailcam.py

Nano is a simple text editor that we can use to write copy the following program to the file and trailcam.py is the name of the filename.

Copy the program and paste it into the blank file (if you right-click the mouse in PuTTY, this will paste the code).

from gpiozero import MotionSensor
import logging
from datetime import datetime
from subprocess import call
import picamera
import time
import os

if not os.path.exists('/home/pi/trailcam_log'):
    os.makedirs('/home/pi/trailcam_log')

if not os.path.exists('/home/pi/videos'):
    os.makedirs('/home/pi/videos')

if not os.path.exists('/mnt/usb/videos'):
    os.makedirs('/mnt/usb/videos')

logfile = "/home/pi/trailcam_log/trailcam_log-"+str(datetime.now().strftime("%Y%m%d-%H%M"))+".csv"
logging.basicConfig(filename=logfile, level=logging.DEBUG,
    format='%(asctime)s %(message)s',
    datefmt='%Y-%m-%d, %H:%M:%S,')

pir = MotionSensor(17)
duration = 20

print('Starting')
logging.info('Starting')

# Wait an initial duration to allow PIR to settle
print('Waiting for sensor to settle')
time.sleep(10)
print('Ready')

while True:
    pir.wait_for_motion()
    logging.info('Motion detected')
    print('Motion detected')
    while pir.motion_detected:
        print('Beginning capture')
        ts = '{:%Y%m%d-%H%M%S}'.format(datetime.now())
        logging.info('Beginning capture: '+ str(ts)+'.h264')
        with picamera.PiCamera() as cam:
            cam.resolution=(1024,768)
            cam.annotate_background = picamera.Color('black')

            cam.start_recording('/home/pi/video.h264')
            start = datetime.now()
            while (datetime.now() - start).seconds < duration:
                cam.annotate_text = datetime.now().strftime('%d-%m-%y %H:%M:%S')
                cam.wait_recording(0.2)
            cam.stop_recording()
        time.sleep(1)
        print('Stopped recording')
        timestamp = datetime.now().strftime('%d-%m-%y_%H-%M-%S')
        input_video = "/home/pi/video.h264"

        logging.info('Attempting to save video')
        print('Attempting to save video')

        usb = call("mountpoint -q /mnt/usb", shell=True)

        if usb == 0:
            logging.info('Saving to /mnt/usb/videos/')
            print('Saving to /mnt/usb/videos/')
            output_video = "/mnt/usb/videos/{}.mp4".format(timestamp)
        else:
            logging.info('Saving to /home/pi/videos/')
            print('Saving to /home/pi/videos/')
            output_video = "/home/pi/videos/{}.mp4".format(timestamp)

        call(["MP4Box", "-add", input_video, output_video])
        print('Motion ended - sleeping for 10 secs')
        logging.info('Motion Ended')
        time.sleep(10)

Save the file with CTRL+X and then Y to confirm.

 

Saving the video to the USB drive

The major advantage of using a USB drive to save the footage to is that it can be removed and replaced with a fresh drive at any point allowing the camera to be kept in position while we look at what has been recorded.

In the previous part of this guide we set up a mount point for the drive so let's continue from there. Attach your USB drive to the Raspberry Pi and type the following command:

sudo blkid

This should show you information about the drives attached to the Raspberry Pi.

 

In our case, we're interested in the /dev/sda1. Generally the sda1 drive is what you're looking for but in my case, the label 'Kingston' also reveals which drive I'm looking for since that's the brand of USB drive I'm using.

Now we need to make sure that whenever this USB drive is attached to the Raspberry Pi it is mounted to the folder we created previously (/mnt/usb).

sudo nano /etc/fstab

This opens a file that controls the auto-mounting of drives. Add the following to the end of the file

/dev/sda1 /mnt/usb vfat auto,nofail,noatime,users,rw,uid=pi,gid=pi 0 0

Note the first part of the line is the device location we determined with the blkid command. If yours was different, change it accordingly.

Save the file with CTRL+X then Y.

 

Summary so far

If everything is configured correctly, when the trailcam.py program is run, the PIR will be armed and when it detects motion, it will tell the camera to begin recording. After the allotted time, the camera will turn off and save the footage to the USB drive before waiting for more movement. If no drive can be found, there is a fallback in place that will save the footage to the home directory on the Raspberry Pi's SD card. Retrieving footage from the SD card is more tricky than getting it from the USB drive but at least you know the footage is saved.

Now reboot your Raspberry Pi with

sudo reboot

Once logged in again, test the program with

python3 trailcam.py

If everything is working correctly, you should see the following output a few seconds after waving your hand in front of the PIR.

Stop the program with CTRL+C.

You can test if everything worked out ok by shutting down the Raspberry Pi

sudo halt

Remove the USB drive and plug it into your computer to check if the footage has been saved.

 

Start the program automatically

When the trail cam is deployed in the field, it won't be possible to log in and start the trailcam.py program so we need to configure the Raspberry Pi to do this automatically. We can edit out rc.local file to start the program when the Pi boots up:

sudo nano /etc/rc.local

At the bottom of the file (before the exit 0 line) add the following line

/usr/bin/python3 /home/pi/trailcam.py &

Save the file with CTRL+X then Y.

 

Rounding off

Great work! Hopefully you now have your trail cam up and running. If you've been able to view the footage on another computer, you might notice the timestamp at the top of the video and in some cases if might not be correct. If you're testing your trail camera and your Raspberry Pi is connected to the internet during testing, it will automatically sync to the correct time and date, however out the in the field it won't be able to connect to any network to get the correct time. This is pretty annoying because although we can record footage, we'll have to guess when it actually happened. Luckily there is a way to solve this by giving the Raspberry Pi its own clock to keep a track of time.

I'll cover how to add a real time clock (RTC) to our trail cam in the next section of this how-to guide.