Monitoring energy use with an Orb

January 5th, 2009

I spoke at Homecamp recently about how an ambient orb could be used to monitor home energy usage. I’ve finally gotten around to putting some of it into practice so thought I would share some of the details of the setup as well as some more of my thoughts on the subject.

There are three key pieces of hardware in use. The Viglen MPC-L is the heart of the system. As I’ve mentioned previously, this is a low powered linux box running Ubuntu. The CurrentCost meter is connected to the MPC over USB-serial and my trusty arduino acts as an integration point for homebrew toys - including my ambient orb.

The MPC is running a Really Small Message Broker (RSMB). This is a small-footprint pub-sub message broker that talks MQTT. Each time the CurrentCost sends out a update, a piece of perl (”cc_pub.pl“) parses the data, sticks it into an RRDTool database for graphing and also publishes it to the home/cc/power and home/cc/temp topics.

Another piece of perl (”orbcontrol.pl“) is subscribed to the house/orb topic. When messages arrive on that topic, they are passed over serial to the arduino.

The sketch on the arduino currently listens on its serial port for commands that are then passed to the BlinkM in the orb. The format of the commands is identical to those in the BlinkMTester sketch that comes with the BlinkM. In the future this will do more as more things are attached to the arduino.

So far I have described how the orb is controlled and how the power data gets into the system. The next piece is how the two are plumbed together. Unsurprisingly, yet another perl script is running the on the MPC that provides the glue for this mixed metaphor.

orblogic.pl is subscribed to the home/cc/power topic so it receives all of the updates from the CurrentCost. It then makes a decision as to what colour the orb should be and then publishes the appropriate command to the house/orb topic.

Orb setup sketch

That is pretty much it - simple eh? Well, I did skip over the most interesting part - how to decide what colour the orb should be.

There are two key philosophies that come into play here:

  • Alert the unusual - have the ‘default’ state be the least obtrusive, such as ‘off’
  • Band the data - don’t react to single-point changes in the value. For example, when monitoring temperature, nothing is worse than constantly saying “its 19°C, its 18°C, its 19°C…”

These points should be applied whenever thinking about how to turn a raw stream of data into a useful stream of information.

I currently have a very simple piece of logic controlling the orb:

  • If power < 400, turn the orb off
  • If power between 400 and 1000, turn the orb orange
  • If power > 1000, turn the orb red

When we’re sat in the living room watching TV, we typically use under 400 watts, so the orb will only show anything if we’re over this value. It is very unusual to go over 1 kw unless we’re cooking, which is why that gets a stronger alert.

powergraph sketch

Despite its simplicity, this has already had the effect of making us more aware of when lights have been left on or when the kettle has finished boiling.

But as with all things, it could get much smarter. Having said we typically use under 400 watts watching TV, I also made the caveat ‘unless we’re cooking’. Given the system has a history of our power usage, it could feasibly determine suitable bands dynamically - so going over 1 kw between 6pm and 7pm isn’t necessarily a bad thing. Also, it chould only go red if the value goes over 1 kw for more than the time it takes to boil the kettle.

It all comes back to determining what is ‘unusual’.

Light Tent

January 4th, 2009

Inspired by mattb, andyp and make, I have made my own light tent. Made from a cardboard box, some tracing paper and masking tape, it took about 10 minutes to put together.

My first subject for the tent was my growing collection of arduino boards and shields.

Links for 2008-11-20 to 2008-12-18

December 18th, 2008

Upgrading the MPC-L from Feisty

December 12th, 2008

In a break from the norm, I have gone for a search friendly blog title as this is useful information that I couldn’t find myself

Currently, the Viglen MPC-L is shipped with Xubuntu 7.04 (Feisty). As of October this year, Feisty is no longer supported so any attempt to update the software results in plenty of 404 error messages like. A trawl around with google finally found this Launchpad response.

