Introduction: Pumpkin Pi Trick-or-Treat Tracker

Looking for a quick Halloween project that's useful in more ways than one? Want to put that Pi Zero WH to good use? Feel like using data to determine how much candy you'll need for next year?

Get ready to build the Pumpkin Pi Trick-or-Treat Tracker! Doubling as decoration and a people tracker, this Pi-in-a-Pumpkin changes color and streams when motion is detected. Starting from absolute scratch, this project shouldn't take you more than an afternoon to put together - just in time for Halloween!

Supplies

Step 1: Hardware Assembly

Once you have your Pi up and running, we need to connected the motion sensor & LEDs. Make sure you Pi is not connected to power at this point.

Our motion sensor requires that we connect it to 3.3V power, ground, and a data pin. I connected the 3.3V sensor pin to pin 1 of the Pi, the Ground sensor pin to pin 6 of the Pi, and the Data sensor pin to pin 16 of the Pi. The first picture shows the full connection for the Pi and the motion sensor.

LEDs are a bit more tricky than the motion sensor because they require a resistor in order to run correctly without damaging them or the Pi. I used three 220 ohm resistors but 220 and 330 ohm resistors are usually used with LEDs.

To wire everything up you can either:

  • Solder the LED legs to the resistors and then run the wires into the Pi
  • Use a breadboard and tie lines to connect everything
  • Use tie lines and electrical tape to connect everything (like I did).

We will be connecting our LED to pins 11, 13, and 15. This is a little bit trickier than the motion sensor, though, because the legs on the LED correspond to a specific color! The long leg is GND; and, on my LED at least, the legs went Red, GND, Blue, Green. I connected Blue to Pi pin 11, Green to Pi pin 13, and Red to Pi pin 15. The second picture shows the final circuit connections.

Step 2: Initial State

Sure we can see when motion's detected with the LED, but how are we going to track how many trick-or-treaters dropped by to steal our candy?

We're going to stream to a dashboard every time motion starts and stops being detected. Since this dashboard is accessible from anywhere with an internet connection, we can remotely monitor whether or not someone is approaching the front door/candy bowl.

Step 1: Register for Initial State Account
Go to https://iot.app.initialstate.com and create a new account.

Step 2: Install the ISStreamer

Install the Initial State Python module onto your Raspberry Pi. At a command prompt (don’t forget to SSH into your Pi first), run the following command:

$ cd /home/pi/
$ \curl -sSL https://get.initialstate.com/python -o - | sudo bash

Step 3: Make some Automagic

After Step 2 you will see something similar to the following output to the screen:

pi@raspberrypi ~ $ \curl -sSL https://get.initialstate.com/python -o - | sudo bash
Password:
Beginning ISStreamer Python Easy Installation!
This may take a couple minutes to install, grab some coffee :)
But don't forget to come back, I'll have questions later!

Found easy_install: setuptools 1.1.6
Found pip: pip 1.5.6 from /Library/Python/2.7/site-packages/pip-1.5.6- py2.7.egg (python 2.7)
pip major version: 1
pip minor version: 5
ISStreamer found, updating...
Requirement already up-to-date: ISStreamer in /Library/Python/2.7/site-packages
Cleaning up...

Do you want automagically get an example script? [y/N]
Where do you want to save the example? [default: ./is_example.py]

Please select which Initial State app you're using:
1. app.initialstate.com
2. [NEW!] iot.app.initialstate.com
Enter choice 1 or 2:
Enter iot.app.initialstate.com user name:
Enter iot.app.initialstate.com password: 

When prompted to automatically get an example script, type y. This will create a test script that we can run to ensure that we can stream data to Initial State. The next prompt will ask where you want to save the example file. You can either type a custom local path or hit enter to accept the default location. Finally, you'll be asked which Initial State app you are using. If you've recently created an account, select option 2, enter your user name and password. After that the installation will be complete.

Step 4: Access Keys

