Internet connected devices: Using Pachube to control a fan

матрациFor a little while now I have been tinkering with a number of Arduino boards, including the Arduino Diecimila, Duemilanove, Freeduino, Jeenode and stripboard versions to see what I could do with them. So far I have been able to:

  • Blink a LED
  • Display messages on LCD screen
  • Display messages on LED Matrix displays
  • Move servo motors
  • Read temperature and humidity remotely
  • Keep time with a real time clock
  • Build internet connected clock
  • Broadcast Currentcost readings over ethernet
  • Tweet updates
  • Send temperature values to Pachube
  • Turn lights on and off by sending signals to Home Easy devices
  • Create colours with RGB LEDs
  • etc, etc, etc…

These are all mainly simple standalone projects that demonstrate how easy it is to develop microcontroller systems using the Arduino platform. When a number of small projects are combined, things can start to get interesting.

The problem

My home office is in my conservatory that I had built some years ago. The problem is that it can get very warm on a sunny day. I don’t have air-con, just a simple desk fan and blinds. Now what I’d like to do is switch on the fan when the temperature rises and switch it off when it gets cooler.

Possible Solutions

As with any problem, there are a number of solutions:

  • Create a box that the fan is plugged into that measures temperature and turns on a relay at a preset temperature and turns it off when the temperature drops. This would have been fairly simple to do, however it would have required a new circuit to have been built that exposed me to mains wiring. Then the appropriate software would need to be written. The disadvantage here is that it serves one purpose and cant easily be re-used with out re-programming.
  • Use a number of existing projects, namely I am already monitoring temperature in my conservatory via Pachube. I have a network enabled Home Easy transmitter. So why not put them together?

Final Solution

I opted to use what I already had, the Pachube feed already existed. I had previously used the trigger functionality to call a php script and send an email. It is this functionality that I use to control the fan.
The other end of the system is described in my post Arduino and remote control of Home Easy devices. I just needed to set up my internet router to forward requests from the Pachube servers to my Home Easy control Arduino.

I then setup a pair of triggers on the temperature datastream on one of my feeds. The first trigger calls the URL to turn on the fan when the temperature is greater than 24′C and the second to turn it off when the temperature is 24′C or lower. Using the Debug buttons you can test the triggers to make sure everything is working as it should. The temperatures chosen here are just my preferences and can be changed in the trigger rules to suit your environment.

Initial testing using the web control example showed that it didn’t work with the way the Pachube trigger URLs are called. The code was modified to fix this. (Updated code being cleaned up and should be released later).

For mode information on Pachube triggers have a read of the Pachube page Triggers (aka webhooks, notifications, etc.).

So now I have a fan that comes on automatically when it gets warm and turns off when it gets cooler.

Future changes

With being able to control mains powered devices remotely by integrating it with the Pachube trigger functionality, it is therefore possible, later in the year to alter the temperature settings on the triggers and swap the fan for a heater. Although on safety grounds I’m not keen to leave a heater unattended.

Other possible uses could be:

  • Turn a light on when it gets dark, turn it off when it gets light
  • Control your central heating when it gets cold unexpectedly

One thing I have found is that the Pachube triggers are are checked about every 5 minutes mean ing that the minimum time the fan would be on is 5 minutes.

Cautions

Its all very well controlling devices this way, but these methods should not be relied on for anything other then educational value. There are so many things that can and will go wrong:

  • Power failures in your home – no readings taken and no control signals accepted
  • Your internet connection may die
  • If you have a dynamic IP address you’ll need some way to keep track of it for the Pachube trigger URLs
  • Pachube may be down for whatever reason

Final word

As you can see, a few simple building blocks can be combined to control devices based on environmental conditions. This can be expanded using no more than adding extra triggers to your Pachube datastreams.

TFT LCD Touchscreen shield for Arduino – Review

I have recently bought one of the new TFT LCD touchscreen shields from Nuelectronics and this is my experience when using it with the library provided. There are two versions of the shield with the only difference I can see is that one has a 2.4″ display and the other has a 2.8″ display. Both offer the same display size of 320×240 pixels. These are priced at £25 for the 2.4″ and £35 for the 2.8″. The smaller display seems the better value in this case. If the larger display was closer to the smaller display price then I may have opted for this instead.

Hardware

