Monitoring Power Usage
Making Electricity Usage Graphs with the Current Cost device
This page shows how I set up a Current Cost device to monitor my home power usage directly from my electricity meter. (Am I the first non-IBM Hursley employee to be doing this, I wonder? :)
You'll need the following things:
- A Current Cost device and clamp meter.
- A serial cable that fits the current cost device.
- A Linux box or virtual machine to log the data, e.g. Ubuntu, Debian, etc.
- Perl.
- RRDtool.
- Apache and PHP if you want to present things nicely.
Physically installing the Current Cost device
If you haven't already done so, follow the instructions that came with your Current Cost device, installing the clamp meter around your electricity meter output. Now turn on the base unit to check that it's correctly receiving data from the clamp meter. As the base unit receives the data wirelessly, you can place it near any computer in your home.
Now you can use the serial cable to link your Current Cost device to your computer. I bought my cable directly from the device manufacturer on eBay and it arrived a couple of days later.
Perl script to read XML from the Current Cost device
Ultimately, I wanted to produce graphs of my electricity usage and display them from a web server. I therefore chose to set everything up inside an Ubuntu Linux virtual machine, which I use for general day-to-day web application testing. As the host machine was running Windows, I forwarded the COM1 port from the host machine to the VM. Unfortunately, the first serial cable I bought was faulty. This proved to be somewhat annoying, as I had never dabbled with serial ports before, and so it took me an hour or so to deduce that the cable was in fact broken rather than any of my code, or the port forwarding to the VM. Fortunately, the manufacturer promptly dispatched a replacement cable, which worked just fine.
My Current Cost device is the older variety, which only speaks at 2400 baud over the serial link (this seems to be the nature of the devices currently being distributed by the electricity companies). The slow speed is not really a problem, as it only spits out a small amount of data every 5 seconds or so. An easy way to test whether it works properly is to fire up HyperTerminal on Windows and connect to the correct COM port at 2400 bits per second. If the cable is working properly(!), you should see stuff like this appearing in the window every five seconds or so:
<msg><date><dsb>00043</dsb><hr>00</hr><min>10</min><sec>43</sec></date> <src><name>CC02</name><id>02538</id><type>1</type></src> <ch1><watts>00484</watts></ch1><ch2><watts>00000</watts></ch2> <ch3><watts>00000</watts></ch3><tmpr>22.2</tmpr></msg>
Note that the above is sent as a single line of text, which makes it easy for any program to read data samples from the device line by line. There is no need to send any data to the device; it just spews this stuff out unprompted.
Use CPAN (or your favourite package manager) to install the Device::SerialPort
Perl module. You will need this in order to set the serial port speed to
2400 bits per second. If you want to try this on Windows, you can use the
very similar Win32::SerialPort
module.
To install the Device::SerialPort
module directly from CPAN,
open a terminal and type perl -MCPAN -e shell
. Then type
install Device::SerialPort
.
Now you can actually write some code to read the data from the device:
#!/usr/bin/perl -w # Reads data from a Current Cost device via serial port. use strict; use Device::SerialPort qw( :PARAM :STAT 0.07 ); my $PORT = "/dev/ttyS0"; my $ob = Device::SerialPort->new($PORT); $ob->baudrate(2400); $ob->write_settings; open(SERIAL, "+>$PORT"); while (my $line = <SERIAL>) { if ($line =~ m!<ch1><watts>0*(\d+)</watts></ch1>.*<tmpr> *([\-\d.]+)</tmpr>!) { my $watts = $1; my $temp = $2; print "$watts, $temp\n"; } }
When you run this script, it will open the first serial port and print out the power and temperature every time it receives a line from the Current Cost device. Leading zeros are removed from the power value.
Update: If you're using the USB interface instead of the serial cable, Jamie Bennett has described the 2 tweaks you need to make to the above script on http://www.linuxuk.org/CurrentCost_Ubuntu. I'd also like to thank Jonathan Leach and his extremely cold server room for letting me know that the XML contains a leading space ahead of the temperature when it drops below 10C!
Creating a Round Robin Database with RRDtool
This was the first time I'd used RRDtool, but I found it to be a rather painless experience and was rather impressed by how easy it makes everything. As the Current Cost device provides me with both the power usage and the temperature, I wanted to set up an RRD with two data sources (DS), and enough Round Robin Archives (RRA) to let me produce accurate graphs over periods ranging from 10 minutes to 10 years.
RRDtool is: "the OpenSource industry standard, high performance data logging and graphing system for time series data".
If your package repository is up to date, installing RRDtool and its prerequisites is easy:
> apt-get install rrdtool
I shall not explain how to use RRDtool here; that's a job for the rrdtool documentation.
However, here is the rrdtool create
command I used to set up my RRD:
#!/bin/sh rrdtool create powertemp.rrd --step 5 \ DS:Power:GAUGE:180:0:U \ DS:Temperature:GAUGE:180:U:U \ RRA:AVERAGE:0.5:1:3200 \ RRA:AVERAGE:0.5:6:3200 \ RRA:AVERAGE:0.5:36:3200 \ RRA:AVERAGE:0.5:144:3200 \ RRA:AVERAGE:0.5:1008:3200 \ RRA:AVERAGE:0.5:4320:3200 \ RRA:AVERAGE:0.5:52560:3200 \ RRA:AVERAGE:0.5:525600:3200 \ RRA:MIN:0.5:1:3200 \ RRA:MIN:0.5:6:3200 \ RRA:MIN:0.5:36:3200 \ RRA:MIN:0.5:144:3200 \ RRA:MIN:0.5:1008:3200 \ RRA:MIN:0.5:4320:3200 \ RRA:MIN:0.5:52560:3200 \ RRA:MIN:0.5:525600:3200 \ RRA:MAX:0.5:1:3200 \ RRA:MAX:0.5:6:3200 \ RRA:MAX:0.5:36:3200 \ RRA:MAX:0.5:144:3200 \ RRA:MAX:0.5:1008:3200 \ RRA:MAX:0.5:4320:3200 \ RRA:MAX:0.5:52560:3200 \ RRA:MAX:0.5:525600:3200
This creates a fixed-size RRD (about 1.3MB), which will be used to store all
of the graph data for the power and temperature over a period of up to ten
years. It assumes data is sampled every 5
seconds and also logs the maximum
and minimum values, which is useful to display in addition to the average, particularly
when it comes to graphing data that spans large time periods. If no data is
added to the RRD for more than 180
seconds, it will assume the value is 'unknown'.
Adding power and temperature data to the RRD with rrdtool update
The rrdtool update
command can be used to add data to the RRD. If you read a
value of 270W
and 21.3C
from the Current Cost device, you can add this to
the RRD like so:
> rrdtool update powertemp.rrd N:270:21.3
Note that this operation is timestamped with the current time (N
means 'now').
Modify your Perl script to run this rrdtool update
command with the $watts
and $temp
values,
or install and use the RRDp::cmd
package to update the RRD.
Create power and temperature graphs from RRDtool
Leave your Perl script running for a few minutes and you should end up with enough data to graph already. I'm going to produce these as PNG images that I can write directly to the default web server.
Let's start by making a simple graph that shows the average power usage over the last ten minutes:
> rrdtool graph /var/www/currentcost/graphs/power-10min.png \ --start end-10m --width 700 --end now --slope-mode \ --no-legend --vertical-label Watts --lower-limit 0 \ --alt-autoscale-max \ DEF:Power=powertemp.rrd:Power:AVERAGE \ LINE3:Power#0000FF:"Average"
Note that the Y axis is labelled with "Watts" and the minimum value for the scale is 0. The line is given a thickness of 3 and will be blue:
Hurrah! :) Incidentally, this crazy graph results from using my washing machine. My next project will involve generating random numbers from my washing machine.
Because RRDtool can only sensibly display average values over larger time periods, we'll try and display the range of the maximum and minimum values on the same graphs. I wanted to show the range as a transparent filled area, with a slightly less transparent border. This command does just that for the previous week (7 days):
> rrdtool graph /var/www/currentcost/graphs/power-week.png \ --start end-7d --width 700 --end now --slope-mode \ --no-legend --vertical-label Watts --lower-limit 0 \ --alt-autoscale-max \ DEF:Power=powertemp.rrd:Power:AVERAGE \ DEF:PowerMin=powertemp.rrd:Power:MIN \ DEF:PowerMax=powertemp.rrd:Power:MAX \ CDEF:PowerRange=PowerMax,PowerMin,- \ LINE1:PowerMin: \ AREA:PowerRange#0000FF11:"Error Range":STACK \ LINE1:PowerMin#0000FF33:"Min" \ LINE1:PowerMax#0000FF33:"Max" \ LINE1:Power#0000FF:"Average"
Note the CDEF, which defines a new value, PowerRange, which is calculated as the difference between the MAX and MIN values stored in the RRD (using Reverse Polish Notation). The first LINE is invisible (has no colour), and then the PowerRange value is STACKed on top of the minimum and filled in with a transparent blue colour (#0000FF11 - note that the 11 is the value of the alpha channel). Then we draw lines to show the MAX and MIN boundaries before finally drawing a solid blue line for the average value.
This ends up looking somewhat like this:
This graph shows that my house is constantly using about 200W of power nearly all the time. This can be attributed to the quad core VM server that I leave running all the time, my network switch, wireless router, freezer, alarm clocks, etc. The 0.5kW plateaux are where I have turned on another computer and a large LCD television at the same time. The very large spikes are from using high-power appliances, such as kettles, toasters and electric grills.
All you have to do now is create an rrdtool graph
command for
each time period you're interested in, whack it all into a shell
script, and set up a crontab to run it every minute.
Example graphs
Here's an example of what it might look like when you're done. Note that on the daily view, you can clearly see my freezer turning on and off every hour
Then you can sit back and be amazed at how much electricity you waste when you leave a computer on to monitor how much electricity you are using :-(
Search this site
Copyright Paul Mutton 2001-2013
http://www.jibble.org/
Feedback welcomed