Sunday, September 29, 2013

Garage Door Part 1 - Open Door (GPIO Output)

Project Garage Door

My vision for our Garage Door is to have an automated way to open and close it from both a web interface and a proximity sensor.

It has taken me a couple of weeks to finally get everything working, but I finally have my garage door automated, with the help of the Raspberry Pi.  I will break out each of the steps it took into a different article: Open Door (GPIO Output), Monitor Door (GPIO Input), Web Interface, Vocal Notification, Proximity Sensor.

First step was to get the garage door to open.  I started with trying to determine how I could get the Raspberry Pi to trigger the garage door to open/close.  After inspecting the wired garage door button, I found a simple solution to trigger the garage door.
Garage door button
The garage door button has two wires that run all the way to the garage door motor.  I found that by simply jumping the two terminals (circled in red below) this would trigger the garage door.  (FYI: The right two terminals are used for the safety closing door sensor, which makes the center terminal a common terminal).  This made the solution fairly easily, as I would simply need to electronic switch to close the circuit, which I had already posted a working solution for in my Driving a Relay using GPIO and Automated Sprinkler System First Look (Relay Module) articles.
Garage door motor
I could have run wires all the way from the Raspberry Pi to the garage door motor, but as the garage door button was much closer, I instead ran a set of wires (20 gauge door bell wire I picked up from Home Depot for cheap) to the back of the garage door button and connected them to the screw terminals I found there (Note: these new wires can be seen as the red/white combo in the garage door button picture above).

I then connected the Raspberry Pi, with attached Wifi dongle, to a breadboard and wired up a relay (relay-diode-transistor-resistor) as described in Driving a Relay using GPIO).  A pre-built Relay Module would have been easier, but I did not have an extra one on hand at the moment.  I then placed the Raspberry Pi and breadboard into a plastic container, to keep the dust off (which I cut holes for venting).




Raspberry Pi in plastic container to protect from dust

To trigger the electronic relay switch, which will in turn close the garage door button loop, I use the following Python code.


trigger_door.py:
#!/usr/bin/env python

import RPi.GPIO as GPIO
import time

GPIO_PIN = 25

GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_PIN, GPIO.OUT)

try:
    print "Trigger Garage Door"
    GPIO.output(GPIO_PIN, GPIO.HIGH)
    time.sleep(.5)
finally:
    print "Cleaning up..."
    GPIO.cleanup()

You may have noticed that the code makes no mention of if it will be opening or closing the door.  That is because at this point, there is no way for the code to determine the current state of the garage door.

Stay tuned, in the next article, for solution to detect the state of the garage door: Garage Door Part 2 - Monitor Door (GPIO Input)



Saturday, September 14, 2013

Monitoring a UPS

The original reason for my interest in the Raspberry Pi was for a mini computer to monitor a UPS and alert us if there was a power loss.  The following is how I setup the Raspberry Pi to monitor the UPS and send an email to our cell phones in the event of a localized power loss.
CyberPower LCD "Smart" UPS

Short Story of Education the Hard Way


(note to reader: If you are just interested just in the UPS monitoring details, skip ahead...)

What are we monitoring with the UPS?  Well, we have a small chest style deep freezer in our garage.  We store steaks and other expensive meats in it.  Anytime there is an excellent sale, my wife stocks up on meats.  A few months ago, something caused the GFCI to trip, and we didn't notice until a few days latter when the rancid smell reached us.  We estimated over $500 worth of meat lost in one fell swoop.  So the wife tasked me with coming up with a solution to avoid a repeat in the future.

So my solution was to use a "smart" UPS, one that I could actively read the metrics from, and send a email notification in the event of a power failure.  The second benefit, or so I had thought, is the UPS could keep the fridge powered for short term power loss.  I already have a CyberPower UPS connected to my file server, and it works great for battery backed power outages, monitoring battery reserves, and shutting down the server if the reserves deplete.

A bit of painful education.  I wanted to make sure I purchased the "right" size of UPS, so I pulled out my Kill A Watt power meter and connected it to the refrigerator.  During the occasional freeze cycle it appeared to pull about 460-490 Watts, and lasted less than a minute.  At idle, it rated closer to 10 Watts.  I rationalized that the UPS should be able to handle a few of these cycles before failing out.

When I looked online for consumer UPS, a majority measured in VA.  So how does one get VA from Watts?  Well, I cheated.  The Kill A Watt also has a VA meter, so I selected that, and it showed around 560-580 VA.  I then found a 600 VA CyberPower UPS.  I admit that I realized 580 to 600 is not a lot of wiggle room, but the next battery size up jumped quite a bit in price.  I crossed my fingers and ordered it.  I should have done a bit more research.