Due to the size of the displays available, both the 2.4″ and 2.8″ use the same PCB. The problem with this is that it is larger than the regular Arduino shields. The distance between the two rows of pins is also slightly wider, at 50mm, than the normal 48mm, to accommodate the 2.8″ display. The pins are angled inwards slightly which makes for a very tight fit when plugged into an Arduino or clone.
The touchscreen on the LCD display has 4 icons that I presume are at the bottom but could equally be the top. The display carrier on the board I received keeps lifting up from the pcb. It appears to have been stuck down with double sided tape. I’m not prepared to try to remove the display and re-stick it, just yet.

The touchscreen has 4 icons along one edge. These are outside of the display area and can be used to trigger actions in your application without having to use up screen space with icons, if required. As with all touchscreens they can be easily scratched so I have added a screen protector using a spare Nintendo DS protector I had. I am also using a spare DS stylus too.

One major issue with the touchscreen controller is that the PENIRQ interrupt is not connected to the Arduino so you have no indication that the screen has actually been touched. I think this is a serious omission from this shield. You can test the PENIRQ signal by connecting a LED and current limiting resistor between holes 34 (Anode) and 36 (Cathode) on the double row of holes at the edge of the shield. The LED will be on until you touch the display. One way round this shortcoming could be to connect this pin to AD3 configured as a digital input and only take a reading when this was low. Another way would be to improve the reading capabilities to return and indicator to show the value was real and not noise.

From looking at the schematic for the shield, there doesn’t appear to be much I/O left for other use on the standard Arduino. All I can see is that AD3 to AD5 are free, therefore to connect anything else would require using the I2C/Wire library implemented on AD4 and 5.

Hardware used:

  • AD7843 – Touchscreen controller – Uses SPI long with SD card
  • ILI9325 – LCD controller – Uses parallel digital I/O

Software

The library provided is referred to as pre-release, which could mean that it is incomplete and an updated library will be available at some time in the near future. It is still usable, however there is no documentation and the code has very few comments so once the examples have been run you’re on your own! I plan on writing a new post to provide the missing information, watch this space.

The library provided includes classes for accessing SD card, touchscreen and LCD display. Other classes are included for drawing basic graphic elements and text. The one issue I have found so far is that with the circle drawing function, when the point goes outside of the display it is actually mirrored on the display so it looks like the edge of the circle has been folded in on itself. To fix this problem, edit file TFT_ILI9325.cpp and add the following at the beginning of the function putPixel:


if( x<0 || x >= GetWidth() || y < 0 || y >= GetHeight())
return;

I tried a simple drawing test where a small circle is drawn where the stylus touches, this didn’t appear to be as accurate as I hoped with some points being drawn in completely the wrong places!

I’ve not yet tried any of the other functions as this was only a quick late night test.

Examples

Two examples are provided, the first being a touch screen calibration utility. This lets you touch a series of points on the screen to provide calibration data that is then stored in the Arduino eeprom. This data can then be read when you come to use your own touchscreen application. The second part of the utility shows the X and Y coordinates as you drag a stylus across the screen.

I did notice that the values for the X axis seem to fluctuate quite a lot so the touchscreen reading functions need to be looked at in order to stabilise and provide more accurate readings. If there was no touches then it was still giving a reading which is not ideal.

The second example demonstrates reading bitmap images from the SD card in a simple slideshow. The images need to be in BMP format with a maximum resolution of 320×240 although I think this might actually want to be 240×320 as the display seems to be orientated vertically.

One issue with the bitmap display is that the images come out upside down and back to front so this needs to be looked at.

Conclusions

Overall a cheap introduction to big LCD resolution and touchscreen control for the Arduino, however to be any use the library needs to be documented fully and the problems fixed.Using the SD card to store images and icons can reduce the program memory requirements. I would see the display being more useful on an Arduino Mega once that version is available. It would then be able to utilise the 16 bit transfer mode and provide more memory and I/O to make it useful.

On the regular 168/328 based Arduino I see this having not much use other than as a testing and learning tool. However I could be proven wrong. Arduino Tetris anyone?

A database scheme for capturing sensor data

I’ve been monitoring a number of sensors in the house for a while now and storing the results in a simple database table. However the current structure isn’t very flexible. I have one table for electricity data, another for inside/outside temperature, humidity and light levels. Adding more sensors would mean adding more columns or new tables. What I needed is a schema that would allow me to grow the number of sensors without having to change the schema each time more were added.