Based on that, here are my notes for upgrading from Xubuntu 7.04 to 7.10.

  1. Check you really are on 7.04 by running:
    :~$ lsb_release -a
  2. Disable the screensaver. Once running, the upgrade takes an hour or so and you do not want the screensaver to activate. Both AndySC and I found we couldn’t unlock the screen after the upgrade had completed overnight and the only thing to do was reboot. That said, the reboot didn’t harm the upgrade, but it is better to be safe.
  3. Download the Xubuntu 7.10 alternate CD ISO (torrent). It may seem obvious, but make sure you get the Xubuntu CD, not the Ubuntu one. Using the Ubuntu one will fail and you’ll have wasted half-an-hour downloading the ISO - I speak from personal experience.
  4. Mount the ISO locally:
    :~$ sudo mount -o loop \
       ~/Desktop/xubuntu-7.10-alternate-i386.iso \
       /media/cdrom0
  5. A dialog will appear prompting you to upgrade from the CD. If it doesn’t appear, run:
    :~$ gksu "sh /cdrom/cdromupgrade"
  6. When it asks if you would like to include the latest updates from the internets, you say “No”. If you say “Yes” you hit the same 404s you spent an hour trying solve before going down this path. Again, personal experience.
  7. After about a few minutes of sorting out what it needs to do it will start installing the new packages. I found it prompted me for input about 3 times early on in the ~1 hour install time and then ran to completion without further interaction - YMMV.
  8. Reboot as prompted and enjoy.

This should hopefully get you onto Gutsy, from where you can use the regular Update Manager to upgrade to Hardy and beyond.

Given the pain it is to upgrade from Feisty now, I hope Viglen will update their pre-install image soon. I’m also surprised that Ubuntu consider this an acceptable path even if Feisty is no longer supported.

Update: as per Andy’s notes, when you upgrade from Gutsy to Hardy, make sure the Universe repository is enabled, otherwise it will fail as the xubuntu-desktop package moved repositories between these releases.

1000th Tweet

December 3rd, 2008

1000th Tweet Haiku

HomeCamp ‘08

November 30th, 2008

Today was the first homecamp - “an unconference about using technology to monitor and automate the home for greener resource use and to save costs”.

Whilst I hadn’t entirely planned to, I found myself stood up front leading a couple sessions; one on what I’ve been doing with arduino and one a brief overview of what MQTT is.

Read the rest of this entry »

DIY Ambient Orb: Redux

November 25th, 2008

Orb

Orb Base

RJ11

/************************************************
 * Enables a BlinkM to be controlled over MQTT.
 *  - subscribes to the topic 'blinkm'
 *  - expects messages of the format 'RRGGBB'
 *  - doesn't do any error handling
 *
 *    Nicholas O'Leary
 *    http://knolleary.net
 ************************************************/
#include <Wire.h>
#include <Ethernet.h>
#include <PubSubClient.h>
#include <BlinkM_funcs.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 172, 16, 0, 50 };
byte server[] = { 172, 16, 0, 100 };

void callback(char* topic, byte* payload,int length) {
  byte a = toHex( payload[0],payload[1] );
  byte b = toHex( payload[2],payload[3] );
  byte c = toHex( payload[4],payload[5] );
  BlinkM_fadeToRGB( 0x09, a,b,c);
}

PubSubClient client(server, 1883, callback);

void setup()
{
  BlinkM_beginWithPower();
  BlinkM_setAddress( 0x09 );
  BlinkM_stopScript( 0x09 );

  Ethernet.begin(mac, ip);

  if (mqttClient.connect("blinkr")) {
    mqttClient.subscribe((uint8_t*)"blinkm");
  }
}

void loop()
{
  mqttClient.loop();
  delay(500);
}

// a really cheap strtol(s,NULL,16) - taken from BlinkMTester
#include <ctype.h>
uint8_t toHex(char hi, char lo)
{
    uint8_t b;
    hi = toupper(hi);
    if( isxdigit(hi) ) {
        if( hi > '9' ) hi -= 7;
        hi -= 0x30;
        b = hi<<4;
        lo = toupper(lo);
        if( isxdigit(lo) ) {
            if( lo > '9' ) lo -= 7;
            lo -= 0x30;
            b = b + lo;
            return b;
        }
    }
    return 0;
}

CurrentCostuino

November 19th, 2008

With homecamp fast approaching I spent some time last weekend reviving some CurrentCost hacking I started in the summer.

One of the downsides of the data connection on the CurrentCost is the need for an always-on computer in order to capture the data. In practice, the existence of low powered machines like the MPC-L, or slug, make this a pretty inconsequential downside. That said, it was enough motivation to see what I could do with an Arduino and Ethernet Shield.

I have previously mentioned that part of the setup used to graph the power data online was to publish the data to a broker-in-the-sky using MQTT. To achieve this with an arduino it was clear that I needed one thing in particular - an arduino that is capable of connecting and publishing to an MQTT server.

