f-log

just another web log

05 Aug 2015:
pi pir python rig success
I struggled for a long time with the last Pi cam, so I wanted to take a completely different approach.

PIR (Passive Infrared Sensor) are simple and cheap, detecting the movement of objects giving of Infrared radiation e.g. humans. (You might want to watch Sneakers for tips on how to avoid them ;)

This would involve electronics (which I am not very good at) but should result in a simple setup. Luckily for me there is a handy worksheet over on the https://www.raspberrypi.org/learning/ portal.

Great news! Number of components is 1, not even a resistor! All that is needed is the PIR sensor and the right cables to connect it to the Pi.

I copied the first code example from the worksheet and it worked!

Not a pretty program when running, I decided to make it a bit more interesting.


import RPi.GPIO as GPIO
import time
import sys

sensor = 4

GPIO.setmode(GPIO.BCM)
GPIO.setup(sensor, GPIO.IN, GPIO.PUD_DOWN)

previous_state = False
current_state = False
state = "+"

try:
    while True:
        time.sleep(0.01)
        previous_state = current_state
        current_state = GPIO.input(sensor)
        if current_state != previous_state:
            new_state = "HIGH" if current_state else "LOW"
            if new_state == "HIGH":
                state = "+"
            else:
                state = "="
        else:
            state = "_"
        sys.stdout.write(state)
        sys.stdout.flush()
except KeyboardInterrupt:
    print "User Quit, doing GPIO clean up"
    GPIO.cleanup()


Instead of spitting out the words "HIGH" and "LOW", it streams characters
___________________________________________+=___________________________+__=____________________+_=___________________________________+=__________________+______________________________=________________User Quit, doing GPIO clean up

You can clearly see when the sensor was tripped "+" and then when the sensor thought nothing else was going to happen "=" and finally nothing has changed from the last state "_".

I then added in some simple camera commands and it would take pictures and save them to the PI when activity was sensed. There is a lot of documentation and even more examples of driving the raspberry Pi camera with Python https://picamera.readthedocs.org/

Then I wondered about calling out to the DropBox upload script I had used previously. Surely trying to upload files to DropBox in Python would be super painful?

I quick demo to myself
#DropBox POC from stackoverflow
#http://stackoverflow.com/questions/23894221/upload-file-to-my-dropbox-from-python-script
import dropbox

client = dropbox.client.DropboxClient('DROPBOXAUTHKEYGETYOURSFROMYOURDROPBOXACCOUNT')
print 'linked account: ', client.account_info()

f = open('working-draft.txt', 'rb')
response = client.put_file('/88/magnum-opux.txt', f)
print 'uploaded: ', response

folder_metadata = client.metadata('/')
print 'metadata: ', folder_metadata

f, metadata = client.get_file_and_metadata('/88/magnum-opux.txt')
out = open('magnum-opux.txt', 'wb')
out.write(f.read())
out.close()
print metadata


This uploads a local file "working-draft.txt" to a DropBox folder "88" with the new file name of "magnum-opux.txt" and then downloads that file "/88/magnum-opux.txt". It also spits out a lot of information, but it did work.

Get your "DROPBOXAUTHKEYGETYOURSFROMYOURDROPBOXACCOUNT" key by going to your https://www.dropbox.com/developers/apps page creating an app and creating a key.

This means all I need to add is 5-6 lines to my main camera script.

# Pir_camera.py
#
# Polling script to take and upload images when PIR sensor is triggered
# Rob Davis 2015
#
import RPi.GPIO as GPIO
import time
import sys
import os
import picamera
import datetime
import dropbox

# Never upload your secret keys to github!
client = dropbox.client.DropboxClient('DROPBOXAUTHKEYGETYOURSFROMYOURDROPBOXACCOUNT')

liveOutput = False
#Create a camera interface with the half the maximum 5MP resolution
cam = picamera.PiCamera()
cam.resolution = (1296, 972)

