Electricity Usage Logging with CurrentCost EnviR and a Raspberry Pi

Ever since seeing the CurrentCost setup at 44kg (a particularly geeky student house whilst I was at uni) and Paul Mutton’s Jibble on the Matter, and then the subsequent posts about doing roughly the same thing, I decided that my new flat would need to have an electricity monitoring setup of some sort.

There are various energy monitors that you can get that will indeed measure how much electricity you’re using and display it on a screen.  Some even come with a USB cable that lets you download the past data onto a computer to do what you want with.  Some of them have Ethernet interfaces, that let you send the data into the cloud!  There is even an Open Source Energy Monitor (emon) that you can build or buy which can do the job for you – and you can hack it’s firmware as well if you like (it’s Arduino based).

I decided that, given the past success with the device, and my lack of time and money, I’d go with the well proven, thoroughly understood CurrentCost EnviR – including the USB/serial cable that lets you hook it up to a PC (or, my my case, a Raspberry Pi)

Before going into detail about how I set up my monitoring, I need to explain a bit how the power distribution in my flat works, that’s a little non-standard.  My flat only has electricity, and all of the heating is done by night storage heaters.  The way these work is there is a separate Consumer Unit which the storage heaters are attached to, and this consumer unit (CU) is fed by a Radio Teleswitch.  The teleswitch is controlled by data modulated onto the LW output of BBC Radio 4.  The data contains: current date and time, on/off codes.  Each teleswitch has it’s own set of codes to tell it to turn on or turn off.  When it recieves one of it’s own codes, it will act upon it – either by turning on or off, or by waiting until a specified time before turning on or off.

When the teleswitch is enabled, it sends power to the night storage heater CU, and also sends a signal to the electricity meter to say that it should now log off peak usage instead of on peak usage.

 

I wanted to be able to show on my graphs whether we were on day or night rate – as this meant that I could potentially change my behaviour to use more power during off-peak than I would on peak.  With a normal-ish setup, that’s just a matter knowing what time on and off peak hours start, but in my case, I don’t know when off peak will start with the teleswitch – especially if the power company was trying to do some load levelling that day to keep the demand at an even keel over the course of 24 hours.

So what I ended up doing was getting an extra CT clamp and transmitter (although, in hindsight I could have just got an extra clamp as the transmitter that comes with the kit has 3 input channels), and attaching it to the night power line.  It turns out the “mini” transmitter is far more reliable than the stock transmitter!  This means that I can measure how much power is being used up by the night power stuff (which is quite a lot, up to 7kW!).

 

Once I’d got the EnviR paired up with the two transmitters (with the main one on 0, and the night power one one 1) I hooked up the USB cable to my RPi.  It’s got a PL2303 USB to serial converter in the cable – who’s driver is built into the raspbian kernel (it’s a pretty common chipset).  The EnviR has a baudrate of 57600 bps.  If you hook up a serial terminal program (like screen) you can see the EnviR spits out some XML every 5 or 6 seconds, for each sensor that you have configured. It’s all in the manual.

Helpfully, each XML message is terminated by a “\n” newline character.  This makes it super easy to parse.

I decided that, today, I was going to write this in Python using pyserial

#!/usr/bin/env python
import os
import serial
import xml.etree.ElementTree as ET
ser = serial.Serial('/dev/ttyUSB0',57600 )

line = ""
while 1:
        x = ser.read()
        line = line + x
        if (x == "\n"):
                # parse that line!
                tree = ET.fromstring(line)
                line = ""
                type = tree.find('type')
                if type is None or type.text != '1':
                        print "Received non-realtime sensor packet: %s" % line
                        continue
                sensor = int(tree.find('sensor').text)
                print "\t --- Received packet from sensor %d" % sensor
                temp = tree.find('tmpr').text
                update_line = "N:%s:" % temp
                if tree.find('ch1') is not None:
                        ch1 = tree.find('ch1')
                        ch1_watts = int(ch1.find('watts').text)
                        update_line = update_line + "%d:" % ch1_watts
                else:
                        update_line = update_line + "U:"

                if tree.find('ch2') is not None:
                        ch2 = tree.find('ch2')
                        ch2_watts = int(ch2.find('watts').text)
                        update_line = update_line + "%d:" % ch2_watts
                else:
                        update_line = update_line + "U:"

                if tree.find('ch3') is not None:
                        ch3 = tree.find('ch3')
                        ch3_watts = int(ch3.find('watts').text)
                        update_line = update_line + "%d" % ch3_watts
                else:
                        update_line = update_line + "U"
                print "Temperature: %s C" % temp
                print "Ch 1: %dW" % ch1_watts
                print "Ch 2: %dW" % ch1_watts
                print "Ch 3: %dW" % ch1_watts
                print "rrdtool update file.rrd %s  % update_line

So, when I run this program it will print the various values of the sensors as received by the CurrentCost, as it receives them.  Now, the last line you might recognise as a rrdtool update line.  That is where I’m going to be saving my data, very very much line Paul’s rrdtool setup.  Implementing this in Python is quite easy – there’s quite a nice little python rrdtool tutorial here.  I’m using the same RRD file structure as Paul, as it seems fairly sensible.

The one slightly noteworthy tweak that I made was putting the live RRD DB files into a ram disk – and copied to the SD card regularly as backup.  The reason for this was doing lots of writes to the SD card (which are sloowww) on my RPi slows things down quite a lot – stacking up the IO operations.  Only doing this once an hour helps a lot.  I’ve also got a script that runs only on boot that copies the RRD files back into RAM when the RPi boots up.  Also, the graphs are generated straight into RAM – there’s no reason for them to be written to the SD card at all.