Let’s take a look at the example script that was created. $ nano is_example.py On line 15, you will see a line that starts with streamer = Streamer(bucket_ .... This lines creates a new data bucket named “Python Stream Example” and is associated with your account. This association happens because of the access_key=”...” parameter on that same line. That long series of letters and numbers is your Initial State account access key. If you go to your Initial State account in your web browser, click on your username in the top right, then go to “my settings”, you will find that same access key at the bottom of the page under “Streaming Access Keys”.

Every time you create a data stream, that access key will direct that data stream to your account (so don’t share your key with anyone).

Step 5: Run the Example

Run the test script to make sure we can create a data stream to your Initial State account. Run the following:

$ python is_example.py 

Step 6: Profit

Go back to your Initial State account in your web browser. A new data bucket called “Python Stream Example” should have shown up on the left in your log shelf (you may have to refresh the page). Click on this bucket and then click on the Waves icon to view the test data.

Step 3: Python Script

Create a script and open the text editor with the following command:

nano vistors.py

Copy and past the code from here to into your text editor.

Before we try to run anything, we need to make a few edits and review what's happening in our script.

import RPi.GPIO as GPIO
from time import sleep
from ISStreamer.Streamer import Streamer

# Tell the Pi we're going to use it's numbering system
GPIO.setmode(GPIO.BCM)
# Pins that D1 and LED are connected to
PIN = 23
BLUE = 17
GREEN = 27
RED = 22

# Specify our motion sensor pin as input
GPIO.setup(PIN,GPIO.IN)
# Specify our LED pins as output
GPIO.setup(RED,GPIO.OUT)
GPIO.output(RED,0)
GPIO.setup(GREEN,GPIO.OUT)
GPIO.output(GREEN,0)
GPIO.setup(BLUE,GPIO.OUT)
GPIO.output(BLUE,0) 

Lines 1-21 are for initialization. First we import the Pi's GPIO interface and a way to sleep our script. Then we import the Initial State streamer that we installed on the previous page.

GPIO.setmode specifies which numbering system we are using for the pins. Rather than physical location, we are using the Pi's numbering system. As in our diagram earlier, the pins we chose were 23, 17, 27, and 22. We then setup the motion pin as input and the LED pins as output.

# Initial State bucket name (displayed)
BUCKET_NAME = ":jack_o_lantern: Trick or Treat Tracker" 
# Initial State bucket key (hidden)
BUCKET_KEY = "trickortreat"
# Initial State access key
ACCESS_KEY = "Your_Access_Key"

# Variables that ensure we don't stream that there was or wasn't motion twice in a row
# This saves on sent events and processing power
alreadyRecordedMotion = False
alreadyRecordedNoMotion = False
counter = 0

# Initialize the Initial State Streamer
streamer = Streamer(bucket_name=BUCKET_NAME, bucket_key=BUCKET_KEY, access_key=ACCESS_KEY)

# Turn on and set the LED to yellow
GPIO.output(RED,1)
GPIO.output(GREEN,1) 

Lines 23-41 are important because we are initializing the Initial State streamer and setting the LED to yellow. Put your Initial State access key on line 28.

# Loop indefinitely
while True:
	# If the motion sensor pulls high (detects motion):
	if GPIO.input(PIN) == 1:
		print "Motion detected"
		# If we haven't streamed yet:
		if not alreadyRecordedMotion:
			counter = counter + 1
			# Set LED to red
			GPIO.output(RED,1)
			GPIO.output(GREEN,0)
			# Stream to Initial State
			streamer.log(":ghost: or :chocolate_bar:?",":chocolate_bar: Time For Treats!")
			streamer.log(":candy: Hungry Humans? :candy:",counter)
			streamer.flush()
			alreadyRecordedMotion = True
			alreadyRecordedNoMotion = False
		else:
			# Pause the script for 1 second
			sleep(1)
	else:
		print "No motion detected"
		# If we haven't streamed yet:
		if not alreadyRecordedNoMotion:
			# Set LED to yellow
			GPIO.output(RED,1)
			GPIO.output(GREEN,1)
			# Stream to Initial State
			streamer.log(":ghost: or :chocolate_bar:?",":no_pedestrians: No One Around")
			streamer.flush()
			alreadyRecordedNoMotion = True
			alreadyRecordedMotion = False
		else:
			# Pause the script for 1 second
			sleep(1) 

Lines 43-77 are the meat of the code. If motion is detected the script will check to see if " Time For Treats!" has already been streamed. If it hasn't, it's sent to Initial State and the LED is set to red; if it has, the script waits 1 second and then reads from the motion sensor again. The same goes for if no motion is detected.

It's time to test the code out! Make sure you've saved your edited file with your access key added on line 28, and then enter into the terminal:

python visitors.py 

You should see the LED come on and "No motion detected" start printing out to the command line. Try waving your hand over the motion sensor - you should now see a red light and "Motion detected" start printing!

Now to verify that our readings are being streamed to Initial State.

Step 4: Trick-or-Treat Dashboard

Head on over to Initial State and check out your dashboard! You should see a bucket called "🎃Trick or Treat Tracker". Wave your hand near the motion sensor and watch it update!

My dashboard consists of 2 Summary Tiles displaying the Last value and a Histogram of event count so I can see what times the sensor was triggered.

Here are some things to consider:

  • You probably want to divide the count of "Hungry Humans" by 2 to account for the fact that the same person will pass in front of the motion sensor on twice - on their way to your door and on their way back. You can do this with Real-Time Expressions using the equation "=math.round(([ Hungry Humans? ]/2),0)".
  • You can test how sensitive your motion sensor seems to be and place it on your sidewalk accordingly. I suggest keeping it far enough from the door that it doesn't trigger when someone's standing at the door.
  • You can also setup text alerts to tell you someone is approaching.
  • Choose a background image to give your dashboard a little spooky personality!

Step 5: Pumpkin Pi

We're going to want to start our script as soon as we power on the Pi since our only control over it will be the power button on our portable power bank. Lucky for us, this is super easy!

First off, we're going to want to add a line to our visitors.py file to pause the script for 1 minute while our Pi connects to the WiFi. This is the crude way, but it's effective. Run:

nano visitors.py 

And add sleep(60) to line 35 (between counter=0 and # Initialize the Initial State Streamer. Ctl-X, Y to save and exit. Using the service crontab we can start our script at boot:

sudo crontab -e 

Pick your favorite text editor (I like nano) and at the bottom of the file (under all of the comments), add @reboot sudo python /home/pi/visitors.py. If you named your script something else or put it in a different directory, replace /home/pi/visitors.py with the correct path. The path in my example is just the main Pi directory.

Save the file and reboot your Pi for it to take effect!

If your pumpkin is going to be sitting too far from an outlet to be plugged in, portable batteries work great! I recommend this one - the pack lasted 12 hours. Make sure the Pi can still reach your houses WiFi.

Carving a fake pumpkin to fit your project in is easy as...PUMPKIN PI.

I just cut a hole in the bottom big enough to fit my portable battery and a hole in the side that my motion sensor could peak out from! Electrical tape is my best friend. Put your Pi inside and test it out using your real-time dashboard.