The UPS arrived and I connected it to the freezer.  The freezer's motor kicked on and the UPS went offline.  Clearly I was wrong.

When I actually searched for VA to Watt conversion calculations online, I found that a good estimate is closer to 50% - 60%.  I would have needed almost 800 VA to be on the safe side.  Even this may not have been sufficient, as I learned that the initial motor spike can be quite high.

Lesson learned: You would probably need an industrial sized UPS to battery back a simple freezer.

Well, the battery protection was a bust, but at least I could still use the UPS to monitor for a power failure.  Unfortunately, had I known this, I could have saved a few bucks, and just purchased the cheaper smaller "smart" UPS.  The Raspberry Pi could run for days off even the smallest one.

So onto the technical stuff...


How to monitor a UPS with a Raspberry Pi


The setup.  The Raspberry Pi lives out in the garage, on top of the deep freezer.  I have a USB powered hub connected to the UPS, in one of the battery backed up slots.  The USB hub then powers the Raspberry Pi (to avoid having to waste two power adapters).  To talk to the USB hub I have a second USB cable connected to the data side of the Pi.  To connect to the network, I have a WiFi dongle connected to the USB powered hub.  To try and keep it as clean as possible, I have Raspberry Pi inside a plastic container, with holes for air flow.  Finally, to get as much use of the Raspberry Pi, it also serves double duty and controls/monitors the garage door.

There are numerous "UPS" monitoring packages available, but the one I have had the most success with, is the one from APC called "apcupsd - APC UPS Power Management (daemon)".  Although it was designed for APC branded UPS, it works quite well with numerous other UPS.

I tend to purchase the CyperPower UPS line with the LCD display.  I am a sucker for the LCD that provides quick visual metrics, of the UPS.  The CyperPower UPS connects to a PC through USB and works well with the apcupsd daemon.

Luckily the package is already included in the Raspbian repositories, so installation is this simple:

# apcupsd installation
apt-get update
apt-get install apcupsd

The next step is to modify the configuration scripts, so apcupsd can find the UPS.  Use your editor and modify /etc/apcupsd/apcupsd.conf with the following changes.

# vim /etc/apcupsd/apcupsd.conf

#UPSCABLE smart
UPSCABLE usb

#UPSTYPE apcsmart
UPSTYPE usb

#DEVICE /dev/ttyS0
DEVICE

These changes tell apcupsd that the UPS is connected via USB.

Next we want to test our connection to the UPS.  This can be achieved with the 'acptest' program.

# apctest

2013-09-14 14:49:10 apctest 3.14.10 (13 September 2011) debian
Checking configuration ...
Attached to driver: usb
sharenet.type = Network & ShareUPS Disabled
cable.type = USB Cable
mode.type = USB UPS Driver
Setting up the port ...
Doing prep_device() ...

You are using a USB cable type, so I'm entering USB test mode
Hello, this is the apcupsd Cable Test program.
This part of apctest is for testing USB UPSes.

Getting UPS capabilities...SUCCESS

If you see the "SUCCESS", everything is great.  There isn't much here that you will want to change, so let's quit this program and start the apcupsd daemon.

First, enable the service:

# vim /etc/default/apcupsd

ISCONFIGURED=yes

Next, restart the service:

# service apcupsd restart

Starting UPS power management: apcupsd.

To have apcupsd auto start at boot:

# update-rc.d apcupsd defaults

Next, we can query the UPS to see the various metrics available to us using the 'apcaccess' application.  The properties that apcupsd supports is quite large, and each UPS uses different properties, so your results may vary.

# apcaccess

APC      : 001,032,0781
DATE     : 2013-09-14 14:54:31 -0600
HOSTNAME : pi-ups
VERSION  : 3.14.10 (13 September 2011) debian
UPSNAME  : pi-ups
CABLE    : USB Cable
DRIVER   : USB UPS Driver
UPSMODE  : Stand Alone
STARTTIME: 2013-09-14 14:54:30 -0600
MODEL    : UPS CP600
STATUS   : ONLINE
LINEV    : 120.0 Volts
LOADPCT  :   0.0 Percent Load Capacity
BCHARGE  : 100.0 Percent
TIMELEFT :  82.0 Minutes
MBATTCHG : 5 Percent
MINTIMEL : 3 Minutes
MAXTIME  : 0 Seconds
OUTPUTV  : 120.0 Volts
DWAKE    : 000 Seconds
LOTRANS  : 100.0 Volts
HITRANS  : 140.0 Volts
ALARMDEL : 30 seconds
NUMXFERS : 0
TONBATT  : 0 seconds
CUMONBATT: 0 seconds
XOFFBATT : N/A
SELFTEST : OK
STATFLAG : 0x07000008 Status Flag
SERIALNO : AEC7101.251
NOMINV   : 120 Volts
NOMPOWER : 340 Watts
END APC  : 2013-09-14 14:55:02 -0600