#Which GPIO pin are we using?
sensor = 4

#Set the GPIO pin ready for input
GPIO.setmode(GPIO.BCM)
GPIO.setup(sensor, GPIO.IN, GPIO.PUD_DOWN)

#simple state variables
previous_state = False
current_state = False
state = "+"
capturing = False
captureCount = 0

#Upload a file name to a path on DropBox
def UploadFile(filename, uploadPath):
    fileHandle = open(filename, 'rb')
    response = client.put_file(uploadPath + filename, fileHandle)
    #really should check the response, but, it always works ;)
    os.remove(filename)

#Get a unique filename based on the datetime
def GetFileName(count):
    return datetime.datetime.now().strftime("%Y%m%d%H%M%S_" + str(count) + ".jpg")

#Get a path based on the date, so a new folder each day
def GetUploadPath():
    return datetime.datetime.now().strftime("%Y%m%d/")

if len(sys.argv) >= 2 and sys.argv[1] == "-v" :
    liveOutput = True


#Main loop in a try/catch to allow for CTRL+c termination
try:
    while True:
        time.sleep(0.01)    # very short sleep, 100th of a second
        previous_state = current_state # back up current state
        current_state = GPIO.input(sensor) # get new 'current' state
        if current_state != previous_state:
            new_state = "HIGH" if current_state else "LOW"
            if new_state == "HIGH":
                state = "+"
                capturing = True
            else:
                state = "="
                capturing = False
                captureCount = 0
        else:
            state = "_"
        if capturing:
            state = "[o]"
            captureCount += 1    # allows for multiple frames per-second
            filename = GetFileName(captureCount)
            uploadPath = GetUploadPath()
            cam.annotate_background = picamera.Color('black')
            cam.annotate_text = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            cam.capture(filename)    # get a photo from the camera
            UploadFile(filename, uploadPath)    # upload the photo to a 'todays' folder on DropBox
        if liveOutput :
            sys.stdout.write(state)    # print out the state without a LF
            sys.stdout.flush()    # flush to stdout or it will sit waiting for a LF
except KeyboardInterrupt:
    print "User Quit, doing GPIO clean up"
    GPIO.cleanup()


Woh! This looks like a really big program!

Start with importing the right libraries...


Set all the starting values, like image size and which pin the PIR sensors is on.

"UploadFile" takes filename and path, uploads the file DropBox and deletes it afterwards. There is no checking to see if the upload has completed successfully, this was by design to avoid the SD card filling up if DropBox is unavailable/full.

"GetFileName" takes a frame count and builds a unique filename for that moment in time.

"GetUploadPath" makes a folder name based on the day. Each day would be presented in a different folder on DropBox.

Get the command line variable (if it exists) and compare it with "-v". If no variables are included with the Python command then no output is made during the scripts operation. If want to see the output then I run it with "-v" after the name.

Then the main loop is in a "try/except" to allow the user to CTRL+c out of the infinite "while" loop. Waits a hundredth of a second to make sure we are not hammering the poor little Pi then checks the PIR status and sets a flag to say if we should be taking photos or not.

If the "capturing" flag is set then increase the frame counter, get a new file name and the correct folder name for the day. Then set a black background for the photo text annotation and set the text of the annotation to be a time stamp. Finally take the picture saving it to the unique file name and upload it to DropBox.

It has been running for 10 days with no issue other than my free DropBox account ran out of space. I have lowered the resolution and it is filling up at a much slower rate.

loading results, please wait loading animateloading animateloading animate
[More tags]
rss feed

email

root

flog archives


Disclaimer: This page is by me for me, if you are not me then please be aware of the following
I am not responsible for anything that works or does not work including files and pages made available at www.jumpstation.co.uk I am also not responsible for any information(or what you or others do with it) available at www.jumpstation.co.uk In fact I'm not responsible for anything ever, so there!

[Pay4Foss banner long]