If you tinker with technology then chances are you already know what the “Internet of Things” is all about. If you don’t know, then my question to you is, where have you been!?

For those of you not in the know, here’s a quick primer.

“The Internet of Things is a network of Internet-enabled objects, together with web services that interact with these objects. Underlying the Internet of Things are technologies such as RFID (radio frequency identification), sensors, and smartphones.”[1] 

One way that folks put this concept into practice is the set up their “things” so they, like their owners, can update their status.  I like to think of it as Twitter for my stuff.  One site that gives your devices a place to update their status information is called Pachube (pronounced “PATCH-bay” [2]).  I’ve been using Pachube for a couple of years to report health data from my servers but I’ve been wanting to experiment with building a microcontroller based stand-alone device that could use sensors to gather environmental data and then report that data to Pachube without the need for a computer.

A microcontroller (in this context) is a pre-built device consisting of circuitry on a single printed circuit board (PCB) such as microprocessor, I/O circuits, clock generator, RAM, stored program memory, etc. The idea behind the microcontroller is that it is immediately available and useful to an application developer, without needing to spend time and effort in developing the controller board itself [3].

In the case of an Arduino, however, the idea is to make it easy to prototype solutions by building your own circuits and devices and proving them before committing your device to a PCB of it’s own or going into large-scale production

There are lots of microcontrollers on the market such as the Arduino, BASIC Stamp and others. I’ve been reading about the Open-Source Arduino Platfrom for a long time and had been looking for an excuse to buy one and expirament. To get my feet wet, I decided to buy the latest Arduino board, some photocells, a nice selection of resistors, and a simple breadboard.

Building The Circuit

When I received the parts, my first task was to build a very simple circuit. Since a photocell is basically a resistor, the easiest way to get a measurement was to connect one end to 5V and the other to a pull-down resistor to ground. Now all I had to do was make a connection from analog input to the point between the fixed pull-down resistor and the photocell.

Now we have a complete circuit and should be able to build a simple sketch (firmware program) to read the data and pump it to our serial port.

  Ldr

Writing The Sketch

In Arduino parlance, a sketch refers to the program that is written and uploaded to the ATMega chip (aka the firmware) that tells the Arduino what to do.

The easiest way to get up and going is to download the Arduino IDE from the Arduino website.  The IDE makes it easy to compile and upload our code and at this point, easy is what we want.

int ldrPin = 0;
void setup() {
Serial.begin(9600);
}
void loop () {
Serial.println(analogRead(ldrPin)/204.8);
delay(1500);
}

Our sketch is very simple.  We start by defining the location of our photocell which in this case is Pin 0. We then open the serial port at 9600 baud and then start a perpetual loop that reads the voltage from the photocell, waits 1500 milliseconds (1.5 seconds) and then sends the result to the serial port.

When we read the analog port the value that is returned is a value between 0, representing zero volts, and 1024, representing five volts. I could easily use that number but I want to convert the number to actual voltage which I do by dividing the value returned by the analogRead function by 204.8.

Reading and Posting

As I stated in my opening, the goal with the Arduino is to have a stand-alone device that can post data to Pachube (or anywhere for that matter) independently.  Since we’re just experimenting with the fundamentals, in this instance, we’ll leave our Arduino connected to the computer to read the data and then post it.

On my Mac I opened a Terminal session and navigated to /dev to look for the device name of the Arduino.  In my case it’s cu.usbmodem621. To validate that we’re getting data, I opened a read-only connection to see what I would get (be sure to close the Arduino IDE first).

cat /dev/cu.usbmodem621

If you receive a value on a new line every 1.5 seconds then everything is functioning correctly.  Since I’ve been using Pachube for a while, I already have my API Key which is necessary to programmatically update the Pachube feed.  If you don’t have an account already, go to pachube.com, set one up and grab your API Key.

Now that we know our device name, know that we’re getting data and have our Pachube API Key, we can now write our script.

You can use any scripting language to accomplish the task of reading serial data from the Arduino and then making the necessary calls to post the data.  My preference is PHP, so that’s what I’ll use here.