The slightly more involved bit now is the graph.

I took cue from the revspace.nl power stats graph (currently down), which I found at the RRDtool examples gallery.  The thing that particularly interested me was the off peak display, and calculation of the average cost of the day.  The Revspace power graph uses times for calculating when off peak times are.  I made a few modifications to it, to make it UK centric.

                "--start","-1$period",
                "-t", "Flat Power Usage",
                "-v", "W",
                "--full-size-mode",
                "DEF:Watt=$rrdfile:power_ch1:AVERAGE",
                "CDEF:weekend=LTIME,604800,%,172800,345600,LIMIT,UN,UNKN,Watt,*,INF,IF",
                "CDEF:night=LTIME,86400,%,19800,81000,LIMIT,UN,INF,UNKN,Watt,*,IF",
                "CDEF:offpeak=weekend,ISINF,night,ISINF,+,INF,*",
                "CDEF:KWatt=Watt,1000,/",
                "AREA:offpeak#27932788:",
                "CDEF:pounds=Watt,offpeak,0.0637,0.1760,IF,*,1000,/,24,*",
                "CDEF:Low=Watt,0,750,LIMIT",
                "CDEF:Mid=Watt,750,1500,LIMIT",
                "CDEF:High=Watt,1500,3000,LIMIT",
                "CDEF:VHigh=Watt,3000,15000,LIMIT",
                "AREA:Low#00ff00:0 - 750",
                "AREA:Mid#ffbf00:750 - 1500",
                "AREA:High#FF9A0D:1500 - 3000",
                "AREA:VHigh#ff0000:> 3kW",
                "GPRINT:KWatt:AVERAGE:Average usage\: %.3lf kW",
                "GPRINT:pounds:AVERAGE:Average cost per day\: %.2lf GBP",

There are some other options not shown here, but they’re mainly just formatting and colours. You can see the RPN CDEF which defines when offpeak (and weekend and night) are defined. And the “pounds”, is the  off peak power, times the off-peak rate (0.0637 GBP), and the on-peak power by the on peak rate (0.1760 GBP).  The actual stuff that is graphed (with AREA) is bars coloured by the value, so you can easily see whether something using not much power (green/orange), or LOTS of power (red).

I generate the graph using a PHP script, which gets called when I’m actually looking at the graph page.  This way, I’m not generating graphs all the time that nobody will see.  All the PHP script does is call rrdtool graph (using the rrdtool PHP plugin).

I made a couple of tweaks to the graph, namely:

                "DEF:TotalWatt=$rrdfile:power_ch1:AVERAGE",
                "DEF:OffPeakWatt=/var/tmp/rrd/currentcost-1.rrd:power_ch1:AVERAGE",
                "CDEF:offpeak=OffPeakWatt,0,GT,INF,0,IF",
                "CDEF:KWatt=TotalWatt,1000,/",
                "AREA:offpeak#27932788:",

For reference, /var/tmp/rrd/currentcost-1.rrd is RRD DB that the Night Power transmitter data goes into.  My logic being (and this might not be ideal…) that when the night power consumer unit is being powered (i.e. when off peak power is on) then it’ll always be consuming a bit of power – so I can use that to detect when off peak power is enabled.  This is done in the graph, with the RPN that says IF OffPeakWatt > 0, then offpeak = infinity, else offpeak = 0.

This seems to work quite well.  However, the flaw is that if somehow, the night power CU wasn’t drawing enough power for the CT clamp to detect, it’d (incorrectly) report that as being on peak.

The other way I could detect this is using the LED on the Radio Teleswitch, which is turned on when it’s in off-peak mode.  I’ve ordered an CurrentCost analogue dev board, which I plan to hook up an LDR to – that will let me detect when the LED is turned on.  That should, in theory, be the most accurate way of determining it. I can then have another RRD DB that keeps track of on/off peak switches, and incorporate that into the graph.

Next, I plan to get a weather station and hook that up, to draw some more graphs!

3 responses to “Electricity Usage Logging with CurrentCost EnviR and a Raspberry Pi”

  1. Ray Ellison

    Hello from Australia,
    Merry Christmas also

    I stumbled upon your Envir page last week and thought your approach to this was quite unique and could be useful to me.

    I have an Envir installed to monitor my electricity usage and solar generation.

    I found a couple of tweaks needed to be made to get the python serial read script going on my system so I thought Id let you know.

    In the below, your print entries all refver to ch1_watts, they need to refer to ch1,2, and 3. The code also needs to handle missing channels at this point as Ch2 and ch3 may not be output and the script breaks under these conditions. In my case I have simply remd the unused lines.
    ————————-><————————-

    I am also keen to learn how you store the RRD database in ramdisk, and copy to the flash hourly. Id like to do this also. but am a relative Rpi newbie so havent figured out how to do it myself.

    Thanks in advance
    Regards
    Ray

  2. Ray Ellison

    Oops, heres the code I needed to tweak…

    print “Temperature: %s C” % temp
    print “Ch 1: %dW” % ch1_watts
    print “Ch 2: %dW” % ch1_watts
    print “Ch 3: %dW” % ch1_watts
    print “rrdtool update file.rrd %s % update_line

    print “Temperature: %s C” % temp
    print “Ch 1: %dW” % ch1_watts
    print “Ch 2: %dW” % ch2_watts
    # Ch3 not used in my case
    # print “Ch 3: %dW” % ch3_watts
    print “rrdtool update file.rrd %s % update_line

  3. norm

    Hi, thanks for the article. Can you post the full code for the rrdtool graph?

Leave a Reply