Now that we can query the UPS, let's work with the apcupsd "event" scripts.  This is how we will get an email sent when a power failure occurs.  The event scripts can all be found in the /etc/apcupsd/ folder.  All events are controlled by the /etc/apcupsd/apccontrol master script, so take a quick peak there if you want to know what else can be modified.

The two scripts we are interested in are the "onbattery" and "offbattery" scripts.  The "onbattery" is triggered during a power failure, and "offbattery" is triggered when power returns.

By default these scripts are just simple bash scripts that send a message to the PC's console and send a local email.  Instead of using local mail, we will use Gmail to send our notification, and write the script in Python.  One other side benefit of having these scripts written in Python, is I can also integrate Xively and then update Xively with the various data points of my UPS.

Let's backup the current scripts, before modifying them:
cp /etc/apcupsd/onbattery /etc/apcupsd/onbattery.original
cp /etc/apcupsd/offbattery /etc/apcupsd/offbattery.original

This is the powery failure script I use:

onbattery:
#!/usr/bin/env python

import smtplib
import email.mime.text
import syslog

syslog.openlog('[UPS]')
def log(msg):
    syslog.syslog(str(msg))

GMAIL_ADDRESS = 'xxx@gmail.com'
GMAIL_PASSWORD = 'xxx'

from_email = GMAIL_ADDRESS
to_emails = ["xxxxxxxxxx@tmomail.net"]  # cell phone address

msg_subject = "ALERT: UPS Power Failure"
msg_text = "Auto Notification"

log(msg_subject)

msg = email.mime.text.MIMEText(msg_text)
msg['Subject'] = msg_subject
msg['From'] = from_email
msg['To'] = ", ".join(to_emails)
s = smtplib.SMTP_SSL('smtp.gmail.com', '465')
s.login(GMAIL_ADDRESS, GMAIL_PASSWORD)
s.sendmail(from_email, to_emails, msg.as_string())
s.quit()


And for when power returns:

offbattery:
#!/usr/bin/env python

import smtplib
import email.mime.text
import syslog

syslog.openlog('[UPS]')
def log(msg):
    syslog.syslog(str(msg))

GMAIL_ADDRESS = 'xxx@gmail.com'
GMAIL_PASSWORD = 'xxx'

from_email = GMAIL_ADDRESS
to_emails = ["xxxxxxxxxx@tmomail.net"]  # cell phone address

msg_subject = "OK: UPS Power Recovered"
msg_text = "Auto Notification"

log(msg_subject)

msg = email.mime.text.MIMEText(msg_text)
msg['Subject'] = msg_subject
msg['From'] = from_email
msg['To'] = ", ".join(to_emails)
s = smtplib.SMTP_SSL('smtp.gmail.com', '465')
s.login(GMAIL_ADDRESS, GMAIL_PASSWORD)
s.sendmail(from_email, to_emails, msg.as_string())
s.quit()

Finally, we test the scripts locally to make sure the email notification is sent.  If everything looks good, test a power failure by disconnecting the UPS from the wall.  Within a few seconds, the apcupsd daemon should trigger the onbattery event and our email should be sent.  Now we will immediately know the next time the UPS looses wall power.

So, what if the power loss is not local to just the UPS?  An external monitoring service could be used.  Something like Nagios running from the cloud works great for this, but I will save that for another time.



Sunday, September 8, 2013

Driving a Relay using GPIO

The next Raspberry Pi project I am working on is controlling my garage door.  To control the garage door I will need to use a relay.  Unfortunately, I used my one and only, easy to use, and very compact, "Relay Module" with my sprinkler project.  I could order another, but that would take time, and I wanted to get something working over the weekend.

Luckily, I had a pack of 5V relays in my electronics component collection.  I had ordered a 10 pack for $6 off of Amazon some time ago.  (do a quick search for "5V Relay", there are numerous options)
QIANJI JQC-3F(T73) Relay