#!/usr/bin/php -q
<?php
$handle = fopen("/dev/cu.usbmodem621","r");
$str_ldr = fgets($handle);
sleep(5);
$mintime = time();
do{
$str_ldr = fgets($handle);
$str_ldr = trim( preg_replace( '/s+/', ' ', $str_ldr ) );
if( time()> $mintime+60) {
echo $str_ldr . "n";
echo exec("curl --request PUT --header "X-PachubeApiKey: 11112222333344445555566666777778888899999" --data "$str_ldr" "http://www.pachube.com/api/00000.csv" --silent");
$mintime = time();
}
}while(1);
fclose($handle);
?>;

First thing we do is open a connection to the Arduino and read in some data and then wait for 5 seconds. You may have noticed that the first line of data you get from the device after you open a fresh connection is not always clean. Using this method allows the connection to “settle” before we start grabbing data to post.

Next we start an infinite loop to grab a line of data, strip the CRLF, call out to cURL to post our data, wait 60 seconds and then do it all over again.

The image below shows a Pachube 24h graph.

Pachube Graph

Conclusion

I was surprised how easy it was to prototype with the Arduino and to have a working solution up and running with so little effort. My next goal will be to add new sensors to extend my home automation system (track real-time electricity, gas and water usage) and then add an Ethernet Shield to remove the need for a computer to post my data.

Until next time – GEEK OUT!!

~GT~

   

 

In my first post, in this three-part series, I wrote about how I physically interfaced my Ademco Alarm Panel to my Home Automation computer.  In this article, I will show you how to capture the data stream that comes through that interface, how to parse it and then how to make use of it in our Indigo Home Automation system.

Review & Some Cautions

As outlined in the first article, we’re using an AD2USB Adapter from NuTech which is wired into the Ademco panel and then connected to my Mac via USB.  Let me just state here that I had a lot of issues getting this to work reliably! My first attempt to interface to my Mac, located about 30 ft away, was just too unreliable.  I ended up moving my HA server to my wiring closet so I could use a standard USB cable.  This too proved to be unreliable until I used a shielded USB cable as covered in article two. Since implementing these changes, my system has been up and running without incident.

Getting Our Data

In article two I mentioned that I was using a software product called Serial Bridge and thought that it might have been the source of my data feed reliability problems.  While I eventually ruled Serial Bridge out as the source of my problems, I’m not convinced that it was not, at least, a contributing factor. The software is produced by Perceptive Automation and was written for the Mac PowerPC platform. Since my HA system runs on Mac OS/x on the intel platform, that means Serial Bridge had to run using Apple’s Rosetta translator.  This added overhead and I just simply didn’t like the solution and decided to look for other options. Seeking “other options” quickly led to the need to write my own solution. I considered Python and Perl but ultimately settled on my faithful standby, PHP.

One of the beauties of Unix-like operating systems (The core of OS/x is based on BSD) is how easy it is to interface with devices.  When the AD2USB is plugged into one of the Mac’s USB ports the FTDI software creates a Serial Port for us that shows up in /dev. Since the AD2USB is producing a text feed for us we can easily view that feed by opening a connection to our serial device and outputting its contents to STDOUT.

cat /dev/cu.usbserial-A2001wKL

Note: Your device name will differ.

At this point you should see a stream of cryptic data coming from your AD2USB Adapter.

Working with Indigo

Now that we know we have the ability to easily get our data feed from the AD2USB by simply “opening” a connection to our device, let’s now turn our attention to how we interface with Indigo.

Indigo 4 ships with an excellent API that allows us to do just about anything we want programatically.  My setup tracks the status of my alarm panel via a variable.  I can then write triggers within Indigo to take certain actions based on the status of my panel.  An example of this is to turn on all the lights in the house when the garage door is opened after dark ONLY if the Alarm is engaged.  In this scenario, I know the house is empty so we can turn on all the lights without disturbing anyone and we get to walk into a fully lit house.  Scenarios for how you can use this data are endless.

Bringing it all together

Now that we know how to get the data and how we’ll interface with Indigo, we need to write our script. As I mentioned previously, my choice is PHP which I will be running in CLI mode.  Fortunately, PHP CLI ships standard on the Mac platform so there is no setup required.

#!/usr/bin/php -q
<?php
 /**
 *  Author: Geek-Tips.com
 *    Date: 26 November 2010
 * Updated: 27 November 2010
 *    File: ad2usb-parser.php
 * Version: 0.4
 * Purpose: The scripts purpose is to capture the data stream that comes from the ad2usb device and
 *                    feed state change information into Indigo.
 * 
 *   Notes: V0.4: Removed getdata function to external file.
 *                    V0.3: Purchased Serial Bridge from Perceptive Automation to perform this function but
 *                    I seemed to have regular problems with that solution.  I also noticed that Serial Bridge
 *                    seemed to tax the CPU on my Home Automation server in a range from 20% - 85% which didn't
 *                    seem like a good overall solution.  I think the cpu issues may have been related to
 *                    to the fact that the solution was written for PowerPC which requires me to run Rosetta
 *                    and I wanted to get rid of that any way.  I sent a note to Jay over at Perceptive
 *                    Automation.
 *  
 *                    Usage: ./ad2usb-parser.php 
 * 
 *   Legal: AD2USB Parser by Geek-Tips.com is licensed under a Creative Commons 
 *                    Attribution-NonCommercial-ShareAlike 3.0 Unported License.
 *                    http://creativecommons.org/licenses/by-nc-sa/3.0/
 **/
 
 require_once("../functions/getdata.php");
 
 $alarm_state = "";
 $alarm_state_compare = "";
 $alarm_display = "";
 $alarm_display_compare = "";
 $indigourl = "http://127.0.0.1:8176/variables/";
 
 do{
 $handle = fopen("/dev/cu.usbserial-A2001wKL","r");
       $mintime = time();
       do{
 $str_ad2usb = fgets($handle);
 
 $alarm_state_compare = substr($str_ad2usb,1,3);
 $alarm_display_compare = urlencode(trim(substr($str_ad2usb,61,-3)));
 echo $str_ad2usb;
 
 if ($alarm_state_compare != $alarm_state) {
       if ($alarm_state_compare == '100') {
             $updateurl = $indigourl . "alarmstate?_method=put&amp;value=100+Disarmed";
             $result = get_data($updateurl);
       } elseif ($alarm_state_compare == '010') {
             $updateurl = $indigourl . "alarmstate?_method=put&amp;value=010+Armed+Away";
             $result = get_data($updateurl);
       } elseif ($alarm_state_compare == '001') {
             $updateurl = $indigourl . "alarmstate?_method=put&amp;value=001+Armed+Stay";
             $result = get_data($updateurl);
       }
             $alarm_state = $alarm_state_compare;
 }
 
 if ($alarm_display_compare != $alarm_display) {
       if ($alarm_display_compare != urlencode("DISARMED CHIME Hit * for faults")) {
             $updateurl = $indigourl . "alarmdisplay?_method=put&amp;value=" . $alarm_display_compare;
             $result = get_data($updateurl);
             $alarm_display = $alarm_display_compare;
       }
 }
 
 $str_ad2usb = '';
 sleep(1);
       }while( time()&lt; $mintime+60);
       fclose($handle);
 }while(1);
 
 fclose($handle);
 ?>

<?php
 function get_data($url)
 {
 $ch = curl_init();
 
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($ch, CURLOPT_HEADER, 0);
 curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1);
 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
 curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 4);
 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
 curl_setopt($ch, CURLOPT_URL, $url);
 
 $data = curl_exec($ch);
 
 curl_close($ch);
 return $data;
 }
 ?>