What I have come up with is a number of tables linked by foreign keys to keep the integrity together.

Monitoring db schema

Tables:

  1. Locations – A list of physical sensor locations, usually a room or location within the house/garden/garage.
  2. Sensors – A list of sensors, measuring a single value. Could be temperature, humidity, light, electricity usage etc. These are linked back to the location table so multiple sensors are present in a location.
  3. Readings – These are the individual time stamped readings from the various sensors.
  4. Pachube_feeds – This is a table to indicate which sensor data maps to a particular pachube feed and datastream. Not all sensors would need or have a pachube feed, but probably most of them. The table could be extended to include the full pachube config details so that new streams can be added to pachube automatically.

The database design was created using MySQL workbench 5.2 beta. This allows you to design your database structure then create the sql that can be used to build the tables. The MySQL workbench 5.2 is a replacement for the old gui tools and includes database design, administration and development all in one tool. The exported sql was executed using phpMyAdmin although it could easily have been done with the command line.

The applications that read the various sensors just need to write the readings to a single table as they are received. Queries can then be performed with joins to retrieve the units, sensor name and location.
If Pachube updates are required then the various feeds and streams can be updated with the latest value for each sensor.

At present one of the jeenodes is sending readings to an arduino receiver that is connected to a linux server running a simple perl script that writes the values to the readings table using a simple insert statement:


INSERT INTO `homeserver`.`readings` (`sensor_id`, `timestamp`, `value`) VALUES ( 1, CURRENT_TIMESTAMP, '12.34' );

The sensor number in this case is 1 and the value is 12.34.

A simple query that gives a summary of readings by location, type, reading and units:

SELECT r.timestamp, l.name as location, s.name as type, r.value, s.units
FROM `readings` r
JOIN `sensors` s ON s.sensor_id=r.sensor_id
JOIN `locations` l ON l.location_id=s.location_id
ORDER BY r.timestamp ASC;

New devices: Jeenodes

I have now built a trio of Jeenodes from Jee Labs based in the Netherlands. These are simply cut down versions of the Arduino with a built in RFM12B wireless module operating in the 868MHz band. They are designed to operate at 3.3V so are able to run on a set of batteries, which is ideal for remote monitoring applications.

The USB to serial interface has been removed so any programming needs to be done via the end connector and a FTDI USB interface. This can either be a dedicated cable or a regular Arduino with the 168/328 chip carefully removed. Its then a case of wiring the connections to Reset, +5V, Ground, TXD and RXD. Remembering that RXD on the Arduino actually needs to go to TXD on the Jeenode and vice-versa. For this I just plugged the Jeenode into a solderless breadboard and used jumper wire to connect to the Arduino.

With the Jeenodes being compatible with the Arduino IDE it can then be used to develop applications.

The first applications are to be a simple temperature/humidity monitor to replace an ethernet connected arduino that is currently living behind the sofa and sending updates to Pachube/Twitter. What is still required is a base station that will receive the transmitted signals in order for them to be captured and logged.

More later

Arduino and EtherShield – Sending UDP broadcast messages

With the ENC28J60 EtherShield, it is possible to create packets other than the regular HTTP and web packets. The UDP packet is one of these. It is simple and connectionless making minimum overhead needed to create packets. In developing the UDP broadcasts I’ve had to expose a number of functions in my EtherShield library, these are for building the packets and calculating checksums.

The broadcast example featured here is included as an example in the library. The new library is compatible with my previous versions available from this site.

Setting up the ethernet requires a number of addresses to be configured. The broadcast address used is the network broadcast for the local LAN, in this example is it 10.0.0.255:

// Define mac and IP addresses to use
static uint8_t mymac[6] = { 0x54,0x55,0x58,0x10,0x00,0x28 };
static uint8_t myip[4] = { 10,0,0,28 };
static uint8_t broadcastip[4] = { 10,0,0,255 };
// Destination Port 52240
#define DEST_PORT_L  0x10
#define DEST_PORT_H  0xCC

The UDP Payload in the example is stored in a simple struct, this is then copied into the packet and broadcast to all those that are listening on the LAN:

struct UDPPayload {
  uint32_t time;            // Time
  uint16_t temperature;     // Temp in 1/10 degree
  uint16_t data[10];        //watts data
  uint16_t errorCount;      // count of errors in the XML.
  uint16_t timeout_count;   // count of all protocol lockups
};
UDPPayload udpPayload;

Initialise the payload:

  // Initialise data in the payload structure
  for( int i=0; i<10; i++ ) {
    udpPayload.data[i] = i;
  }
  udpPayload.time = millis();
  udpPayload.temperature = 0;

The final step is to build and send the broadcast message:

void broadcastData( void ) {
  uint8_t i=0;
  uint16_t ck;
  // Setup the MAC addresses for ethernet header
  while(i<6){
    buf[ETH_DST_MAC +i]= 0xff; // Broadcsat address
    buf[ETH_SRC_MAC +i]=mymac[i];
    i++;
  }
  buf[ETH_TYPE_H_P] = ETHTYPE_IP_H_V;
  buf[ETH_TYPE_L_P] = ETHTYPE_IP_L_V;
  es.ES_fill_buf_p(&buf[IP_P],9,iphdr);

  // IP Header
  buf[IP_TOTLEN_L_P]=28+sizeof(UDPPayload);
  buf[IP_PROTO_P]=IP_PROTO_UDP_V;
  i=0;
  while(i<4){
    buf[IP_DST_P+i]=broadcastip[i];
    buf[IP_SRC_P+i]=myip[i];
    i++;
  }
  es.ES_fill_ip_hdr_checksum(buf);
  buf[UDP_DST_PORT_H_P]=DEST_PORT_H;
  buf[UDP_DST_PORT_L_P]=DEST_PORT_L;
  buf[UDP_SRC_PORT_H_P]=10;
  buf[UDP_SRC_PORT_L_P]=srcport; // lower 8 bit of src port
  buf[UDP_LEN_H_P]=0;
  buf[UDP_LEN_L_P]=8+sizeof(UDPPayload); // fixed len
  // zero the checksum
  buf[UDP_CHECKSUM_H_P]=0;
  buf[UDP_CHECKSUM_L_P]=0;
  // copy the data:
  i=0;
  // most fields are zero, here we zero everything and fill later
  uint8_t* b = (uint8_t*)&udpPayload;
  while(i< sizeof( UDPPayload ) ){
    buf[UDP_DATA_P+i]=*b++;
    i++;
  }
  // Create correct checksum
  ck=es.ES_checksum(&buf[IP_SRC_P], 16 + sizeof( UDPPayload ),1);
  buf[UDP_CHECKSUM_H_P]=ck>>8;
  buf[UDP_CHECKSUM_L_P]=ck& 0xff;
  es.ES_enc28j60PacketSend(42 + sizeof( UDPPayload ), buf);
}

The payload could be a structure or a text string, just replace the sizeof() functions with strlen(). With using text strings of the correct format is is then possible to create Syslog messages. The only issue here is that you would need a real time clock to provide the correct timestamp header. In practice I have seen my linux syslog daemon accept syslog messages with invalid or missing timestamps and replace it with its own.

Receiving broadcasts using Perl on Linux
Using a simple perl script the broadcast messages can be received and processed. The example below is receiving the broadcast packets and extracting currentcost data. The format of the payload is similar to the example shown above.

#!/usr/bin/perl -w
# cclisten - UDP Currentcost listener
use strict;
use IO::Socket;
my($msglen,$sock, $newmsg, $MAXLEN, $PORTNO);
my($lasttimestamp,$timestamp,$tempr,$watts,$errcount,$timeouts);

# Pachube.com values
my $pachubeApiKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
my $pachubeFeed = "nnnn";

# Keep track of how many sample and total for updating pachube once a minute
my $sampleCount = 0;
my $totalWatts = 0;

$MAXLEN = 1024;
$PORTNO = 52240;
$sock = IO::Socket::INET->new(LocalPort => $PORTNO,
        Proto => 'udp',
        LocalAddr => '10.0.0.255',
        Broadcast => 1)
    or die "socket: $@";
