Monitoring the household energy usage with a Raspberry Pi, Current Cost ENVI (Model:CC128) Home Energy Monitor, LedBorg from PiBorg and controlled with Python.
The Harware
- Raspberry Pi
- Current Cost ENVI (Model:CC128) Home Energy Monitor
- Current Cost (USB) Data Cable
- LedBorg from PiBorg
Connecting the CC128 to the Pi – The Data Cable used to connect the CC128 to the Pi uses the Prolific PL2303 chip to connect a serial device (the CC128) via USB. The RJ45 connector goes into the back of the CC128 and the USB connector to the Pi. I had to use a short USB extender cable as the connector on the Data Cable was too large to fit with another USB device connected but using a powered USB hub would also have got round this small issue.
Establishing serial connection – The drivers for the Prolific PL2303 chip are part of the standard Raspbian “wheezy” distribution (I’m using 2012-12-16-wheezy-raspbian release) so the device was ready to use. To communicate with a serial device using Python first we need to install a serial library. This is easily done with a single command from the terminal:
sudo apt-get install python-serial
Now we can set up a serial connection and read data using a few lines of Python:
import serial cc128 = serial.Serial("/dev/ttyUSB0", 57600, timeout=6) cc128xml = cc128.readlines(6) print cc128xml
The first line tells Python that we want the functions of the serial library to be available.
Line two will set up cc128
as an active connection to the device which maps to /dev/ttyUSB0
(this is the device name given to the USB serial device on my Pi) with a Baud rate of 57600 and a timeout of 6 seconds.
The third line performs the function readlines
and puts the data in cc128xml
.
Finally we print the data that is returned which looks like:
CC128-v0.120086120.3000077100341
Parse the data – The data returned is as an XML string so we can use simple text searching to get the information we are interested in. The CC128 will return data roughly every 7 seconds and includes the current temperature and more importantly the current energy usage in watts. To find the required data we can search the returned text string for the relevant tags and select the data between them. Here I am finding the temperature:
tmprstart=cc128xml[0].find("")+len(" ") tmprend=cc128xml[0].find(" ",tmprstart) tmpr=float(cc128xml[0][tmprstart:tmprend])
The same method is used to get the power usage (watts) data from the returned string but as the device supports more than one channel I am making sure I find the ‘ch1’ tags first.
Now we have this data we can perform some range checking on the current power usage figure and decide to display a different colour to indicate low (green), normal (yellow) or high (red) usage.
if watts>2000: colour="100" # Red else: colour="110" # Yellow if watts<500: colour="010" # Green
I have chosen limits of greater than 2000 Watts as high (red), below 500 Watts as low (green) and anything between as normal (yellow) but his could be extended with a greater range of colours or to give an indication of temperature if desired.
Making it light up - The final part is to make the RGB LED on the LedBorg board show the required colour. The drivers available from the PiBorg website make the board appear as a device that you can open and write to. Setting a specific colour is done by turning on the relevant elements of the RGB LED. There are individual elements for Red, Green and Blue and one digit is used to control each. It is possible to turn each element either off (0), on at 50% (1) or fully on (2). For this project I use the string '100' to set red, '110' to set both the red and green components on to give yellow and '010' for green. There are further examples on the PiBorg website.
Once we have decided the colour string to use we can open the LedBorg device, write the value and close it:
LedBorg = open('/dev/ledborg', 'w') # Open LedBorg for writing LedBorg.write(colour) # Write colour to the LedBorg LedBorg.close() # Close the LedBorg
Making it all work - To develop the Python code I used the Raspberry Pi WebIDE from Adafruit. It is currently an alpha release but is usable and has a great Schedule Manager that allows you to have your code run automatically at a set interval. For this application I have set the interval to 5 minutes and it appears to work very well.
The complete code - read-cc128-serial.py
import serial cc128 = serial.Serial("/dev/ttyUSB0", 57600, timeout=6) cc128xml = cc128.readlines(6) try: # Find the temperature tmprstart=cc128xml[0].find("")+len(" ") tmprend=cc128xml[0].find(" ",tmprstart) tmpr=float(cc128xml[0][tmprstart:tmprend]) # Find ch1 ch1start=cc128xml[0].find("")+len(" ") ch1end=cc128xml[0].find(" ",ch1start) ch1=cc128xml[0][ch1start:ch1end] # Find the power in watts wattsstart=ch1.find("")+len(" ") wattsend=ch1.find(" ",wattsstart) watts=int(ch1[wattsstart:wattsend]) print "Temperature " + str(tmpr) + "C, Power " + str(watts) + "watts" except: print cc128xml #colour="000" # Off/Black else: if watts>2000: colour="100" # Red else: colour="110" # Yellow if watts<500: colour="010" # Green LedBorg = open('/dev/ledborg', 'w') # Open LedBorg for writing LedBorg.write(colour) # Write colour to the LedBorg LedBorg.close() # Close the LedBorg
Hello Steve, I found very interesting the application of ENVI energy monitor on the small Raspberry PI, thanks to your application.
Needless to say, I made it myself, since I have several monitors Envi around in my home.
However, not being an expert in the development of code, I would like to undergo a couple of questions about your work in the hope of solving the problem.
1) In my case, having several sensors in the home (such IAMs) your script performs poorly because it does not select the sensor. In practice it does not distinguish which sensor is reading the “ch1”. Analyzing the outuput of my CC128, can be read several times the value “ch1″, but matched not only to ” 0″, but also to 3, 4, …
2) How can I run from PI computer , the script that you have created on their own without support from other PC or monitor? In practice I would like monitoring all the time all energy used in my home on the RGB LED Ledborg. Maybe with 1 minute interval.
Many thanks and congratulations.
Pasquale from Portogruaro (Venice – Italy)
Hi Pasquale, and thanks for the feedback and here are a few ideas on your comments.
1) I have seen the IAM devices but do not have any to test with. They should appear as individual readings in the data returned from the Envi serial comms. The code I posted will not distinguish between the main ‘Whole House’ reading or any of the individual devices as it is not very sophisticated. To achieve what you are describing it may be better to use an XML Parser (there are a number of libraries available for Python).
2) There are several ways of getting a program to run on the Raspberry Pi at regular intervals. One way would be to set the Python script to run when the Pi boots up and wrap the code in a loop with a time delay. Alternatively you can schedule programs to run at set intervals.
Good luck and if you need any further pointer let me know.
Steve
Hello Steve, as I said, I have no experience with Python. But reading the downloading of data from the device CC128, I do not think it needs major changes to the code that you wrote. Using the development environment Adafruit, I did some testing to select the Sensor 0 using the same function “readlines”. But at the moment in the register cc128xml there seems to be only a string of only one sensor randomly captured, namely that in the string captured at the time of execution of the program.
I ask you: the argument in the function readlines(6) What exactly does it do? I do not understand if it reads six strings from the serial port and then stops or something else? I could send you a piece of captured file with a terminal from the serial port on my Envi cc128 to help you understand better.
Pasquale
Hi Pasquale, the Current Cost meter sends out live XML data every six seconds. As you have additional sensors attached you will need to check the tag for a value of zero to get only the ‘whole house’ reading. To further confuse things the monitor will also send history data every 2 hours which may confuse the above code.
The argument in the function ‘readlines(6)’ does not do anything useful and I was trying to set the timeout to 6 seconds. This is the wrong place to set this as it needs to be set in the second line where the serial device is configured. The readlines will wait for a timeout and return all lines that have been read. With the code above only the first line of data is read. This is OK for reading back the current usage but if we wanted to look at the historical readings we would miss data. There is a function the read the next line of data only and I will look at using this instead.
Python has a library available that allows you to parse an XML string and I think this should be used with some error checking to do what you are trying to achieve. I will rework this example.
Steve
Do we have to use the USB cable, or can you simply wire a cat5 and RJ45 terminated cable to the RPi GPIO serial interface?
Hello Simon, at the moment I was using a USB cable between Current Cost Envi and Raspberry PI. I do not think you can do that also for driver setup, but sorry: I am not sure.
Hi Simon, I have not tried connecting the CC128 directly to the RPi GPIO but I think it should be possible.
There are a number of sources that give you the connections of the CC128 RJ45 connection and many mention that the device runs at 3V. This should be OK but you should check what the actual voltage of your device is.
The important connections to the CC128 RJ45 are (ref: CC128 RJ45):
3 = +V Regulated
4 = GND
7 = Unit RX
8 = Unit TX
You should only need to connect the GND (pin 4) and Unit Tx (pin 8) to the RPi to receive the data stream.
If you measure pin 3 releative to pin 4 you should see the voltage the processor in the CC128 is running at (hopefully 3V). If this is >3.3V (eg 5V) then do not connect the outputs directly to the RPi!!!
On the GPIO of the PRi the connections you will need are (ref: General Purpose Input/Output (GPIO)):
P1-06 = GND
P1-08 = UART0_TXD (GPIO 14)
P1-10 = UART0_RXD (GPIO 15)
Receive the data stream we only need to connect the RXD (P1-10) and GND (P1-06).
This will give the required connections:
RJ45-pin4 (GND) -> P1-06 (GND)
RJ45-pin8 (Unit Tx) -> P1-010 (UART0_RXD) [It may be a good idea to put a 2K2 resistor in series to provide a little protection for the PRi]
You will then need to modify the program to use the device
/dev/ttyAMA0
(ref: Connection to a microcontroller or other peripheral). You may need to take a look at this link as you can usually access the console through UART0 and you may have to disable this. There are details at the above ref.Hope this helps and if you try it let us know how it goes.
Hi,
I’m looking at utilising something like this as a power monitor for a motor home, is it possible to make this work to monitor current being drawn through the batteries and display info relating to how much juice is left in the batteries??
Hi Richard, the Current Cost home energy monitor used for this project uses a current clamp for monitoring an AC supply and will not work with the DC supply from batteries. To monitor a DC voltage and current draw you would require a different measurement circuit which could then be interfaced with a controller device like the Raspberry Pi or an Arduino to give you information you want displayed. This sounds like a fun project but would require a little research and DIY electronics to complete.