Posts Tagged ‘arduino’

Monitoring energy use with an Orb

Monday, 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

Sunday, 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.

HomeCamp ‘08

Sunday, 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.

(more…)

DIY Ambient Orb: Redux

Tuesday, 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

Wednesday, 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.

Arduino Ethernet Shield

Friday, 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.

Turning an Arduino into a Tweetject

Thursday, April 24th, 2008

A couple weeks ago I bought an Ethernet shield for my arduino with a plan to get it connecting to the world directly. The stripped down TCP implementation that comes with it is much more geared towards making the board act as a web-server rather than client. This means you have to poll for information rather than have the arduino send it out. Unfortunately, it is this second case that I am most interested in.

Julian Bleecker’s paper “Why Things Matter” introduced the term “blogjects” - objects that blog. A natural extension of which are “tweetjects” - objects that twitter. A good example being Tower Bridge which twitters whenever the bridge opens or closes and announces which ship is passing by. (Roo has written more on this stuff here.)

I see an ethernet-enabled arduino as a perfect platform for building such objects from. But to do this, it needs to establish the outgoing connection itself.

There is another shield that provides a much more powerful option based on the Lantronix XPort ethernet hardware. It even has a demo sketch that will post to twitter. The advantage of this shield is that it provides a serial interface to run the connection - putting much less strain on the arduino. However, this power comes at a cost - the XPort itself is around $50, whereas the Nuelectronics shield is £12.99 already assembled.

So for now, I am persevering with the cheaper board and have been learning far more about TCP packets than I ever thought necessary. So far, I have got my board doing an ARP request to map IP to MAC address, establishing a TCP connection and then sending a single blob of data (naturally, “HELLO WORLD”). This is all a couple layers lower down in the OSI model than I am used to working with in my day job.

It is still a bit too hard-coded to be easily reused and attempts to re-factor what I’ve done has broken it all; so I still have lots to do.

One thing I have discovered whilst playing with this all is Wireshark - a superb tool for sniffing packets on the network and examining their content. This has helped a lot in working out which bits and bytes are going awry in my packets.

DIY and decorating allowing, I hope to make progress on this over the next couple weeks.

Getting the doorbell online

Sunday, April 13th, 2008

Following Andy’s example, I have setup a twitter account for my own house to share its thoughts with the world on.

So far, it is busy twittering the changing temperature of my living room, as measured by the CurrentCost meter. At the moment it only tweets when the temperature changes at least 10 minutes since the previous change. This reduces some of the noise, but I think there is more to do. I don’t necessarily care if the living room is 16°C rather than 17°C but do care if it is too cold or hot. This is a subject I will come back to another time once I have done some more experiementing.

More immediately, I set myself a challenge this weekend; to get the doorbell twittering.

To begin with I bought a cheap wireless doorbell set from Wickes to play with. This came with two receivers; a portable battery-powered one and a mains-powered one. Wasting no time I took one of them apart to find this:

The circuit has a very conveniently packaged daughterboard containing the wireless receiver. The clue was the aerial connecting to it (the white wire to the right) and even better, in the top left corner are the four pins connecting to the rest of the circuit. With my trusty multimeter, and the labels printed on the board, it didn’t take long to work out the leftmost pin is ground, the rightmost pin is +3v and the other two are the magic data pins.

With my newly acquired arduino, itself a topic for another day, I hooked-up the four pins and fairly instantly had the arduino writing over its serial link to my laptop whenever the doorbell button is pushed. Of the two data pins, I found the one labeled “DAT” is the best trigger to use; the other one, “IDEL”, seems to be more noisy and needs investigating.

The doorbell lets you pick from one of 15 channels to ensure you don’t get interference from the neighbours. It also lets you pick one of three chimes to use, from the traditional ding-dong to the full Big Ben. As that setting is on the button itself, it must be sending it over the wireless signal. Currently my circuit triggers regardless of the channel setting of the button. I assume I need to do some more signal analysis on both the DAT and IDEL pins to figure this part out. For now, it works enough to prove the idea.

Here is the sketch I used. It does some simple debouncing by not triggering twice within 3 seconds.

int potPin = 5; // Connected to 'DAT'
int val = 0;

long time = 0;
long debounce = 3000;

void setup() {
  Serial.begin(9600);
}

void loop() {
  val = analogRead(potPin);

  if (val > 0) {
    if (millis()-time > debounce) {
      Serial.print("ON:");
      time = millis();
    }
  }
}

From this point, a bit of python and mqtt magic and the doorbell would be twittering. I say “would” as I haven’t done this final piece of plumbing yet. I only have one arduino at the moment and I am not yet ready to dedicate it to any one task. Clearly I need to order a second arduino - its always good to have separate development and production systems.

Links for 2007-12-27

Friday, December 28th, 2007

Note to self: now these are being auto-blogged, make more of an effort to add useful descriptions!