With my ethernet shield in hand, I set about implementing enough of the MQTT spec to support basic publishing and subscribing. With that working, I looked into getting the arduino and CurrentCost talking. Thanks to Alexis, this was very straightforward, although I did rework the parsing of the data to take advantage of its somewhat-fixed length format.

Here’s the sketch I ended up with:

#include <Ethernet.h>
#include <PubSubClient.h>
#include <SoftwareSerial.h>

byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 172, 16, 0, 50 };
byte server[] = { 172, 16, 0, 103 };

PubSubClient client(server, 1883,0);

#define rx 6
#define tx 7

SoftwareSerial softSerial =  SoftwareSerial(rx, tx);

void setup()  {
  pinMode(rx, INPUT);
  pinMode(tx, OUTPUT);
  softSerial.begin(9650);
  Ethernet.begin(mac, ip);
  delay(500);
}

void connect() {
  while(!client.connect("nolcc")) {
    delay(10000);
  }
  delay(200);
}

int offset = -1;
void loop() {
  if (!client.connected()) {
    connect();
    offset = -1;
  }
  client.loop();

  // scan the data for <msg>
  while(offset == -1) {
    char c = ' ';
    while (c!='<') {
      c = softSerial.read();
    }
    if (softSerial.read()=='m' &&
        softSerial.read()=='s' &&
        softSerial.read()=='g' &&
        softSerial.read()=='>') {
      offset = 5;
    }
  }

  // skip to the current value
  while(offset < 156) {
    offset++;
    softSerial.read();
  }
  char current[5];
  int value = 0;
  for (int i=0;i<5;i++) {
    current[i] = softSerial.read();
  }
  offset += 5;

  // skip to the temperature value
  while(offset < 243) {
    offset++;
    softSerial.read();
  }
  char temp[5];
  for (int i=0;i<4;i++) {
    temp[i] = softSerial.read();
  }
  offset += 4;

  client.publish("current",(uint8_t*)current,5);
  client.publish("temp",(uint8_t*)temp,4);

  // scan for </msg>
  while(offset != -1) {
    char c = ' ';
    while (c!='<') {
      c = softSerial.read();
    }
    if (softSerial.read()=='/' &&
        softSerial.read()=='m' &&
        softSerial.read()=='s' &&
        softSerial.read()=='g' &&
        softSerial.read()=='>') {
      offset = -1;
    }
  }
}

It publishes each power reading to a topic called ‘current’ and each temperature reading to a topic called ‘temp’. This isn’t quite the right configuration for the existing broker setup, but it wouldn’t take much to modify it appropriately.

You’ll note this sketch isn’t much use without the library that does the MQTT bit. Luckily, I have been given permission to release the library to the world. I should stress at this point, in case it wasn’t obvious from the fact I am releasing this code on my personal site, that my employer has nothing to do with it.

You’ll find the Client for MQTT library here.

If you want an MQTT server to play with, go buy Lotus Expeditor to get your hands on a microbroker <gratuitous-plug />, or check out the links on mqtt.org for the Really Small Message Broker.

Photo Calendar 2009

November 10th, 2008

I like to take the odd photo now and then. Last year, with the help of Lulu I put together a calendar that featured some of my favourite photos as a Christmas present for my parents and in-laws.

This year I have done the same, and as the surprise factor is no longer there, I have decided to make it available to anyone who wants to buy one. They cost £8.25 excluding postage - none of which is profit or will go to charity.



Support independent publishing: buy this calendar on Lulu.

Arduino Ethernet Shield

November 7th, 2008

Earlier this year, I was fortunate enough to get a pre-release Arduino Ethernet shield from the good folk at tinker.it to play with. At that time, I had spent some time trying to improve the TCP-stack for the nuelectonics ethernet shield, but that was hard work and I wasn’t making much progress.

The advantage of this new shield is that all of the hard work is done for you - the API provided is very simple to use and doesn’t take up too much program space. It also includes an SD card slot and although that isn’t supported in the library yet, it’s potentially a very cool addition.

Massimo has now announced the shield to the world. Hopefully they will be available from the tinker.it store soon.

Arduino Ethernet Shield

I have a cool project on the go using the shield that I’m going to hold off writing about for the moment. It touches close to what I get paid to do at work, so I have to go through a few hoops before I can make the code available publicly. Anyone following my twitter stream will have a good idea what it is already.

My plan is to write it up and release the code in time for HomeCamp, as it will tie in very nicely to some of the topics being discussed there.