print "Awaiting UDP messages on port $PORTNO\n";
$lasttimestamp = 0;
while ($sock->recv($newmsg, $MAXLEN)) {
    $msglen = length($newmsg);
    $timestamp = unpack("L", substr( $newmsg, 0, 4));
    $tempr = unpack("S", substr( $newmsg, 4, 2)) / 10;
    $watts = unpack("S", substr( $newmsg, 6, 2));
    $errcount = unpack("S", substr( $newmsg, 26, 2));
    $timeouts = unpack("S", substr( $newmsg, 28, 2));
    if ( $timestamp != $lasttimestamp ) {
        $lasttimestamp = $timestamp;
        $sampleCount++;
        $totalWatts += $watts;
        print "Time $timestamp temp = $tempr errors $errcount Timeouts $timeouts Ch0 Watts $watts\n";
        # Update RRD
        system( "/usr/bin/rrdtool update currentcost.rrd N:$watts:0");
        # Update pachube once a minute with a minute's worth of averaged data
        if ( $sampleCount > 10 ) {
                # Do a little formatting on the output
                my $averageWatts = sprintf("%.2f",$totalWatts / $sampleCount);
                system("curl -s --request PUT --header 'X-PachubeApiKey: $pachubeApiKey' --data $averageWatts 'http://www.pachube.com/api/$pachubeFeed.csv'");

                # Reset the counts
                $totalWatts = 0;
                $sampleCount = 0;
        }
    }
}
die "recv: $!";

Downloads

Arduino sending requests to PHP script

I’ve been asked by a number of people to provide an example of using the EtherShield library to pass data to a PHP script, to for example store sensor data in a database.

The example here is based on existing code that reads the SHT1x temperature and humidity sensor. The results are passed as parameters to a php script running on a local linux server. The php script then saves the results in a simple text file.

The url format for this example is

http://10.0.0.2/storedata.php?p1=temp&p2=humidity&p3=dewpoint

The example Arduino sketch can be downloaded here

The PHP script used to test is


< ?php
$p1 = $_GET['p1'];
$p2 = $_GET['p2'];
$p3 = $_GET['p3'];

$timestamp = mktime();
//echo "Timestamp is ".date("d/m/Y H:i:s", $timestamp);

$your_data = date("d/m/Y H:i:s", $timestamp) . "," . $p1 . "," . $p2 . "," . $p3
. "\n";

echo "OK";

// Open the file for appending
$fp = fopen("/var/www/data.txt", "a");

// Write the data to the file
fwrite($fp, $your_data);

// Close the file
fclose($fp);
?>

This creates a file like this:


07/01/2010 20:58:04,18.95,41.16,5.51
07/01/2010 20:58:34,18.91,40.94,5.37
07/01/2010 20:59:04,18.62,41.69,5.41
07/01/2010 20:59:34,18.48,42.03,5.40
07/01/2010 21:00:04,18.50,41.86,5.36
07/01/2010 21:00:34,18.44,42.01,5.39

Arduino and remote control of Home Easy devices

I had bought a number of devices from the Home Easy On/Off Range, including 6 HE302S sockets and two HE300 remote controls. It was my intention to be able to remotely control these from an Arduino. The devices use the 433MHz AM radio band to communicate with the sockets being receivers and the remote being the transmitter. More information and links are available on the Home Easy Hacking wiki including links to the required RF modules.
I used the modules from Maplin Electronics, part number VY48. The transmitter is simply connected to ground, power, pin 4 for data and a 170mm antenna. I have also combined the receiver onto a stripboard shield (Circuit and layout still to follow) with jumpered links to enable power to the receiver or transmitter depending on which is to be used at the time.

Library

Any bit of hardware works best with a library, the code used is based on code available from the Arduino Home Easy playground article. The HE300/HE302S use what has been termed the advanced protocol even though it is just a basic on/off action. The code was formed into a library with the constructor being passed the port pins that are to be used for the transmit and receive signals as well as the ID to use for the remote. The library is divided up into the transmit and recieve halves and these can be compiled in or not depending on the final application.

Library functions:

  • Send Single channel On/Off
  • Send Group On/Off
  • Receive data from remote control

Examples

I have included 3 examples with the library:

  • Simple On/Off – one channel is turned on then 3 seconds later turned off
  • Group On/Off – group is turned on then 3 seconds later turned off
  • Receive – functions are assigned to remote buttons and executed. Example operates 4 LEDs based on remote button presses.