Controlling a relay from a Raspberry Pi is not as easy as simply connecting it to a GPIO port.  First, the GPIO port is only 3.3V and most small relays require 5V.  Luckily the Raspberry Pi does have a 5V rail we can use, but we need a way to switch that on and off.  That is where the transistor comes in.  Our GPIO port will turn the transistor on and off, which will in turn turn the 5V lead to the relay on and off.

In theory this GPIO -> Transistor -> Relay are all that is needed, but of course we need a bit of protection to not fry the components (or the Pi).  This involves a few resistors and a diode.  The resistors will limit the current, and the diode will wrap the relay to dissipate the back current (a relay is just a coil with a magnet, and coils store energy).  This mess is why the compact pre-built Relay Modules are so very nice!

I found an excellent article, by Kevin Sangeelee, that provides a great explanation and a sample schematic for driving a simple relay.  Kevin describes the use of the diode as:  "The diode in the circuit is there to conduct the current generated by the de-energising coil back across the coil (e.g. when switched off), allowing the power to dissipate more gradually, avoiding a voltage spike." (source)
Schematic for a relay via GPIO on the Raspberry Pi (source)

I did not have all of the exact components listed in Kevin's schematic, but I did have several close components that I traded with, from my electronic component box.  (If you don't have a box for all these various small components, you really should, as you never know when you will need one).  For the transistor I used a 2N2222 A338.  For the relay I used the 5V QIANJI JQC-3F(T73) relay from Amazon.  For the diode I used a generic, nondescript, one I also had in the component box.  With my setup, the 1K resistor was too high to drive my transistor, so I reduced it to a 100 Ohm resistor, and this seemed to work fine.  I also connected up a resistor and LED on the load side, to verify that the relay was functioning, as if the noisy relay clicking wasn't enough.

I then put together a little bit of Python code to produced this fun clicking light show:

#!/usr/bin/env python

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)
GPIO.setup(25, GPIO.OUT)

try:
    while True:
        print "On"
        GPIO.output(25, GPIO.HIGH)
        time.sleep(.1)
        print "Off"
        GPIO.output(25, GPIO.LOW)
        time.sleep(.1)
finally:
    print "Cleaning up..."
    GPIO.cleanup()

The next step is to connect it to the garage door opener, and then get some open/close sensors so I can tell when the door is open or closed.  Eventually, I am going to write up a proximity application for my cell phone to automatically open the garage door on my way home from work.



Saturday, September 7, 2013

Data Logging with the Internet of Things - Xively

Sensor Graphing

The Raspberry Pi is great for collecting data points from various sensors.  For historical reasons, the sensor values can be stored in some sort of database, and retrieved for later usage.

In an article of The MagPi (Sep 2012), there was a recommendation to use the "Internet of Things" web service COSM to store data points.  COSM also provides the added benefit of graphing features.  Since this Sep 2013 article ran, COSM has been renamed to Xively.
Xively - The Internet of Things

The first step was sign up for a free Developer Account.  Then from the "Development Devices" select "Add Device".  Each device can have numerous data feeds, so I created my device with a generic name of "Raspberry Pi".

To see a sample of various feeds, and graphing options, the following is the feed from my web server.

The next step is to populate the device with data streams called "channels".  Each channel would represent an individual sensor.  The sensors can be added from the web interface, or dynamically added using the Xively API.

Xively has a simple REST based API that is fairly easy to use.  There are also numerous libraries for various programming languages, such as Python, C and Java.  Having a bit of an infatuation with Python, I of course chose to go with the Python library.

Installation of the Xively Python library was fairly easy.  There is a dependency on the external "requests" Python library that has to be installed first, and it does require Python 2.7 or higher.
# Xively Library Installation 
git clone https://github.com/kennethreitz/requests
git clone https://github.com/xively/xively-python
cd xively-python
ln -s ../requests/requests

# verify import throws no errors
echo "import xively" | python

Note: If you get an error about "ImportError: No module named requests.auth", make sure the "requests" python library is installed.
Note: If you get an error about "params = {k: v for k, v in (    SyntaxError: invalid syntax", make sure you are using Python 2.7+.

I put together this simple script for dynamically updating the channels.  I then plugged this directly into the various sensor reading scripts.

#!/usr/bin/python2.7

# NOTE: xively requires Python 2.7+

import sys
import datetime
import xively

API_KEY = "API_KEY"  # set to your API Key
FEED_ID = "FEED_ID"  # set to your Feed ID

