Sei sulla pagina 1di 85

10 PROJECTS

FOR THE RASPBERRY PI

A RESOURCE FOR BEGINNER AND INTERMEDIATE-LEVEL MAKERS

About Initial State


See what happened.
Real-time data streaming from your
Raspberry Pi with just one line of code. It's
that easy.

Interactive data visualizations.


Visualize and mine your data in waveforms,
stacked line graphs, and statistics. Data logs
streamed in less than 1ms!

Rest easy, your data is secure.


Every data stream is secured by enterprisegrade SSL encryption from the millisecond you
stream it. While many of our user share their
data with friends and coworkers, others choose
to work privately.

So, You Own a Raspberry Pi


Welcome to the Raspberry Pi community!
Developed in the UK by the Raspberry Pi Foundation with the
intention of promoting the teaching of basic computer science in
schools, the Raspberry Pi was released to the public in February
2012.
In two years, about 4.5 million boards have been sold around the
world.
The Raspberry Pi is a hacker or maker's dream device, a credit
card-sized Linux computer with enormous educational and DIY/
hobbyist possibilities.
From adding and using temperature sensors and LED lights to
building a hamster fitness tracker, weve outlined a few of our
favorite beginner and intermediate Raspberry Pi projects.
Enjoy!

Project Chapters
1.

Getting Your Monitor to Work

2.

Taking Control of Your Keyboard Layout

3.

Pressing Buttons to Light Up LEDs

4.

Pressing Buttons to Make an LED Blink

5.

Using Pi-Plates to Add Functionality

6.

Streaming Temperature

7.

Baking a Turkey

8.

Running a Shutdown Button Script at Boot

9.

Building a Mobile GPS Streamer

10. Building a Hamster Fitness Tracker

CHAPTER
Getting Your Monitor to Work

Why Wont My Monitor Work?


New toys are exciting. Every moment not spent unpackaging and getting your toy
ready for action is a moment wasted. Thats exactly how I felt when I got my hands
on my first Raspberry Pi. Initial States ever-generous leader had provided me with
everything I needed to get started an HDMI monitor, a Bluetooth keyboard and
mouselife was looking pretty good.

I made sure everything was hooked up properly, turned on my monitor and then
powered up the Pi. Andnothing happened. Instead of the beautiful Raspberry
SVG popping up on my screen, I saw a No HDMI Input Detected message. I was
confused. I checked the HDMI cable. I checked that the Pi was actually on.
Everything was good. But everything was not good because the most important

slice of my Pi was refusing to cooperate.

Come to find out, Initial States leader wasnt overly generous the monitor was
probably as old as HDMI itself. And after a bit of research, I realized that Pis tend
to have widespread issues not working with older monitors. But Im an engineer,
and I wasnt going to let that stop me. When rebooting failed, I turned to Google
and found out about a very important config.txt file that was the answer to my
problems.

Problem #1:
The monitor is not working with the Raspberry Pi.
Fix:
Change the config.txt file
Problem #2:
NOOBS, Raspberry Pis out-of-box software that came
preloaded on my SD card

The problem with NOOBS is that, while


it does have lines in its code to help
your monitor recognize the Pis HDMI
signal, the key presses (1 for HDMI
preferred mode and 2 for HDMI safe
mode) never worked for me. And since
I couldnt see the NOOBS interface
since my monitor wasnt working I
couldnt access the config.txt file that
way.

Fix:
I decided that the OS I wanted was Raspbian. So I went and downloaded
just Raspbian (this will work for any other OS too). When I unzipped the
file, I now had access to the config.txt file! If you open it up, youll see that
the entire file is commented out:

# For more options and information see


# http://www.raspberrypi.org/documentation/configuration/config-txt.md
# Some settings may impact device functionality. See link above for details

# uncomment if you get no picture on HDMI for a default "safe" mode
#hdmi_safe=1

# uncomment this if your display has a black border of unused pixels visible
# and your display can output without overscan
#disable_overscan=1

# uncomment the following to adjust overscan. Use positive numbers if console
# goes off screen, and negative if there is too much border
#overscan_left=16
#overscan_right=16
#overscan_top=16
#overscan_bottom=16

# uncomment to force a console size. By default it will be display's size minus
# overscan.
#framebuffer_width=1280
#framebuffer_height=720

# uncomment if hdmi display is not detected and composite is being output
#hdmi_force_hotplug=1

# uncomment to force a specific HDMI mode (this will force VGA)
#hdmi_group=1
#hdmi_mode=1

# uncomment to force a HDMI mode rather than DVI. This can make audio work in
# DMT (computer monitor) modes
#hdmi_drive=2

# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display
#config_hdmi_boost=4

# uncomment for composite PAL
#sdtv_mode=2

#uncomment to overclock the arm. 700 MHz is the default.
#arm_freq=800

I went through and uncommented these lines to cover all of my bases:

# uncomment if you get no picture on HDMI for a default "safe" mode


hdmi_safe=1
# uncomment if hdmi display is not detected and composite is being output
hdmi_force_hotplug=1
# uncomment to increase signal to HDMI, if you have interference, blanking, or
# no display
config_hdmi_boost=4

Result:
The new uncommented lines worked like a charm. My monitor recognized the Pi

as soon as I booted with the newly formatted SD card.

Now you can play with your new toy!

CHAPTER
Taking Control of Your Keyboard Layout

My Keyboard Layout is Funny


Alright, so you followed my last tutorial to get your ancient (which is only 4 or 5 years
old nowadays) monitor working with your Raspberry Pi. Once you got over the initial
excitement of seeing the Pi boot, you mightve gone into the terminal and noticed
something funky going on your keyboard was not working! How on earth can you
be expected to do anything at all without a pipe* key?!
This little guy |. Dont worry, I didnt know what he was before terminal, either.

Not to worry, I can tell you whats wrong and how to fix it.

Note: We love Great Britain they gave us the Pi, after all!

Problem #1: Keyboard is not working when you boot Raspbian


Fix: Raspbians default keyboard layout is British! We need to
change it to the U.S. layout.

Problem #2:
I have no idea how to change the
keyboard layout

Fix:

This is easy-peasy, mainly because no


pipes are involved.
First, check to make sure you have
Nano. It is an amazing text editor that
works directly in your terminal.

sudo -s
apt-get install nano
If you dont have it, get it. Its awesome and will let you do this next step.
Just type in:

sudo -s
nano /etc/default/keyboard
Now we can see this little line in your keyboard layout file that says:
XKBLAYOUT=gb

That stands for Great Britain and Unattainable Pipes. Change it to:
XKBLAYOUT=us"

And save (Ctrl-X -> Y).


Now before you start spamming the backslash key and getting angry, let
your Pi know that you want it to drop the accent:
reboot

Once the system is back, you can enjoy your proper keyboard layout!

If youd like an example script to type on your newly formatted keyboard, try
our Performance Monitor you can see how hard youre making your little
board work!

CHAPTER
Pressing Buttons to Light Up LEDs

Pressing Buttons to Light up


LEDs
Ok, so youve installed the Initial State streamer, you ran our little example code,
and now youre ready to learn more about streaming and internet-enabled
development platforms!

I chose to use a Raspberry Pi for my project, but the basics can be applied to
other single-board computer platforms like BeagleBone Black, PandaBoard,
MinnowBoard, and UDOO, or even Gumstix COM and Arduino if they have been
outfitted to access the internet and can run Python.

In this little tutorial I show you how to do a couple things:

Setup a hardware circuit with LEDs and


buttons

Communicate between software and


hardware using Raspberry Pis GPIO
pins

Write a python script that translates


button presses into LED events
And most importantly.

Use the Initial State streamer to debug and monitor your code!

My Supplies

I used a Canakit so all of these pieces minus the monitor were included:

Raspberry Pi B+ w/ Raspbian loaded SD card

HDMI cable + HDMI Monitor (some way to see your Pi)

WiFi Adapter/Dongle (can use ethernet cord for hard connection instead)

Breadboard

40-pin GPIO Ribbon Cable (can use 5 individual male-to-female jumper cables instead)

40-pin T-Shaped GPIO to Breadboard Interface Board (not necessary if using jumper
cables)

2 Push Button Switches

3 LEDs (I used Red, Green and Yellow)

3 220 Ohm Resistors (to use with the LEDs; 180-2K Ohms is generally a safe range)

2 10K Ohm Resistors (to use with the buttons; 5K-100K Ohms is generally a safe
range)

The Raspberry Pi has power, ground, and programmable GPIO pins. These GPIO
pins are how we are going to communicate button presses and when we want the
LEDs to turn on or off. In the graphic below, you can see my breadboard
connections (everything is crowded at the bottom of the board due to the interface
board taking up the top 20 pins). Connection to any GPIO pin will work, but I will use
my numbering for the examples.

You want to connect:

One row of Button 1 to GPIO 23 (pin 16) and a 10K


resistor; the other end of the resistor should be
connected to ground

The other row of Button 1 to the voltage source (3.3


V)

One row of Button 2 to GPIO 24 (pin 18) and a 10K


resistor; the other end of the resistor should be
connected to ground

The other row of Button 2 to the voltage source

The short leg of the red LED to GPIO 4 (pin 7)

The long leg of the red LED to a 220 resistor; the


other end of the resistor should be connected to the
voltage source

The short leg of the yellow LED to GPIO 17 (pin 11)

The long leg of the yellow LED to a 220 resistor; the


other end of the resistor should be connected to the
voltage source

The short leg of the green LED to GPIO 27 (pin 13)

The long leg of the green LED to a 220 resistor; the


other end of the resistor should be connected to the
voltage source

The Raspberry Pi has power, ground, and programmable GPIO pins. These GPIO
pins are how we are going to communicate button presses and when we want the
LEDs to turn on or off. In the graphic below, you can see my breadboard
connections (everything is crowded at the bottom of the board due to the interface
board taking up the top 20 pins). Connection to any GPIO pin will work, but I will use
my numbering for the examples.

The first thing were going to want to do is import some libraries:

import RPi.GPIO as GPIO ## Import library that lets you control the Pi's GPIO pins
from time import sleep ## Import time for delays

Sleep is a command that ignores inputs for the specified amount of time. Youll

see how it can be used in a few lines.

As you saw earlier, making the Initial State streamer usable is as easy as:
from ISStreamer.Streamer import Streamer

Now we want to tell it where to stream:


## Streamer constructor, this will create a bucket called Double Button LED
## you'll be able to see this name in your list of logs on initialstate.com
## your access_key is a secret and is specific to you, don't share it!
streamer = Streamer(bucket_name="Double Button LED", access_key="Place Your Access Key
Here")

Every time you run a script with a bucket name a new bucket will be created,
even if that bucket name already exists in your log shelf. You can append to the
same bucket by adding the bucket_key parameter (see below). Any stream with
the same bucket_key will go to the same bucket regardless of bucket name.

streamer = Streamer(bucket_name="Double Button LED", bucket_key="double_button_led",


access_key="Place Your Access Key Here")

Its time to set up the GPIO pins. The first phrase keeps the terminal from
alerting us about GPIO pin use (since we know were using them!).
GPIO.BOARD tells the Pi that you will designate pins by their placement (i.e. the
number in the circle) instead of their name (i.e. GPIO 3). If you want to use the
latter convention, simply replace BOARD with BCM.

GPIO.setwarnings(False) ## Disables messages about GPIO pins already being in use


GPIO.setmode(GPIO.BOARD) ## Indicates which pin numbering configuration to use

GPIO.setup(16, GPIO.IN) ## Tells it that pin 16 (button) will be giving input


GPIO.setup(18, GPIO.IN) ## Tells it that pin 18 (button) will be giving input

GPIO.setup(7, GPIO.OUT) ## Tells it that pin 7 (LED) will be outputting


GPIO.setup(11, GPIO.OUT) ## Tells it that pin 11 (LED) will be outputting
GPIO.setup(13, GPIO.OUT) ## Tells it that pin 13 (LED) will be outputting
GPIO.output(7, GPIO.HIGH) ## Sets pin 7 (LED) to "HIGH" or off
GPIO.output(11, GPIO.HIGH) ## Sets pin 11 (LED) to "HIGH" or off
GPIO.output(13, GPIO.HIGH) ## Sets pin 13 (LED) to "HIGH" or off

GPIO.setup lets the Pi know which pins you are using and whether they will
receive input (buttons) or giving output (LEDs). We will set the LEDs initial

states to off.

Now comes the fun part! We need to initialize some of the parameters well
be using later:

## state - decides what LED should be on and off


## initialize to 0 or all off
state = 0

## increment - the direction of states


## initialize to 1 or increasing
inc = 1

## Set prev_input's initial value to 2


prev_input=2

And start our While loop! The code within this loop executes whenever a
statement is True. So the first If statement will execute if GPIO pin 16 (or button
1) receives input (is pressed). The increment variable designates whether the
LEDs will turn on or turn off one-by-one. The state is indicative of how many
LEDs are on currently. We also begin to insert streamer statements!

## This while loop constantly looks for button input (presses)


while True:

## When state toggle button is pressed


if ( GPIO.input(16) == True ):

## If increment is increasing, increase state by 1 each press


if (inc == 1):
state = state + 1;
## If increment is decreasing (0), decrease state by 1 each press
else:
state = state - 1;

## Reached the max state, time to decrease state


if (state == 3):
inc = 0
prev_input=1 ## Keeps a reset button phrase from executing when state shifts down to 2
streamer.log("prev_input",prev_input) ## Stream prev_input when changed
streamer.log("increment", inc) ## Stream increment when changed; "stream name", value
## Reached the min state, time to increase state
elif (state == 0):
inc = 1
prev_input=2 ## Makes all reset button phrases executable
streamer.log("prev_input",prev_input) ## Stream prev_input when changed
streamer.log("increment", inc) ## Stream increment when changed

## Define state 1
if (state == 1):
GPIO.output(7, GPIO.LOW) ## LED on
GPIO.output(11, GPIO.HIGH) ## LED off
GPIO.output(13, GPIO.HIGH) ## LED off
prev_input=2 ## Makes all reset button phrases executable
streamer.log("state",state) ## Stream current state
streamer.log("increment",inc) ## Stream current increment
streamer.log("prev_input",prev_input) ## Stream current prev_input
## Define state 2
elif (state == 2):

GPIO.output(7, GPIO.LOW) ## LED on


GPIO.output(11, GPIO.LOW) ## LED on
GPIO.output(13, GPIO.HIGH) ## LED off
prev_input=2 ## Makes all reset button phrases executable
streamer.log("state",state) ## Stream current state
streamer.log("increment",inc) ## Stream current increment
streamer.log("prev_input",prev_input) ## Stream current prev_input
## Define state 3
elif (state == 3):
GPIO.output(7, GPIO.LOW) ## LED on
GPIO.output(11, GPIO.LOW) ## LED on
GPIO.output(13, GPIO.LOW) ## LED on
streamer.log("state",state) ## Stream current state
streamer.log("increment",inc) ## Stream current increment
streamer.log("prev_input",prev_input) ## Stream current prev_input
## If the state equals anything other than 1, 2, or 3 (0)
else:
GPIO.output(7, GPIO.HIGH) ## LED off
GPIO.output(11, GPIO.HIGH) ## LED off
GPIO.output(13, GPIO.HIGH) ## LED off
streamer.log("state",state) ## Stream current state
streamer.log("increment",inc) ## Stream current increment
streamer.log("prev_input",prev_input) ## Stream current prev_input

streamer.log("button_1", "pressed") ## Stream which button was pressed


sleep(0.2); ## Wait 0.2 second before looking for another button input

This next if statement executes whenever GPIO pin 18 (or button 2) is pressed. It
will either turn all of the LEDs on or off depending on their current state.

## When reset button is pressed


if ( GPIO.input(18) == True ):

## If 1 or 2 LEDs are on
if (state == 1 or 2 and prev_input!=1):
GPIO.output(7, GPIO.LOW) ## LED on
GPIO.output(11, GPIO.LOW) ## LED on
GPIO.output(13, GPIO.LOW) ## LED on
prev_input=1 ## Keeps this phrase from executing when all LEDs are already on
state=3 ## Change state to 3
inc=0 ## Change increment to decreasing
streamer.log("state",state) ## Stream current state
streamer.log("increment",inc) ## Stream current increment
streamer.log("prev_input",prev_input) ## Stream current prev_input
#streamer.log("phrase",1) ## used to see when each phrase was executing

## If no LEDs are on
elif (state == 0 and prev_input!=0):
GPIO.output(7, GPIO.LOW) ## LED on
GPIO.output(11, GPIO.LOW) ## LED on
GPIO.output(13, GPIO.LOW) ## LED on
prev_input=1 ## Keeps this phrase from executing immediately after the state is set to 0
state=3 ## Change state to 3
inc=0 ## Change increment to decreasing
streamer.log("state",state) ## Stream current state
streamer.log("increment",inc) ## Stream current increment
streamer.log("prev_input",prev_input) ## Stream current prev_input
#streamer.log("phrase",2) ## used to see when each phrase was executing
## If all LEDs are on
elif (state == 3 and prev_input!=0):
GPIO.output(7, GPIO.HIGH) ## LED off
GPIO.output(11, GPIO.HIGH) ## LED off
GPIO.output(13, GPIO.HIGH) ## LED off
prev_input=0 ## Keeps this phrase from executing immediately after the state is set to 3
state=0 ## Change state to 0
inc=1 ## Change increment to increasing
streamer.log("state",state) ## Stream current state
streamer.log("increment",inc) ## Stream current increment
streamer.log("prev_input",prev_input) ## Stream current prev_input
#streamer.log("phrase",3) ## used to see when each phrase was executing

streamer.log("button_2(bullseye)", "pressed") ## Stream which button was pressed


sleep(0.2); ## Wait 0.2 second before looking for another button input

And finally we need to safely wrap up everything with a closing statement:


streamer.close()

Now we can run the code! Pressing Button 1 should light the LEDs up one at a
time, while pressing Button 2 should turn them all on if 0, 1, or 2 LEDs were on or

all off if all 3 were on.

You can also go to your Initial State account to see your new Double Button
LED bucket! After pressing my buttons a few times, this is what I had to look at:

If you like the idea of streaming your


data directly from your device but
dont have an Initial State account
yet, sign up for free here.

CHAPTER
Pressing Buttons to Make an LED Blink

Use Button to Make an LED


Blink
A while ago, I showed you how to configure three LEDs and two buttons using the
Raspberry Pis GPIO pins. Once youve gotten the hang of buttons and how
programmable pins work, there are all sorts of cool applications.

Just to show you another neat thing youre now capable of, Im going to walk you
through setting up an LED that starts blinking when you press a button. Learning
how to start and stop an action with button presses and make something alternate
states on its own is great for tackling more complex projects!

Here Im going to show you how to

Start and stop a blinking LED with the push


of a button

Use Initial State to broadcast a message


when the button is ready to be pressed and
then register each time the LED goes on
and off before the button is pressed again.

I used a Canakit so all of these pieces minus the monitor,


keyboard, and mouse were included:

Raspberry Pi B+ w/ Raspbian loaded SD card

HDMI cable + HDMI Monitor + Bluetooth Keyboard/Mouse

WiFi Adapter/Dongle (can use ethernet cord for hard connection instead)

Breadboard

40-pin GPIO Ribbon Cable (can use 5 individual male-to-female jumper cables
instead)

40-pin T-Shaped GPIO to Breadboard Interface Board (not necessary if using jumper
cables)

3 Breadboard Tie Lines

1 Push Button Switch

1 LED (I used Blue)

1 220 Ohm Resistors (to use with the LEDs; 180-2K Ohms is generally a safe range)

1 10K Ohm Resistors (to use with the buttons; 5K-100K Ohms is generally a safe
range)

You want to connect:

One row of the button to GPIO 23 (pin 16) and


a 10K resistor; the other end of the resistor
should be connected to ground

The other row of the button to the voltage


source (3.3 V)

The short leg of the blue LED to GPIO 4 (pin 7)

The long leg of the blue LED to a 220 resistor;


the other end of the resistor should be
connected to the voltage source

Now for the software part! If you havent installed the Initial State Streamer yet, its
super fast and easy.
Instructions
1.

Create an Access Key in your Initial State account (can do on the landing page
under Streaming Access Keys). If you dont have an account you can sign up at
https://www.initialstate.com/app/#/register!

2. Turn on your device and make sure you have an internet connection.
3. Type this command into the command line:

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

4.Follow the prompts if you say Y to the Create an example script? prompt,
then you can designate where youd like the script and what youd like to name it.
Your Initial State username and password will also be requested so that it can
autofill your Access Key. If you say n then a script wont be created, but the
streamer will be ready for use.
5. Either use your example script to get your Access Key or create one from
scratch and start streaming!

Import the GPIO library, time, and the streamer.

import RPi.GPIO as GPIO ## Import library that lets you control the Pi's GPIO pins
from time import sleep ## Import time for delays
from ISStreamer.Streamer import Streamer ## Import the Initial State streamer

Designate the name of your stream and which Initial State account it should go to.
## Streamer constructor, this will create a bucket called Button Blink
## you'll be able to see this name in your list of logs on initialstate.com
## your access_key is a secret and is specific to you, don't share it!
streamer = Streamer(bucket_name=Button Blink", access_key="Your Access Key Here")

Setup your GPIO pins and initialize some variables.

GPIO.setwarnings(False) ## Disables messages about GPIO pins already being in use


GPIO.setmode(GPIO.BOARD) ## Indicates which pin numbering configuration to use

pinNumLED = 7
pinNumBTN = 16
GPIO.setup(pinNumLED,GPIO.OUT) ## Tells it that pinNumLED will be outputting
GPIO.setup(pinNumBTN,GPIO.IN) ## Tells it that pinNumBTN will be giving input

## Initialize btnOn and prev_input


btnOn = False
prev_input = 1

Stream your first message!

## Stream a message when the button is ready to press


streamer.log("msg","Press the Button!")

Run a while loop to check for button presses and either blink or stop the LED when it
detects one. Note that the sleep sometimes causes button presses not to register
while the LED is blinking. Pressing and holding the button for 1 second should do
the trick.

while True:
try:
input = GPIO.input(pinNumBTN)

if ((not prev_input) and input):


btnOn = not btnOn
prev_input=input
sleep(0.05)

## When the button is pressed, start toggling the LED between


## HIGH and LOW with a 0.5s interval between
if btnOn:
GPIO.output(pinNumLED,GPIO.HIGH)
streamer.log("LED","Off") ## Stream that the LED is Off
sleep(0.5)
GPIO.output(pinNumLED,GPIO.LOW)
streamer.log("LED","On") ## Stream that the LED is On
sleep(0.5)
else:
GPIO.output(pinNumLED,GPIO.HIGH)

Pressing Cntl-C will exit the while loop and stream the final message.
streamer.close() makes sure that all of the logs are streamed before the script
finishes.

except KeyboardInterrupt:
break

## Stream a message when the loop has been broken


streamer.log("msg","Finished!")
streamer.close()

In Initial State you can see when the button was first pressed and when the LED turns

on and off.

If you like the idea of streaming your


data directly from your device but
dont have an Initial State account
yet, sign up for free here.

CHAPTER
Using Pi-Plates to Add Functionality

Using Pi-Plates
If you thought that Raspberry Pis were cool, just wait till you see all of the things you
can add to them to expand their functionality. And if you already knew about all of
the things you can add to them, just wait till you see this one!

Pi-Plates are stackable Raspberry Pi add-on circuit boards that come with all sorts of
goodies. The one I have pictures of here is the ppDAQC board, and it comes with 7
digital outputs, 8 analog to digital inputs, 8 digital inputs, 2 analog outputs and 7
indicator LEDs. My other favorite features are the programmable pushbutton and
bicolor LED (but thats just because Im easily entertained).

To show you how easy it is to set this bad boy up, Im going to tell you how right
now. The Pi-Plate just stacks on top of the Pis GPIO pins. It makes use of the
Pis SPI feature, so make sure that its enabled by entering:
sudo nano /etc/modprobe.d/raspi-blacklist.conf

And commenting out blacklist spi-bcm2708.

If you had to comment it out, reboot your Pi (sudo reboot). spi_bcm2708

should now be listed if you enter lsmod in the command line.

If you dont already have the SPI and GPIO libraries, youll need to update

and install them:


sudo apt-get update
sudo apt-get install python-dev
sudo apt-get install python-rpi.gpio

And now we want to make the ports accessible in Python:

mkdir python-spi
cd python-spi
wget https://raw.github.com/doceme/py-spidev/master/setup.py
wget https://raw.github.com/doceme/py-spidev/master/spidev_module.c
sudo python setup.py install

Finally, the ppDAQC module needs to be installed. It uses pip, so if you dont already have
that, be sure to run the first line:

sudo apt-get install python-pip


sudo pip install http://pi-plates.com/downloads/pi-plates.tar.gz

Now lets run a Hello World! The guys at Pi-Plates provide a nice beginner
script that outputs Hello World in ASCII through the built-in LEDs. I
thought this was pretty neat, so I also inserted some streamer statements
so I could see the ASCII values of each letter. Want to try out Initial States
data streamer? See how to install it below.

Instructions:

1. Create an Access Key in your Initial State account (can do on the landing page
under Streaming Access Keys). If you dont have an account you can sign up here!

2. Turn on your device and make sure you have an internet connection.

3. Type this command into the command line:

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

4. Follow the prompts if you say Y to the Create an example script?


prompt, then you can designate where youd like the script and what youd
like to name it. Your Initial State username and password will also be
requested so that it can autofill your Access Key. If you say n then a
script wont be created, but the streamer will be ready for use.

5. Either use your example script to get your Access Key or create one
from scratch and start streaming!
The script is very simple we just import the ppDAQC module, the
ISStreamer module and time. Then we set up the streamer and a while
loop that converts each letter in Hello World into an ASCII value that is
output to the Pi-Plates LEDs.
## Import the Pi-Plates ppDAQC module
import piplates.ppDAQC as ppDAQC
## Import time for delays
import time
## Import the ISStreamer module
from ISStreamer.Streamer import Streamer
## Streamer constructor, this will create a bucket called Computer Performance
## you'll be able to see this name in your list of logs on initialstate.com
## your access_key is a secret and is specific to you, don't share it!
streamer = Streamer(bucket_name="Pi-Plates Hello World",access_key="[Your Access Key]")

msg='Hello World'
msgLen = len(msg)

## This will run until you interrupt it (Ctrl-C)


while(1):
for i in range(0,msgLen):
value=ord(msg[i])
streamer.log("Letter",msg[i])
ppDAQC.setDOUTall(0,value)
streamer.log("ASCII value", value)
time.sleep(.5)

streamer.close()

The while loop will run until you interrupt it with Ctrl-C.

You can see the Pi-Plates built-in LEDs lit up in the top left corner of the board. On the right you can see how
ASCII value changes with each letter inside of Initial State.

Now youve made your board light up! Lets use my other favorite built-in feature
the programmable button. The Pi-Plate makes it very very easy to turn this button

into the one thing I always wish my Raspberry Pi had a shutdown button!

First you need to install a program that runs in the background of your Pi called
ppPower. This is easy to do with these commands:

wget http://pi-plates.com/downloads/ppPower-1.00.tar.gz
tar -xzf ppPower-1.00.tar.gz
cd ppPower-1.00
sudo ./install-ppPower

Now you just need to reboot your Pi (sudo reboot), and associate the button with this program. Enter Python with sudo python and

enter the following lines:

import piplates.ppDAQC as ppDAQC


ppDAQC.enableSWpower(0)

Aaaaaaaand it was that easy to set up a functioning shutdown button! It will work
every time you turn on your Pi with the Pi-Plate attached from here on out. The PiPlate even provides a convenient LED indicator that turns orange while the Pi is
shutting down and red when it is safe to remove the power.
To read more about the button and
what this particular Pi-Plate can do,

be sure to visit this users guide.

Thats all for now on the Pi-Plate,


but be on the lookout for future
tutorials this little guy is
waaaaaay more powerful than what
Ive shown!

Here you can see the magical blue button

CHAPTER
Streaming Temperature

Stream Temperature from Your


Raspberry Pi

Hello World! This is likely the output of the first program you ever wrote when
learning how to code. Setting up a device to stream temperature data is quickly
becoming the de facto Internet of Things (IoT) Hello World! project. If printing
Hello World! the first time was a long, frustrating task, you might have never written
another program. Your first IoT project should only put a big ol smile on your face.
This fun, easy project will introduce you to the wonderful world of IoT data streaming.

A video tutorial of this entire project can be found at http://youtu.be/HMqPbfvCshs.

Here are the supplies you will need

An internet connected Raspberry Pi or your single-board computer of choice.

A DS18B20 temperature sensor (https://www.adafruit.com/product/381).


A breadboard for wiring up a simple circuit (in the Adafruit Pi starter kit).

A 4.7K to 10K resistor (also in the Adafruit Pi starter kit).

The DS18B20 temperature sensor works well with the Raspberry Pi because it has a
digital output, and the Pi has no on-board analog to digital convertors (ADC). Raspbian
includes an interface to read the output of the sensor. We just have to write a little
code to grab and parse out the temperature. Adafruit has a great tutorial here (and
here for the PDF version) for using the DS18B20 that we are simply going to follow and
modify to stream the temperature instead of just outputting it to the screen.
The hardware setup is simple. DS18B20 red wire to 3.3V. Black wire to GND. Blue
wire to a pull-up resistor and to GPIO pin 4 of your Pi.

To start the temperature sensor read interface we need to run two


commands. Go to a command prompt on your Pi or SSH into your Pi.

Type the following commands:


sudo modprobe w1-gpio
sudo modprobe w1-therm

The output of your temperature sensor is now being written to a file on your Pi. To
find that file,
cd /sys/bus/w1/devices

In this directory, there will be a sub-directory that starts with 28-. What comes after
the 28- is the serial number of your sensor. cd into that directory. Inside this
directory, a file named w1_slave contains the output of your sensor. The contents of

this file will look something like this:


a2 01 4b 46 7f ff 0e 10 d8 : crc=d8 YES
a2 01 4b 46 7f ff 0e 10 d8t=26125

The number after t= is the number we want. This is the temperature in 1/1000
degrees Celsius (in the example above, the temperature is 26.125 C). We just need
a simple program that reads this file and parses out that number. Lucky for us,
Adafruit already created a Python script for us that does just this and outputs the
temperature to the screen. Create a new file on your Pi (e.g. temperature.py) and

copy-paste the following code in.


import os
import glob
import time

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')
base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'
def read_temp_raw():
f = open(device_file, 'r')
lines = f.readlines()

f.close()
return lines

def read_temp():
lines = read_temp_raw()
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_temp_raw()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
temp_f = temp_c * 9.0 / 5.0 + 32.0
return temp_c, temp_f

while True:
print(read_temp())
time.sleep(.5)

Run this script (sudo python temperature.py) to see the output of your temperature

sensor on the screen.

This is the point where we deviate from the Adafruit tutorial. Sending temperature to
the screen is boring. We want to stream this data to somewhere we can see not
only the current temperature but a history of captured temperature data (plus, who
wants to read a bunch of temperatures as text; we want a pretty data visualization).
First install the Initial State streamer to give our temperature measurements a
destination to go to (go here for instructions on setting up the Initial State streamer; it
is super easy and takes less than two minutes). We are going to modify the script
above to stream the temperature to our Initial State account instead of outputting it to
the screen. Here are the modifications:
import os
import glob
import time
from ISStreamer.Streamer import Streamer
streamer = Streamer(bucket_name="Temperature Stream", access_key="PUT YOUR ACCESS KEY
HERE")

os.system('modprobe w1-gpio')
os.system('modprobe w1-therm')

base_dir = '/sys/bus/w1/devices/'
device_folder = glob.glob(base_dir + '28*')[0]
device_file = device_folder + '/w1_slave'

def read_temp_raw():
f = open(device_file, 'r')
lines = f.readlines()
f.close()
return lines

def read_temp():
lines = read_temp_raw()
while lines[0].strip()[-3:] != 'YES':
time.sleep(0.2)
lines = read_temp_raw()
equals_pos = lines[1].find('t=')
if equals_pos != -1:
temp_string = lines[1][equals_pos+2:]
temp_c = float(temp_string) / 1000.0
return temp_c

while True:
temp_c = read_temp()
temp_f = temp_c * 9.0 / 5.0 + 32.0
streamer.log("temperature(C)", temp_c)
streamer.log("temperature(F)", temp_f)
time.sleep(.5)

You will need to copy+paste the access key associated with your Initial State
account in between the quotes on line 6 where it says PUT YOUR ACCESS KEY
HERE. You can find your access key under your account settings or on the landing

page once you log into your account.

These are the modifications we just made:

On line 4, we imported the Initial State data streamer module.

On line 6, we created a new bucket called Temperature Stream and associated it


with our account via our access key.

On line 30, we modified the read_temp() function to only return the


temperature in Celsius.

On line 34, we converted the output of read_temp() to fahrenheit.

On lines 35 and 36, we streamed the two temperatures.

Run the modified script (sudo python temperature.py or if you want to set
this to run uninterrupted for a long time, you might want to use the nohup
command nohup sudo python temperature.py > tmp.txt &). I put my
temperature sensor on ice then warmed it back up again in my hand to test
it out. Go to your Initial State account and a new log will show up in your
log shelf called Temperature Stream. View this in Waves or Lines to see
your data streaming in real-time. Here is what my data looked like in Lines.

Now that you can capture and stream temperature data, you have the tools to
stream anything you can capture sensor outputs, software variables, hardware
events, button presses, doors opening, your heart rate, gps data, your hamsters
activity, anything.

CHAPTER
Baking a Turkey

Use a Respberry Pi Help You


Bake a Turkey
Since everything is getting connected to the Internet of Things, it is time for your
turkey to get in on the IoT action. In this simple tutorial, I will show you how capture
the temperature of your bird as it cooks in the oven and stream it to a data
visualization in your web browser. Hi-tech turkey!

e the
r
a
e
Her
s you
e
i
l
p
sup
eed
will n

An internet connected
Raspberry Pi or your singleboard computer of choice

Vernier Go!Temp USB


temperature probe

Thermal shield tape

The Vernier Go!Temp probe has a temperature range of -20C 115C (-4F
239F), convenient since we want our turkey to reach an internal temperature of
71C (160F). However, you do not want to expose the plastic base or cord of the
Go!Temp probe to the ovens high temperatures. This is where the thermal shield
tape comes in. Thoroughly wrap all of the probes exposed plastic that will be inside
of the oven in the thermal shield tape to keep it safe. The wrapped, shielded cord
and Go!Temp probe are the only things that will go in the oven with your turkey
(please do not put your Raspberry Pi in the oven).

Plug your Go!Temp probe into your USB port and start your Pi. At a command
prompt, type lsusb to verify that your Pi sees the probe:

pi@raspberrypi ~ $ lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 08f7:0002 Vernier EasyTemp/Go!Temp
Bus 001 Device 004: ID 148f:5370 Ralink Technology, Corp. RT5370 Wireless Adapter
Bus 001 Device 005: ID 046d:c534 Logitech, Inc.

One of the devices connected should say Vernier EasyTemp/Go!Temp. Once


connected, your Go!Temp probe is going to write data to a file, /dev/ldusb0. Verify
that file is present (type ls -l /dev/ldusb0 at the command prompt).

That completes the hardware setup. For the software setup, first install the Initial
State streamer (instructions previously laid out in this eBook) to give your captured
temperature readings a destination to go to. Create a new file on your Raspberry Pi
(e.g. turkey_temp.py) and copy+paste the code below into it. You will need to copy
+paste the access key associated with your Initial State account in between the
quotes on line 6 where it says PUT YOUR ACCESS KEY HERE. You can find your
access key under your account settings or on the landing page once you log into
your account. The code below is all of the code that you will need.

from ISStreamer.Streamer import Streamer


import time
import struct

# Streamer constructor, this will create a bucket called Turkey Temperature


streamer = Streamer(bucket_name=Turkey Temperature", access_key="PUT YOUR ACCESS KEY
HERE")

# Stream message
streamer.log("Turkey Says", "Gobble Gobble")

targetTemp = 160
targetReached = False

while True:
# Set sample interval to 5 seconds
time.sleep(5.0)

# Read 8 bytes from ldusb0 and unpack them


# little endian format
# data 0: 1-Byte Sample Count
# data 1: 1-Byte Sequence Number
# data 2, 3, 4: 2-Byte Temperature Samples
ldusb = open("/dev/ldusb0")
raw = ldusb.read(8)
ldusb.close()
data = list(struct.unpack("<BBHHH", raw))

# Average together the three temperature samples and apply transform: C = Average/126.74 - 5.4
cel = (data[2] + data[3] + data[4]) / 3 / 126.74 - 5.4
fahr = (9.0/5.0 * cel) + 32.0
# Adjusted temperature factor determined empirically
fahrAdj = fahr * 1.16

# Stream it
streamer.log("Temperature(F)", fahrAdj)
if fahrAdj > targetTemp and not targetReached:
streamer.log("Turkey Says", "I am cooked!!")
targetReached = True

Line 6 sets up the destination bucket for our data stream. We will name the bucket
Turkey Temperature. Every time you run this script, a new bucket named Turkey
Temperature will be created under your Initial State account (identified by your
access key), and all data generated from that script run will be contained there. Line
9 streams the first message to the newly constructed stream.

Reading the temperature from the Go!Temp probe (lines 16-32) follows the guide
given at http://finninday.net/wiki/index.php/Vernier_Go_Temp_USB_device_in_Linux.
Every five seconds, eight bytes are read from /dev/ldusb0. Within these eight bytes
are three 2-byte temperature readings from the probe. However, these readings
need to be converted to Celsius/Fahrenheit. After testing the conversion equation
given in the finninday.net tutorial, I realized that my Go!Temp required a bit more
calibration tuning to be accurate. I tested the reading on a few different temperatures
and empirically determined the readings were off by a factor of 1.16 (hence the
adjustment on line 32). I recommend doing similar tests on your Go!Temp probe and
adjusting the conversion accordingly.

Streaming the calculated temperature happens on line 35. If you want to change
how often the temperature is captured and streamed, change the sleep time on line
16.

We are ready for a test run. A good test to run is to capture the temperature change
inside your oven when you preheat it. This will ensure that everything is working
before you mess with your turkey. Set your preheat to something less than 115C
(239F). Do not preheat more than 150C (302F) or you will damage your Go!
Temp probe. Be careful to only put the thermally wrapped and shielded portion of
the probe in the oven and start the preheat cycle. Run the python script at the
command prompt (type sudo python turkey_temp.py).

Log into your Initial State account and a new log will pop up in your log shelf called
Turkey Temperature. View this in Waves or Lines to see your temperature changes.
My test run is shown above when I used my ovens fast preheat option. It took my
oven 6.58 minutes to reach 256F where it then settled back to the target 240F. I
found it Interesting that this option overshoots the target then settles back down. I
decided to do a second test run using my ovens normal preheat option for
comparison. This was a much more surprising result.

I learned that my oven is a liar. After 11 minutes, my oven beeped to tell me that it was
preheated to 240F. The temperature reading was only 184F. For the next 10
minutes, it continued to preheat until it stabilized at 230F. Huh? I have a hard enough
time cooking as it is. I do not need any additional help from my oven to sabotage
dinner.
Once everything is working, you are ready to cook. You will want to place the Go!
Temp probe in the thigh of the turkey but do not touch the bone (b/c the bone heats up
faster than the meat). A nice guide on exactly where to place a meat thermometer in a
turkey can be found at http://karyosmond.com/where-do-you-stick-thermometerturkey. Use a small knife or something sharp as a guide for your probe. Did I mention
that the only thing that should be in the oven besides your turkey is the thermally
wrapped portion of your Go!Temp probe and not your Raspberry Pi? Please dont kill a
perfectly good Pi. You are ready to cook and stream. Once you see that your turkey
has reached its target temperature (160F to 175F depending on whose advice you
take), your bird is cooked. Bon Apptit
**Note This tutorial pushes the Go!Temp probe to its temperature limits. If you cook
your turkey at an oven temperature higher than 150C (302F), your Go!Temp probe
may die. Follow all directions and restrictions listed in your Go!Temp probes
instruction manual.

CHAPTER
Running a Shutdown Button
Script at Boot

Run Shutdown Button Script


at Boot
Alright, so I showed you how to use buttons and LEDs with the Raspberry Pi now
were going to move on to something a little more advanced. Ever wanted one of your
scripts to start running as soon as your Pi boots up? Getting tired of having to type
the shutdown command into the terminal whenever you want to safely power down
your Pi or have your Pi powering a project so that you cant type into it? Want to know
how long your Pis been running during a certain experiment or application?

If you answered yes to any of those questions, this tutorial has got you covered!

You will learn how to

Start running a script as soon as the Pi

boots

Make any command you want execute


when you press your button
(particularly the shutdown command in

this example)

Use an LED as an indicator that your


script is running in the background

Aaaaaaaand

Use Initial State to track how long you use your Raspberry Pi from boot to
shutdown

Get a behind-the-scenes look at how Initial State helped me discover something


very interesting about how the Pi tracks time

Overcome this time-tracking issue

I used a Canakit so all of these pieces minus the monitor, keyboard, and mouse were included:

Raspberry Pi B+ w/ Raspbian loaded SD card

HDMI cable + HDMI Monitor + Bluetooth Keyboard/Mouse

WiFi Adapter/Dongle (can use ethernet cord for hard connection instead)

Breadboard

40-pin GPIO Ribbon Cable (can use 5 individual male-to-female jumper cables
instead)

40-pin T-Shaped GPIO to Breadboard Interface Board (not necessary if using


jumper cables)

3 Breadboard Tie Lines

1 Push Button Switch


1 LED (I used Green)

1 220 Ohm Resistors (to use with the LEDs; 180-2K Ohms is generally a safe
range)

1 10K Ohm Resistors (to use with the buttons; 5K-100K Ohms is generally a
safe range)

You want to
connect

One row of the button to GPIO 23 (pin 16)


and a 10K resistor; the other end of the
resistor should be connected to ground

The other row of the button to the voltage


source (3.3 V)

The short leg of the green LED to GPIO 4


(pin 7)

The long leg of the green LED to a 220


resistor; the other end of the resistor should
be connected to the voltage source

Now were going to go over the script. I named mine offbutton.py.


The first thing youre going to want to do is import the Pis RPi.GPIO library, os to send
commands to execute in the terminal, exit so that the script quits once the results of the
button push are done executing, and sleep for waiting before the next action.

import RPi.GPIO as GPIO ## library that lets you control the Pi's GPIO pins
import os ## allows us to talk to the system like in the terminal
from sys import exit ## allows us to use "exit"
from time import sleep ## allows us to use "sleep"

If you havent imported the GPIO module yet, youll need to enter sudo apt-get install
python-rpi.gpio into the terminal and let it install. The only other import that requires
installation is the Initial State streamer. If you havent installed it yet, its super easy and
takes less than 2 minutes (instructions written in earlier tutorials).

## allows us to use the Initial State streamer


from ISStreamer.Streamer import Streamer

## designate bucket name and individual access_key


## if the bucket name already exists in association with the access_key,
## then the data will append to that bucket
## if the bucket name does not already exist, then a new bucket will be created
## the access_key tells Initial State which account to send the data to
streamer = Streamer(bucket_name=Shutdown", access_key="[Your Access Key Here]")

Now we need to get the GPIO pins in order.

GPIO.setwarnings(False) ## disables messages about GPIO pins already being in use


GPIO.setmode(GPIO.BOARD) ## indicates which pin numbering configuration to use

GPIO.setup(16, GPIO.IN) ## tells it that pin 16 (button) will be giving input


GPIO.setup(7, GPIO.OUT) ## tells it that pin 7 (LED) will be outputting
GPIO.output(7, GPIO.HIGH) ## sets pin 7 (LED) to "HIGH" or off

Time to initialize some variables. i is going to keep track of how many times the

LED blinks while our script is running.

## set i's initial value to 0


i=0

## set prev_input's initial value to 0


prev_input=0

This while loop will stream a message when it is running and wait for a button
press. The first if statement will keep a status LED blinking as long as the button
has not been pressed. The else statement will run sudo shutdown -h now as if it
had been entered in the command line. You can change this to be a different
command if you want.

Note: Because of the sleep, you may have to press and hold the button
for half a second to make sure the press is picked up.

## this while loop constantly looks for button input (presses)


while True:
streamer.log("msg","Ready for button input") ## stream message
## if no button press
if (GPIO.input(16) == False and prev_input!=1):
i=i+1 ## iteration count increases by 1
streamer.log("iteration",(i)) ## stream current iteration
GPIO.output(7,True) ## switch on pin 7 (LED)
sleep(0.5) ## wait for 0.5 second
GPIO.output(7,False) ## switch off pin 7 (LED)
sleep(1) ## wait for 1 second

## when button is pressed


else:
GPIO.output(7,GPIO.HIGH) ## turn pin 7 (LED) off
## script to be called
os.system("sudo shutdown -h now") ## shuts down Pi
streamer.log("msg","Script has been called")
## keeps script from executing the "if" section while button is unpressed
## after it has been pressed
prev_input=1
streamer.close() ## send any messages left in the streamer

Adding exit() at the end will stop the script. If you remove it along with prev_input=1,
the LED will resume blinking and you can press the button to execute the same
command again.
exit() ## terminates this script

Now, to call this script automatically!

There are a couple of ways that you can run a script at a certain time or when something
specific happens. A very easy way to do this is with Cron, a tool that comes ready to use
on Unix systems (like the Pi!). Cron allows you to specify minute, hour, day of month,
month of year and day of week. A more advanced method that also allows you greater
freedom to designate when your script is run is by creating an init (initialization) file.

Because I only needed my script to start at boot, I chose to use Cron. While init files do
allow you greater control, they are much more complicated to write. If youd like to use

an init file, you can see how to here.

Getting to the file you need to edit is as easy as typing


sudo crontab -e

In your terminal and hitting enter. You will see a file pop up with a lot of comments. At
the bottom of this file youll want to add the line
@reboot sudo python /home/pi/Streamer/offbutton.py

@reboot tells Cron to execute the line following it once the system has booted up. My
file is named offbutton.py and it is located in my Streamer folder. Youll want to replace
those with the name and location of your file. If its just in the main folder on the Pi, its
location is /home/pi/. Whenever you dont want the script to run just comment out the
line with # and save the file.
Note: You do need to reboot the Pi before this new Crontab will take effect.
Since our script also starts at boot, we had to do this anyways!

The first time I ran this script, it worked beautifully. I saw the LED start flashing a bit
after the Pi had started, and when I pressed the button, my Pi safely shutdown. I then
went over to Initial State to make sure that everything was streaming correctly.

Check out my
visualization

As may be able to tell, something funny is going on! It looks like the code is stuck on
iteration 5 for about 90 seconds. But thats strange because I never noticed the LED
blinking irregularly, and I dont even think that it takes the Pi that long to startup. I
consulted Initial States resident expert (our backend developer, David Sulpy), and he

thought that it might be a time stamping issue. I investigated further, and he was right!!

Turns out that most (if not all) computers utilize a Network Time Protocol daemon (NTP)
to synchronize their clocks over a network since theyre generally not very good at
keeping time themselves. The Pi makes use of this to ensure that, after being
shutdown for an unknown amount of time, it displays the correct time. However, this

means that at boot the Pi thinks its the wrong time.


So, what exactly are we seeing when the iteration counter sticks at 5? We are seeing
that the Pi starts running our script before it has updated its time. That 90 second gap
is not a physical 90 second period but a 90 second difference between the time the Pi

thought it was and the time the NTPD told the Pi it actually is.

Its good to know that something with our streamer isnt broken, but how do we get ride
of that apparent time skip? Well, we can use a python library called psutil to look for the
NTPD process before starting the main part of our script that way we know that the
time has already been updated. If you dont have psutil installed already, install it by
entering
sudo pip install psutil

into the terminal.

First, lets import psutil at the beginning with our other imports:
import psutil ## allows us to look at processes on the Pi

Next were going to want to initialize two new parameters: counter to regulate how long
we look for the NTPD process and found_ntpd. Do this before the while loop, where we
initialized i and prev_input.

## set counter's initial value to 0


counter = 0
## set found_ntpd's initial value to False
found_ntpd = False

Now we need to add a new while loop. This loop will look for ntpd in the list of
processes that psutil.process_iter() returns. If it doesnt find NTPD before the counter
reaches 60 (60 seconds based on our sleep time), then found_ntpd will be set to True
so that the next while loop will run. You want to insert the following code before the
previous while loop:

## this while loop looks to see if NTPD has been executed yet
while found_ntpd == False:
## use psutil to iterate through a list of current processes
for proc in psutil.process_iter():
## only execute if "ntpd" is found
if proc.name() == "ntpd":
streamer.log("msg","Found NTPD") ## stream alert that ntpd was found
streamer.log("psutil_msg",proc.status()) ## stream process status of ntpd; "stream name",
value
found_ntpd=True ## change variable to True to exit this loop
## assume that ntpd has already run if not found in 60 seconds
elif counter>=60:
streamer.log"msg","Search for NTPD timeout") ## stream alert that 60 seconds passed
before ntpd was found
found_ntpd=True ## change variable to True to exit this loop
else:
counter = counter + 1 ## add to the counter to track time passed
streamer.log("counter",counter) ## stream current counter value
sleep(1) ## wait for 1 second

And change the second while loop to


while found_ntpd == True:

Below is the complete new code.

import RPi.GPIO as GPIO ## library that lets you control the Pi's GPIO pins
import os ## allows us to talk to the system like in the terminal
from sys import exit ## allows us to use "exit"
from time import sleep ## allows us to use "sleep"
import psutil ## allows us to look at processes on the Pi

## allows us to use the Initial State streamer


from ISStreamer.Streamer import Streamer

## designate bucket name and individual access_key


## if the bucket name already exists in association with the access_key,
## then the data will append to that bucket
## if the bucket name does not already exist, then a new bucket will be created
## the access_key tells Initial State which account to send the data to
streamer = Streamer(bucket_name=Shutdown", access_key="[Your Access Key Here]")

GPIO.setwarnings(False) ## disables messages about GPIO pins already being in use


GPIO.setmode(GPIO.BOARD) ## indicates which pin numbering configuration to use

GPIO.setup(16, GPIO.IN) ## tells it that pin 16 (button) will be giving input


GPIO.setup(7, GPIO.OUT) ## tells it that pin 7 (LED) will be outputting
GPIO.output(7, GPIO.HIGH) ## sets pin 7 (LED) to "HIGH" or off

## set counter's initial value to 0


counter = 0

## set found_ntpd's initial value to False


found_ntpd = False

## set i's initial value to 0


i=0

## set prev_input's initial value to 0


prev_input=0

## this while loop looks to see if NTPD has been executed yet
while found_ntpd == False:
## use psutil to iterate through a list of current processes
for proc in psutil.process_iter():
## only execute if "ntpd" is found
if proc.name() == "ntpd":
streamer.log("msg","Found NTPD") ## stream alert that ntpd was found
streamer.log("psutil_msg",proc.status()) ## stream process status of ntpd; "stream name",
value
found_ntpd=True ## change variable to True to exit this loop
## assume that ntpd has already run if not found in 60 seconds
elif counter>=60:
streamer.log"msg","Search for NTPD timeout") ## stream alert that 60 seconds passed
before ntpd was found
found_ntpd=True ## change variable to True to exit this loop
else:
counter = counter + 1 ## add to the counter to track time passed
#streamer.log("counter",counter) ## stream current counter value
sleep(1) ## wait for 1 second

## this while loop constantly looks for button input (presses) once NTPD has run or 60 seconds
have passed
while found_ntpd == True:
streamer.log("msg","Ready for button input") ## stream message
## if no button press
if (GPIO.input(16) == False and prev_input!=1):
i=i+1 ## iteration count increases by 1
streamer.log("iteration",(i)) ## stream current iteration
GPIO.output(7,True) ## switch on pin 7 (LED)
sleep(0.5) ## wait for 0.5 second
GPIO.output(7,False) ## switch off pin 7 (LED)
sleep(1) ## wait for 1 second

## when button is pressed


else:
GPIO.output(7,GPIO.HIGH) ## turn pin 7 (LED) off
## script to be called
os.system("sudo shutdown -h now") ## shuts down Pi
streamer.log("msg","Script has been called")
## keeps script from executing the "if" section while button is unpressed
## after it has been pressed
prev_input=1
streamer.close() ## send any messages left in the streamer
exit() ## terminates this script

If you reboot your Pi so that the script starts running again, you should see something
like what I have below:

This time its the counter that shows the time-keeping hiccup. You can see that the NTPD
process is found after about 58 seconds, and then the main portion of our script begins
running. If you comment out streamer.log(counter, counter), the hiccup becomes invisible
and our script only runs once NTP has updated the Pis clock.

A shutdown button is pretty handy, but you could run a number of other useful scripts at
boot (though the Pi cant handle too much!). An interesting application would be
running our monitoring script in the background while you use the Pi and seeing how
much processing power your project takes!

CHAPTER
Building a Mobile GPS Streamer

Completely Mobile GPS Streamer


A little while ago I showed you how to start a script on your Raspberry Pi from boot and then
use a button to execute a command in the terminal. One of the cool applications of being able
to do this is that now you just have to turn on your Raspberry Pi for something to happen no
keyboard, mouse, ssh-ing or monitor required!

I decided to apply this awesomeness to Adafruits Ultimate GPS Breakout Board so that I
could take the GPS and the Pi anywhere I wanted.

You will learn how to

In this tutorial you will learn how to

Make your Pi truly mobile with a battery pack


and mobile hotspot

Collect location, speed, time, and other


information from the GPS board

Stream the GPS data to Initial State to see


location and speed over time

Start collecting GPS data with the press of a


button and safely shutdown your Pi with another
button

I used a Canakit so a lot of this was included:

Raspberry Pi B+ w/ Raspbian loaded SD card


HDMI cable + HDMI Monitor + Bluetooth Keyboard/Mouse (unless you already know your
Pis IP address and can SSH in)
WiFi Adapter/Dongle
2 Breadboards
40-pin GPIO Ribbon Cable (can use 5 individual male-to-female jumper cables instead)
40-pin T-Shaped GPIO to Breadboard Interface Board (not necessary if using jumper
cables)
14 Breadboard Tie Lines
2 Push Button Switches
2 LEDs (I used Red and Blue)
2 220 Ohm Resistors (to use with the LEDs; 180-2K Ohms is generally a safe range)
2 10K Ohm Resistors (to use with the buttons; 5K-100K Ohms is generally a safe range)
Adafruits Ultimate GPS Breakout Board
1 USB to TTL Serial Cable
1 Breakout Pin Header with at least 9 pins (mine came with the GPS)
1 Portable Power Bank w/microUSB connector (5V/0.7-2Amps)

On the breadboard with the GPIO interface board, you want to connect:

One row of the first button to GPIO 23 (pin 16) and a 10K resistor;
the other end of the resistor should be connected to ground

The other row of the button to the voltage source (3.3 V)

One row of the second button to GPIO 24 (pin 18) and a 10K
resistor; the other end of the resistor should be connected to
ground

The other row of the button to the voltage source (3.3 V)

The short leg of the blue LED to GPIO 4 (pin 7)

The long leg of the blue LED to a 220 resistor; the other end of the
resistor should be connected to the voltage source

The short leg of the red LED to GPIO 17 (pin 11)

The long leg of the red LED to a 220 resistor; the other end of the
resistor should be connected to the voltage source

On the second breadboard, you want to:

Attach the GPS breakout board using the breakout pins

Connect TX to the USB cables white line


Connect RX to the USB cables green line

Connect GND to the USB cables black line

Connect VIN to the USB cables red line

Now just plug the USB cable into the Pi and youre ready to start in on the

terminal action!

The first thing we need to do is make sure that the Pi recognizes your GPS
through the USB port. It is a ttyUSB device, so entering

ls /dev/ttyUSB*

should return a list of all of these devices. Your USB cable is probably the only
one, so you should see /dev/ttyUSB0 as the output.
sudo lsusb

will show you a list of all USB devices. Your cable will appear as Prolific Technology,
Inc. PL2303 if you purchased the one I listed.

Next we need to install some GPS software that will interpret the data coming from our
GPS. To install the GPS Daemon, enter this into the terminal (make sure your Pi has
internet):
sudo apt-get install gpsd gpsd-clients python-gps

After gpsd has installed, you can check to make sure that your GPS is working/has a
fix by running
sudo gpsd /dev/ttyUSB0 -F /var/run/gpsd.sock

to point gpsd to the USB port and then running


cgps -s

to see some GPS data in a nice format.

The first time I tried to see my GPS data, cgps kept timing out because I couldnt get a
fix. If youre not sure if your problem is finding a fix or not, run
gpsmon

to see raw GPS data. If $GPRMC has a V following it, then you dont have a fix and
need to move your GPS somewhere less obstructed from the sky. If $GPRMC has an
A following it, then you do have a fix, but a different problem.

You may need to kill and reset gpsd once you get a fix for cgps to work. You can do
this by running

sudo killall gpsd


sudo gpsd /dev/ttyUSB0 -F /var/run/gpsd.sock

Once cgps is displaying good gps data, youre ready to do something fancy with gpsd

in a script!

Now, since our end goal is to have this all run when the Pi boots up, itd be best if we
didnt have to run sudo gpsd /dev/ttyUSB0 -F /var/run/gpsd.sock to point to the USB
port every time. We can fix this by editing /etc/default/gpsd. Some of these may be
filled in already, but you want it to look like this:

# Default settings for gpsd.


# Please do not edit this file directly - use `dpkg-reconfigure gpsd' to
# change the options.
START_DAEMON="true"
GPSD_OPTIONS="/dev/ttyUSB0"
DEVICES=""
USBAUTO="true"
GPSD_SOCKET="/var/run/gpsd.sock"

Save it with CTRL-X, and gpsd will automatically look at the USB port for your GPS on

boot.

We do need to install a couple more modules before were ready to write our script.
The GPIO module lets us interface with the Pis GPIO pins so that we can control the
LEDs and sense button inputs. Install it with

sudo apt-get install python-rpi.gpio

I also wanted to know the actual location that my latitude and longitude corresponded
to, so I used a geocoding library called Geopy. Install it with

pip install geopy

Lastly, you want to install the Initial State streamer so that you can visualize your GPS
data without needing to look directly into the Pi. Its super easy and takes less than 2
minutes. Instructions are explained earlier in this eBook.
First we need to import everything.

import os ## allows us to talk to the system like in the terminal


from gps import * ## import the gps module
from time import * ## import time for sleeping
import threading ## import threading
from sys import exit ## allows us to use "exit"
import RPi.GPIO as GPIO ## library that lets you control the Pi's GPIO pins
from ISStreamer.Streamer import Streamer ## import the Initial State streamer
from geopy.geocoders import Nominatim ## import the Geopy geocoder
from geopy.exc import GeocoderTimedOut ## import GeocoderTimedOut so we can handle Geopy
timeouts
import sys, traceback ## import sys and traceback for exception handling

There is some initialization too handling the geocoder, gps, GPIO pins and the
streamer (which I called logger).

geolocator=Nominatim() ## call the geocoder "geolocator"

gpsd = gps(mode=WATCH_ENABLE) ## set gpsd to start gps info

prev_input=0 ## set prev_input's initial value to 0


btn_pressed=False ## set btn_pressed's initial value to False

## designate bucket name and individual access_key


## a new bucket will be created with every script run
## the access_key tells Initial State which account to send the data to
## specify .ini file location if you are using one that affects the streamer
logger=Streamer(bucket_name=Pi GPS",access_key="[Your Access Key Here]", ini_file_location="/
home/pi/isstreamer.ini")

GPIO.setwarnings(False) ## disables messages about GPIO pins already being in use


GPIO.setmode(GPIO.BOARD) ## indicates which pin numbering configuration to use

GPIO.setup(16, GPIO.IN) ## tells it that pin 16 (button) will be giving input

GPIO.setup(7, GPIO.OUT) ## tells it that pin 7 (LED) will be outputting


GPIO.output(7, GPIO.HIGH) ## sets pin 7 (LED) to "HIGH" or off

This function is to handle unhandled exceptions by turning off the LED and exiting the
script. This way you can know if your GPS script has given up on you!

## this function will handle any exceptions we don't account for below
## the LED will turn off to tell us that the script has exited
def handleTheUnhandled(type, value, traceback):
logger.log("msg","The Unhandled was handled") ## stream that an unexpected exception
occured
GPIO.output(7,GPIO.HIGH) ## turn off the LED
exit() ## exit the script
## when an exception happens that we don't account for, call our script
sys.excepthook = handleTheUnhandled

Now we use a thread to collect the gpsd information.


## this thread will look for and collect gpsd info
class GpsPoller(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
global gpsd ## bring gpsd in scope
self.current_value = None
self.running = True ## setting the thread running to true
def run(self):
global gpsd
while gpsd.running:
gpsd.next()
sleep(10)
We want to know when we are ready to start collecting information (since you cant watch the
Pi boot up), so once the button is ready to be pressed our blue LED will start blinking and we
will stream a message. Once the button is pressed, another message is streamed and the
LED stops blinking but stays on. The gpsd information is collected, and, if you are watching
the terminal, will output in a readable format. It will also stream to Initial State where you can
see how it changes over time. It will gather and stream this information every second, but you
can change sleep if you want.

## this while loop constantly looks for button input


while True:
## if no button press
if (GPIO.input(16) == False and prev_input!=1):
logger.log("Button 1","Looking for Input") ## stream that button is ready to press
GPIO.output(7,True) ## switch on pin 7 (LED)
sleep(0.5) ## wait for 0.5 second
GPIO.output(7,False) ## switch off pin 7 (LED)
sleep(1) ## wait for 1 second
## when button is pressed
else:
if btn_pressed==False:
logger.log("Button 1","Pressed") ## stream that button has been pressed
btn_pressed=True ## change btn_pressed so "Pressed" only streams once
GPIO.output(7,GPIO.LOW) ## turn pin 7 (LED) on
prev_input=1 ## keep the if statement from executing again
## start thread
if __name__ == '__main__':

try:
while True:
gpsd.next()
os.system('clear') ## clear the terminal window to display GPS data
## this is handy to see when making sure the script works
print
print ' GPS reading'
print '----------------------------------------'
print 'latitude ' , gpsd.fix.latitude
print 'longitude ' , gpsd.fix.longitude
print 'time utc ' , gpsd.utc,' + ', gpsd.fix.time
print 'altitude (m)' , gpsd.fix.altitude
print 'eps
' , gpsd.fix.eps
print 'epx
' , gpsd.fix.epx
print 'epv
' , gpsd.fix.epv
print 'ept
' , gpsd.fix.ept
print 'speed (m/s) ' , gpsd.fix.speed
print 'climb
' , gpsd.fix.climb
print 'track
' , gpsd.fix.track
print 'mode
' , gpsd.fix.mode
print
print 'sats
' , gpsd.satellites
## stream whatever you'd like to collect from the gps
logger.log("Latitude",gpsd.fix.latitude)
logger.log("Longitude",gpsd.fix.longitude)
logger.log("Reported Time",gpsd.utc,)
logger.log("Altitude (m)",gpsd.fix.altitude)
logger.log("Climb (m/s)",gpsd.fix.climb)
logger.log("Lat Error",gpsd.fix.epy)
logger.log("Long Error",gpsd.fix.epx)
logger.log("Timestamp Error",gpsd.fix.ept)
logger.log("Speed (m/s)",gpsd.fix.speed)
logger.log("Speed Error",gpsd.fix.eps)
## the geolocator requires a string so we turn lat and long into one
coord=str(gpsd.fix.latitude) + ", " + str(gpsd.fix.longitude)
location=geolocator.reverse(coord,timeout=10) ## reverse geocode coordinates
logger.log("Location",location.address)
## if the geocoder times out, stream a message and keep looping
except GeocoderTimedOut as e:
logger.log("msg","Geocoder Timeout")
pass

## if you press CTRL-C or the systeme exits, print a message and close everything
except (KeyboardInterrupt, SystemExit): #when you press ctrl+c
print "\nKilling Thread..."
GPIO.output(7,GPIO.HIGH) ## turn LED off
logger.close() ## send any messages left in the streamer
gpsd.running = False
gpsd.join() ## wait for the thread to finish what it's doing
print "Done.\nExiting."
exit() ## exit the script

The except statements will let us stop the script while testing it and keep it running if
the geocoder times out.

There is one more script we need if we want to be able to safely shutdown the Pi
without being able to execute the command in the terminal. I discussed this in more
detail in my previous blog post, but I have slightly edited my original script for this use
case. The main difference is the sub.Popen(sudo python /home/pi/navigation.py,
shell=True) line. This runs the navigation script from the offbutton.py script. This was
my solution to wanting to run two scripts at boot, but there are a couple of other ways
to accomplish roughly the same thing.
import RPi.GPIO as GPIO ## library that lets you control the Pi's GPIO pins
import os ## allows us to talk to the system like in the terminal
from sys import exit ## allows us to use "exit"
from time import sleep ## allows us to use "sleep"
import subprocess as sub ## allows us to call another script
## allows us to use the Initial State streamer
from ISStreamer.Streamer import Streamer
## designate bucket name and individual client_key
## a new bucket will be created with every script run
## the client_key tells Initial State which account to send the data to
## specify .ini file location if you are using one that affects the streamer
logger = Streamer(bucket_name="Shutdown", client_key="[Your Client Key Here]",
ini_file_location="/home/pi/isstreamer.ini")
## create files for logging stdout and stderr
#output_file = open("/home/pi/navdebug.out", "w")
#error_file = open("/home/pi/navdebug.err","w")
## add "stdout=output_file,stderr=error_file" to pipe to files
sub.Popen('sudo python /home/pi/navdebug.py', shell=True)

GPIO.setwarnings(False) ## disables messages about GPIO pins already being in use


GPIO.setmode(GPIO.BOARD) ## indicates which pin numbering configuration to use
GPIO.setup(18, GPIO.IN) ## tells it that pin 18 (button) will be giving input
GPIO.setup(11, GPIO.OUT) ## tells it that pin 11 (LED) will be outputting
GPIO.output(11, GPIO.HIGH) ## sets pin 11 (LED) to "HIGH" or off
## set prev_input's initial value to 0
prev_input=0
## this while loop constantly looks for button input (presses)
while True:
## if no button press
if (GPIO.input(18) == False and prev_input!=1):
logger.log("Button 2","Looking for input") ## stream message
GPIO.output(11,True) ## switch on pin 11 (LED)
sleep(0.5) ## wait for 0.5 second
GPIO.output(11,False) ## switch off pin 11 (LED)
sleep(1) ## wait for 1 second
## when button is pressed
else:
logger.log("Button 2","Pressed")
GPIO.output(11,GPIO.HIGH) ## turn pin 11 (LED) off
## script to be called
os.system("sudo shutdown -h now") ## shuts down Pi
logger.log("msg","Script has been called")
## keeps script from executing the "if" section while button is unpressed
## after it has been pressed
prev_input=1
logger.close() ## send any messages left in the streamer
exit() ## terminates this script

I left the statements I used for debugging commented out in the script in case you might need them. All
that they do is specify files to write the standard output and standard error of the navigation.py script to.

So you have the scripts, but how do we get them to run automatically when the Pi boots up? There are
a couple of ways that you can run a script at a certain time or when something specific happens. A very
easy way to do this is with Cron, a tool that comes ready to use on Unix systems (like the Pi!). Cron
allows you to specify minute, hour, day of month, month of year and day of week. A more advanced
method that also allows you greater freedom to designate when your script is run is by creating an init
(initialization) file.

Because I only needed my script to start at boot, I chose to use Cron. While init files
do allow you greater control, they are much more complicated to write. If youd like to

use an init file, you can see how to here.

Getting to the file you need to edit is as easy as typing


sudo crontab -e

in your terminal and hitting enter. You will see a file pop up with a lot of
comments. At the bottom of this file youll want to add the line
@reboot sudo python /home/pi/Streamer/offbutton.py

@reboot tells Cron to execute the line following it once the system has booted up. My
file is named offbutton.py and it is located in my Streamer folder. Youll want to
replace those with the name and location of your file. If its just in the main folder on
the Pi, its location is /home/pi/. Whenever you dont want the script to run just
comment out the line with # and save the file.
Note: You do need to reboot the Pi before this new Crontab will take effect.
Since our script also starts at boot, we had to do this anyways!
Now that your scripts will run automatically when you boot the Pi, you have LED status
indicators, and a portable power bank, we are almost ready to hit the ground running. The
only thing that we havent taken care of yet is how to maintain an internet connection.

Its surprisingly easy to get your Pi to automatically connect to a specific WiFi. In my case, I
wanted it to connect to my iPhones hotspot (the ssid will obviously differ). You need to edit /
etc/wpa_supplicant/wpa_supplicant.conf and make this the first network:

network={
ssid="iPhone"
psk="password"
key_mgmt=WPA-PSK
}

Save the file and go to /etc/network/interfaces. If you dont see auto wlan0, add it.

Youre good to go! Just make sure that your phones personal hotspot is turned on and
power on your Pi. I drove around with my Pi running and could see this in Initial States
Waves:

Pretty sweet, huh? A cool addition to this project would be a neat way to bundle all of
the equipment into a case of some sort.

CHAPTER
Building a Hamster Fitness Tracker

10

Turn Your Raspberry Pi Into a


Hamster Fitness Tracker
Have you ever wondered just how much your hamster runs throughout the day/
night? How far? How fast? My 9 year old daughter did, and we decided to find
out. Turns out, it was pretty easy, and the results were unbelievable.

Here are the supplies you will need:

An internet connected Raspberry Pi or your single-board computer of choice.

A laser break beam sensor (such as this sensor from Adafruit https://

www.adafruit.com/product/2122).

A breadboard for wiring up a simple circuit (such as the one found in the

Adafruit Pi starter kit).

An LED (optional, also found in the Adafruit Pi starter kit).

Two pull-up resistors (one 220 ohm resistor and one 10K ohm resistor, also

in the Adafruit Pi starter kit).

A hamster cage with a running wheel that is outside the main living area (to
avoid ever shining a laser into your hamsters eyes). Here is an example

cage.

A hamster.

The measurement system is very simple. The laser break beam sensor will be
aimed at a small target on the wheel that will only reflect the beam once per full
rotation of the wheel. The Pi will detect each time the wheel turns a full rotation and
calculate the distance traveled and speed (the distance traveled is simply the
circumference of the wheel). The resulting measurements will be captured and
streamed to a data visualization that you can look at when you wake up each
morning (because your hamster is probably getting his workout on while you sleep at
night).

The laser break beam sensor from Adafruit is a good choice for this project because
of its simplicity to wire up and use. No extra weight will be added to the wheel to
make it harder to spin for your 2 oz. dwarf hamster. Both the laser transmitter and
receiver are built into the same small plastic housing. If the laser beam reflects off of
a target within 1 meter or so, the receiver detects and outputs the break.

This is much better than a traditional laser break sensor that requires a separate
receiver that must be aligned to the laser (like your garage door sensor that can
easily get off track if you touch it). The laser break beam sensor will have three
wires to attach. Attach the red wire to 5V. Attach the black wire to ground. The blue
wire will be the sensor output. Connect this wire to a 10K ohm pull-up resistor and to
an input pin on your Pi as shown below. *Warning* Do not shine the laser into the
living area of your hamster!!! You could cause damage to your hamsters eyes. If
your wheel is inside the cage, consider using a magnetic contact switch instead of a
laser break beam sensor.

The LED will be used to visually indicate that the laser break sensor has detected a
break. This is extremely useful when lining up the laser with the target and making
sure that nothing unwanted is causing a light reflection into the sensor. Initially, I
taped the laser break sensor to the wall, but enough light was reflecting off of the
white wall to cause the sensor to always detect a break.

Having the LED helped me find the best place to mount the sensor. You can hook the input
of the LED directly to the output of the sensor (make sure you have a pull-up or pull-down
resistor on your LED). I hooked my LED up to an output pin on my Pi in case I wanted to use
the LED for something else in the project. Turns out, having the LED blink each time a laser
break is detected is more useful than I anticipated. The entire hardware setup is shown
above.

Create a target on the outside of the wheel for the laser. I used a small piece of masking
tape. Align the laser to the target and make sure no other part of the wheel breaks the laser
when it spins. Keep the laser out of any area that your hamsters eyes can enter!!

For the software setup, first install the Initial State streamer to give your hamster fitness
measurements a destination to go to (go here for instructions on setting up the Initial State
streamer; it is super easy and takes less than two minutes). Create a new file on your
Raspberry Pi (e.g. hamster_fitness.py) and copy+paste the code below into it. You will need
to copy+paste the access key associated with your Initial State account in between the
quotes on line 6 where it says PUT YOUR ACCESS KEY HERE. You can find your access
key under your account settings or on the landing page once you log into your account. The
code below is all of the code that you will need.

import RPi.GPIO as GPIO


import time
import datetime
import math
from ISStreamer.Streamer import Streamer
streamer = Streamer(bucket_name=Hamster Fitness Tracker", access_key="PUT YOUR ACCESS
KEY HERE")
streamer.log("ZooZoo Says","")

# Setup Pins
pinNumLaserBreak = 18
pinNumLED = 4
GPIO.setmode(GPIO.BCM) # numbering scheme that corresponds to breakout board and pin layout
GPIO.setup(pinNumLaserBreak,GPIO.IN)
GPIO.setup(pinNumLED,GPIO.OUT)

# Setup Constants
diameter = 13 # inches
circumference = diameter * math.pi * 0.0000157828283 # miles
distanceTotal = 0
timeNoActivity = 5 # seconds
speed = 0
lastTime = datetime.datetime.now()
while True:
input = GPIO.input(pinNumLaserBreak)
if not input:
if speed == 0:
streamer.log("ZooZoo Says", "It's time to get pumped")
# Calculate stuff
thisTime = datetime.datetime.now()
timeDiff = (thisTime-lastTime).total_seconds()
speed = circumference/(timeDiff/3600) # miles per hour
# Log stuff
streamer.log("Full Rotation", "1")
if speed < 5: # Filter out glitches (rocking on the sensor)
distanceTotal += circumference
streamer.log("Speed(mph)", speed)
streamer.log("Total Distance(miles)", distanceTotal)

GPIO.output(pinNumLED,GPIO.HIGH) # Turn LED on for visual cue that everthing is working


lastTime = thisTime

# Wait for sensor break to clear


input = GPIO.input(pinNumLaserBreak)
while not input:
input = GPIO.input(pinNumLaserBreak)
time.sleep(.05)
else:
if speed > 0:
thisTime = datetime.datetime.now()
timeDiff = (thisTime-lastTime).total_seconds()
# Reset the speed to 0 if no activity (for log visualization)
if timeDiff > timeNoActivity:
speed = 0
# Log stuff
streamer.log("ZooZoo Says", "I need a rest")
streamer.log("Speed(mph)", speed)
streamer.flush()
GPIO.output(pinNumLED,GPIO.LOW) # Turn LED off for visual cue that everthing is working

Line 6 sets up the destination bucket for our data stream. We will name the bucket
Hamster Fitness Tracker. Every time you run this script, a new bucket named
Hamster Fitness Tracker will be created under your Initial State account (identified by
your access key), and all data generated from that script run will be contained there.
Line 7 streams the first message to the newly constructed stream.

Lines 10-20 setup the constants that we will use. Set the pin numbers according to
how you wired up your sensor input and LED output. Measure the diameter of the
wheel and enter the diameter on line 17. The script above assumes the diameter is
measured in inches and the speed will be calculated in miles/hour. Convert to your
desired units accordingly.

Line 25 checks the sensor output. If the sensor outputs a logic 0 (which means there
was a laser break detected), the distance and speed measurements will be calculated
and streamed. A simple attempt to filter out glitches (e.g. when the wheel stops right on
the target and rocks) happens on line 37. If a speed greater than 5 is detected, this is
assumed to be a glitch and is filtered out of the speed and distance traveled calculation.
Line 42 turns on the LED to indicate a laser break is detected. If the wheel stops right
on the target, all calculations are paused until the break is cleared (lines 46-49).
Lines 51-61 detect if there is no activity on the wheel for x number of seconds (x
specified on Line 20). If there is no activity, the speed is cleared to 0 and message is
output, I need a rest. After a rest has been detected, the first full rotation of the wheel
will stream another message, Its time to get pumped, on line 28.

We are ready to test our setup. Run the script at the command line of your Pi (type
sudo python hamster_fitness.py). Spin your wheel and make sure the LED blinks only
when the laser hits the target on the wheel. After a few spins, log into your Initial State
account and a new log will pop up in your log shelf called Hamster Fitness Tracker.
View this in Waves or Lines to see your hamsters activity. When you are ready to let
this script run for a long time, you might want to use the nohup command (no hangup),
especially if you are sshing into your Pi (e.g. nohup sudo python hamster_fitness.py >
tmp.txt &).

We measured the activity of my daughters hamster, ZooZoo, for the last four days. You can
see a screenshot of all her captured activity over this time in Waves above. At a quick glance,
you can see the big gaps in speed (and flat line of total distance) that correlate to the daylight
hours when she sleeps. Around 10 pm every night, she gets busy. After four days, she ran 12
miles!! If we zoom into one of her many runs, it looks like the following:

This is a 10 minute view of her activity. It is interesting to see the little mini-breaks
that she takes but overall maintains a speed of about 1.15 mph, spiking up to 3.25
mph. We were surprised to see that such a little creature would willingly run so far,
so fast every night. We had to do a little Google research to sanity check our
results. Turns out, hamsters do indeed run 1-5 miles per night, averaging 0.8 to 1.5
mph with spikes up to 5 mph in speed. In the wild, hamsters are always moving
around and burrowing to find food. In a cage with plenty of food, they have to
maintain a significant amount of movement to remain healthy. A hamster that is
sedentary will become paralyzed, making that hamster wheel a pretty important part
of your hamsters environment.

Another interesting observation was the fact that she ran 5 miles the night after we
cleaned her cage and gave her a different type of food. The night before, she ran
1.5 miles. More surprising than any specific observation from this project is the fact
that we were so fascinated by the capture of a hamsters fitness schedule. Capture
your hamsters activity and tell us what you find. We want to compare notes :-).

THANK YOU
We hope you enjoyed these ten
project tutorials! If you have any
questions, dont hesitate to email
us at support@initialstate.com. If
you havent done so already, we
encourage you to sign up for our
free data streaming tier.

initialstate.com/pricing

Potrebbero piacerti anche