A further example, not included with the library is for an ethernet controlled Home Easy transmitter. This uses the updated ENC28J60 EtherShield library although the functionality could be replicated with the official Arduino Ethernet shield. When running you point a web browser at the IP address and correct port for your Arduino, a simple web page is displayed. This then allows you to turn on and off the first 4 channels as well as turning on and off the group. For a more complex control application the URLs can be accessed from another server using PHP for example. The URLs have the form /on=x and /off=x where x is the channel number to switch in the range 0-15. For the group control use /gon and /goff.

It is possible, and I have tried it, to use this via the internet and a mobile phone. You would need to change the default port from 80 to something else and setup your broadband router to perform port forwarding. The exact settings needed are outside of the scope of this article.
Warning: this is a simple application and there is no security built into it, therefore it will be possible for someone to access your Arduino and turn on and off whatever it is that you are controlling. I accept no responsibility for however you decide to use this code.

Downloads

HT1623 based LED Matrix Displays and Arduino

Recently I’ve been playing around with a pair of 8 x 32 LED matrix displays and come up with the beginnings of a library to drive this display. Basically it extends the Print class to provide easy output to the display. Upto 4 of the displays can be cascaded together to produce a single 8 x 128 LED matrix display that is about 60cm in length!

The displays can be cascaded in different configurations but these have not yet been investigated yet. This would be a future development for the library. At present I only have two of these displays so am limited to the configurations possible.

The code is based on code from a number of contributors to the Arduino forum. The sample application is based on some previous software that enabled an Arduino and LCD display to emulate the instruction set for Matrix Orbital LCD displays. These have a serial interface and can be driven from a Windows PC using LCDSmartie. I’ve nto yet been able to get LCDProc working as all the configs look for a two line display These applications deal with all the scrolling and character positioning. The Arduino only then has to perform basic character drawing and positioning.

Update

The library has been updated to include a couple of changes from John Crouchley with regard to the port pin setup. I have also included the ability to alter the brightness of the LEDs. This does work from LCDSmartie too.

Downloads

Demo Video

Nokia 3310 LCD Library with basic graphics functions

After buying one of the Nokia 3310 LCD with joystick shields from Nuelectronics.com I wanted the library to do more in the way of graphical functions. After re-writing the library, cleaning it up and renaming all the functions I now have a library that can do what I want it to do.

The library includes functions for:

  1. Text display
  2. Large digits
  3. Plot single pixel
  4. Draw line between two points
  5. Draw a rectangle given two opposite corners
  6. Draw a filled rectangle
  7. Draw circle
  8. Display a bitmap from flash memory
  9. Clear an area of the screen

Update 1

The library has been updated by John Crouchley to inherit the Print class to produce an easier method of printing strings, numbers and general text formatting. Other changes include:

  • Allow for multiple SPI devices
  • Move get_key into the class
  • Fix bug in writeChar
  • Additional bounds checking

Update 2

I have now made some further updates to the library, the changes are:

  • Created new big font. This is much neater looking than original.
  • Updated 5×7 font as % was one row too low.
  • Updated example to include print functions and degree symbol

Update 3

This is a minor update to enable the library to work with newer displays available from Nuelectronics. Previous library may may show a very dark display. The temperature coefficient and contrast values have been updated in the initialisation function.

Example Application

The example application is based on the original Nuelectronics example but displays the values from a real temperature/humidity sensor, the SHT11, using a modified library from http://www.practicalarduino.com/news/id/211. The modification is the addition of the readDewPoint function. The menu also includes a demo option which gives a run through the graphical functions by drawing circles, lines, rectangles, displaying a full screen bitmap and a simple animation using bitmaps.

Downloads:

  • nokia_3310_lcd.zip – Updated library with Johns changes, second and third update changes.
  • SHT1x.zip – Updated library for accessing temp/humidity sensor.

Demonstration video

CurrentCost CC128 working with RRD, Pachube and Twitter.

After finding the instructions at http://www.jibble.org/currentcost/ to create a basic perl script that read the Currentcost datastream, parsed the XML and updated a RRD file I was able to create some power usage graphs. Using the RRDTool CGI application on a local linux box with the apache webserver I’ve got graphs for the last 10 minutes, 60 minutes, 6 hours, 24 hours, 7 days, month and year. However as tis is not internet facing, using an updated perl script I can now update a pachube.com feed. The pachube updates are once per minute so as to not exceed the api posting limits.