if len(sys.argv) != 3:
    print "Usage: {0} <channel> <value>".format(sys.path[0])
    sys.exit(1)

channel = sys.argv[1]
value = sys.argv[2]

api = xively.XivelyAPIClient(API_KEY)
feed = api.feeds.get(FEED_ID)
now = datetime.datetime.utcnow()
feed.datastreams = [
    xively.Datastream(id=channel, current_value=value, at=now)
    ]
feed.update()

This script can then be run with a simple:
./xively-update.py sensor1 42

Although the live graphing options are nice, I also wanted to be able to embed the graph into a web site.  Xively provides an API to do this as well:

The following dynamically generated CPU graph was generated from a simple query URL, which can be embedded into a web site:

Now that I have my sensor data being stored and graphed, the next task will be to extend the Python script to be able to pull the raw data back and perform some trending calculations.




Monday, September 2, 2013

Automated Sprinkler System First Look


Our sprinkler system is now controlled by a Raspberry Pi! Achievement Unlocked.

Raspberry Pi Sprinkler Controller


With a little bit of Python and web development, we can now control the sprinkler system from a simple to use web interface and Google Calendars. The Raspberry Pi controller was actually pretty simple to setup. I simply connected several free GPIO pins to an relay module, connected the sprinkler valves to the relay module, and then control the relay module with a Python script.
8 Channel Relay Module(~$15)

A standard sprinkler system uses a 24 VAC line to power a sprinkler valve. When 24 VAC is applied to the line, the sprinkler valve opens and the lawn is watered. Remove the 24 VAC and the valve closes. Obviously we could not connect 24 VAC directly to the Raspberry Pi, so instead we hide it behind a relay (electrically operated switch) which physically isolates the two circuits.

To build a relay circuit would requires a transistor-resistor-diode-relay. As our sprinkler system has 8 "zones", and each zone would require one of these transistor-resistor-diode-relay circuits, this would have been quite a mess to assemble. Luckily there are numerous pre-built Relay Modules, such as the SainSmart 8-Channel 5V Relay Module for Arduino($15), that come in a variety of sizes to fit one's needs.

To connect the Raspberry Pi to the relay module, connect the 5V GPIO pin to the VCC pin on the relay module, then connect the Ground GPIO pin to the GND pin on the relay module, and finally connect 8 (or as many zones as you have) free GPIO pins to the relay module. Next connect one sprinkler valve line to each relay, and finally connect the common ground line to the other side of each relay. Now the sprinkler valves can be turned on and off from the Raspberry Pi using the GPIO output functions.

Schematic of Raspberry Pi Sprinkler Controller

With some Python, HTML and Javascript I then created a simple web interface that my wife could turn on and off the sprinkler system with.
Sprinkler Control Web Interface

When a zone is activated, the web interface highlights that zone and blinks on/off till the watering program has completed.
Zone 1 Activated

Finally, I wrote a Python daemon that runs in the background, probing Google Calendars. This allows the sprinkler system to be scheduled out in advance. Originally I was using a simple Cron Job scheduler, but I wanted something simple that my wife could also set.

Google Calendar Scheduling

The remote web interface access also allows for a really cool, and obvious, feature. We can now walk out into the back yard, with our tablets / cell phones, and control the sprinkler system right in front of our eyes. Instant gratification.

This remote control capability has led to a silly game that my kids absolutely enjoy. We would turn on a sprinkler zone at one side of the yard, and the kids would run towards it. Then we would turn on the sprinkler zone at the other end of the yard, and the kids would run there. They would enjoy this back and forth game until they were too cold to continue. Oh the sweet, simple things of life.






Remote Control Machines

Remote Control Machines Construction Kit

My loving wife asked me what I wanted for my birthday this year.  I asked for some sort of Legos-like-build-your-own-robot-kit that I could control with the Raspberry Pi, and simple enough that I could build it with my son.  Well happy birthday to me, as she came through with this excellent Remote Control Machines Construction Kit ($46).
It comes with enough pieces and instructions to build 10 different models, 3 electric motors and an infrared remote control.  Inserting the Raspberry Pi should be as simple as swapping out the remote control receiver with a Raspberry Pi and a simple motor controller.





The MagPi

The MagPi Magazine
While out of town, at VMworld 2013, didn't have the opportunity to play with my Raspberry Pi, so instead occupied my free time reading this excellent free Raspberry Pi magazine I found:

The MagPi magazine: The magazine for Raspberry Pi users. Articles cover include coding, robotics, and electronics.

The magazine can be read online, or downloaded as a PDF (preferred).