You will need to modify the code to match your setup. Assuming you are running the script on your Indigo server then all you should be required to change is the variable names. If not, you’ll need to change the URL for the Indigo webserver as well.

That’s really all there is to it! For more information on the data records produced by the AD2USB, check out this link and adjust the script to meet your needs.

You will notice that I close the connection to the port with each loop.  This may not be necessary but was implemented while trying to sort out the reliability issues mentioned above.  Future versions of the script will likely leave the connection open indefinitely, but this will need to be thoroughly tested.

Until next time, GEEK OUT!

If you use this script or publish modifications, please give credit and let me know by leaving a comment.

~GT~

   

 

In my last post I wrote about interfacing my Ademco alarm panel into my Home Automation (HA) network. Since I completed the installation I have had an on again and off again problem with the Mac receiving output from the AD2USB unit.

The problem manifested itself via the Serial Bridge software (more on that later) that I am using to receive the serial feed on my Mac.  After a period of time, it simply stopped logging messages.  My initial thought was that the AD2USB was faulty. To validate this, I terminaled into the device but immediately started receiving output again.  Without ever restarting Serial Bridge, it would start receiving updated messages and all was okay for a time.

My next thought was that the problem might be with the Serial Bridge software so I shut the program down and then terminaled into the AD2USB and just let the RAW data stream flow for a few hours and then I noticed that it too stopped receiving data from the AD2USB. At this point, my suspicion was directed back to the AD2USB itself.

I contacted Sean M from NuTech and he suggested that the problem might be with noise on the line and that I should try to insert a USB1.0 passive hub between the computer and the AD2USB.  While that may have helped, I don’t have any USB1.0 hubs laying around and getting one would require a purchase from eBay or Craigslist with no guarantee that the devices would even be functional. I was skeptical of this approach so I kept looking.

My next step was to look at the USB cable that I had running between the computer and the AD2USB.  I had just grabbed a cable from my stash without really paying any attention.  What I found was a 3ft, ultra-thin, unshielded cable. Since I have so much terminating into my wiring panel it seemed plausible that the thin, unshielded cable could be picking up noise so I decided to swap it out with a fully shielded albeit slightly longer cable.

Since that change, the system has been running without issue.  I’ll sit tight for a few days before I make a final judgment.

In part 3, I’ll pick up on the Indigo integration I promised in the first article in this series.

Until next time GEEK OUT!

~GT~

   

© 2012 Geek-Tips Suffusion theme by Sayontan Sinha