With the CC128 there is a history output that is generated every 2 hours, this includes the total kWh used on a daily basis. With an addition to the perl script I can now get a daily usage value that is used to update my Home automation twitter feed.

The script used is as follows: (Please note, this has been updated on 3rd September 2009 to include a daily cost calculation and to fix an issue with the history information attempting to update the rrd file)

#!/usr/bin/perl -w
# Reads data from a CurrentCost CC128 device via serial port.
# Based on script at http://www.jibble.org/currentcost/
#
# Heavily updated to include pachube.com updates every minute
# and a daily tweet at twitter.com for previous days power usage
#
# Andrew Lindsay http://blog.thiseldo.co.uk
#

use strict;
use Device::SerialPort qw( :PARAM :STAT 0.07 );

# Alter these values to suit your configuration
# Serial port CC128 connected to
my $PORT = "/dev/ttyS0";

# Pachube.com values
my $pachubeApiKey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
my $pachubeFeed = "NNNN";

# twitter.com values
my $twitterUser = "USERNAME";
my $twitterPass = "PaSsWoRd";
# Set your own values here
my $unitCharge = "0.115";       # 11.50p
my $standingCharge = "0.1441";  # 14.41p

# End of configuration

# Setup the serial port.
my $ob = Device::SerialPort->new($PORT);
$ob->baudrate(57600);
$ob->write_settings;

print "Reading currentcost datastream\n";

open(SERIAL, "+>$PORT");

# Keep track of how many sample and total for updating pachube once a minute
my $sampleCount = 0;
my $totalWatts = 0;

while (my $line = ) {
        # History received every 2 hours, look for last day, d001 and limit to whole house sensor for now.
        if ($line =~ m!.*0.*(\d+\.?\d*)1.*!) {
                # process history output
                print "$line\n";
                my $histSensor = "0";
                my $kwatts = $1;
                my $cost = sprintf("%.2f",$standingCharge + ($unitCharge * $kwatts) );
                # Tweet yesterdays usage, only need do this once per day if hour is 0
                my ($second, $minute, $hour, $dayOfMonth, $month, $yearOffset, $dayOfWeek, $dayOfYear, $daylightSavings) = localtime();
                print "Got a match for day 1, sensor $histSensor Watts $kwatts kWh Hour $hour\n";
                if( $histSensor == "0" && $hour < "2" ) {
                        print "Tweet\n";
                        print "Yesterdays usage was $kwatts kWh at an approximate cost of £$cost Hour: $hour\n";
                        system( "curl -s -u $twitterUser:$twitterPass -d 'status=$kwatts kWh used yesterday at an approximate cost of £$cost' http://twitter.
com/statuses/update.xml");
                }
        } elsif ($line =~ m!(\d+).*0*(\d+)!) {
                # Regular updates received from CC128 approx every 6s, total to create average over 1 minute
                my $sensor = $1;
                my $watts = $2;

                # Only deal with sensor 0 - Whole house sensor now
                if( $sensor == "0" ) {
                        $sampleCount++;
                        $totalWatts += $watts;
                        # Update RRD
                        system( "/usr/local/rrdtool/bin/rrdtool update currentcost.rrd N:$watts:0");
                        # Update pachube once a minute with a minute's worth of averaged data
                        if ( $sampleCount > 10 ) {
                                # Do a little formatting on the output
                                my $averageWatts = sprintf("%.2f",$totalWatts / $sampleCount);
                                #system("curl  --request PUT --header 'X-PachubeApiKey: $pachubeApiKey' -D tmp.txt --data $averageWatts 'http://www.pachube.c
om/api/$pachubeFeed.csv'");
                                system("curl -s --request PUT --header 'X-PachubeApiKey: $pachubeApiKey' --data $averageWatts 'http://www.pachube.com/api/$pa
chubeFeed.csv'");
                                # Reset the counts
                                $totalWatts = 0;
                                $sampleCount = 0;
                        }
                }
        }
}

The script currently runs from a shell and outputs to a log file:


# ./readCurrentCost.pl >currentcost.log 2>&1

This is not a permanent application yet, more a learning exercise to determine what information comes out of the CC128 device while I develop an Arduino based version. Another aspect is tha we ar also identifying how much power we use on a daily basis and when it peaks.

The pachube feed is here. The twitter feed is currently restricted to my main account.