Home Energy Monitor & Control System


2 posts
by moallen » Mon Feb 11, 2013 2:44 pm
This post describes the conversion of my home energy monitor & control system from a Windows computer over to my RPi. It had been running fine for about 4 months, logging and charting data, but I just had to find out if my RPi could handle the same workload.

First my utility room - this part of the project consists of 3 sensors that feed an Arduino FIO and a Xbee RF module.

Image
http://allenconnections.com/rpi-images/home-util/util-room.png

The furnace status sensor is actually a 24VAC relay connected across the furnace's 24VAC gas valve. The relay's N.C. contacts are connected to one of the Arduino's analog inputs. That input is normally low when the furnace's main burner is off. When the gas valve is opened by a normal wall thermostat in my dining room, the burner ignites and that digital line goes high to the Arduino.

The gas water heater is a bit more complicated, since its gas valve is controlled by its internal thermocouple. The only way to sense whether its burner is on or off is by using a heat sensor or light sensor. I tried a heat sensor, but it was just too slow responding for my purposes.

A light sensor also proved to be difficult in terms of getting it close enough to sense light from the burner without being destroyed by the heat. The final solution was recessing a photo-resistor in a bakelight standoff. The photo-resistor is connected in series with a regular resistor forming a resistor network between 0V and +3.3V that is connected to one of the Arduino's analog inputs.

The utility room has a source of fresh air via a 6" vent pipe into the attic. I wanted to monitor its temperature, because it is the culprit of a lot of cold drafty air in the winter. It's tempting to close it off, but it's necessary for code and safety reasons. The air coming out of it is normally only 5 degrees or so above the outside temperature! At some point, I'm going to put an electrically controlled damper in the vent pipe and use the Arduino to open and close it as needed.

Code: Select all
// Send analog pin values via Xbee serial every 5 seconds

int led = 10;
int furnacePin = A0;
int furnaceValue = 0;
int ventPin = A1;
int ventValue = 0;
int waterhtrPin = A2;
int waterhtrValue = 0;

void setup() {
  Serial.begin(57600);
  pinMode(led, OUTPUT);
}

void loop() { 
  digitalWrite(led, HIGH);
  delay(2500);
  furnaceValue = analogRead(furnacePin);
  Serial.println(furnaceValue, DEC);
  ventValue = analogRead(ventPin);
  Serial.println(ventValue, DEC);
  waterhtrValue = analogRead(waterhtrPin);
  Serial.println(waterhtrValue, DEC);
  digitalWrite(led, LOW);
  delay(2500);   
}

Without going into a lot of detail, the above sketch sends 3 string values out to a Xbee RF module, which transmits them to another Xbee now connected to my RPi through a USB-Serial TTL adapter. Each of those string values is a number between 0 and 1023, representing the analog value of the sensors converted to digital by the Arduino FIO.

Image
http://allenconnections.com/rpi-images/home-util/xbee-1.jpg

Next I needed to get my Phidgets interface board working with my RPi. The process involved several steps but, for the most part, went smoothly. I have been using a Phidgets interface and sensors for at least 5 years with Windows. This was my first experience setting it up under Linux. Fortunately, the Phidgets website does a nice job of laying out the procedure, step by step, for installing everything under Linux, as well as its Python library.

Image
http://allenconnections.com/rpi-images/home-util/phidget-1.jpg

I won't go into all the details, but here are the basic steps:

1) Install the libusb-1.0 development libraries (libusb-1.0-0.dev)
2) Install the Phidget libraries (libphidget-2.1.8.20121218)
3) Verify the libraries installed correctly by compiling and running the Phidget C Generic Example 'HelloWorld' (phidget21-c-examples-2.1.8.20121218)
4) Install the Phidgets Python library (PhidgetsPython_2.1.8.20121218)

Then I checked the Python library by making a LED blink with this Python code:

Code: Select all
from time import sleep
from Phidgets.Devices.InterfaceKit import InterfaceKit

interfaceKit = InterfaceKit()
interfaceKit.openPhidget(97505)

while True:
    sleep(1)
    interfaceKit.setOutputState(7, 1)
    sleep(1)
    interfaceKit.setOutputState(7, 0)

OK - that works. Now let's move on and add all of the sensors back in.

It's amazing everything one of these little RPi's can do. I now have all of the basic functions the program I was running on a Windows computer running on my RPi. The main functions are:

1) Wirelessly retrieve furnace status, water heater status and fresh air vent temperature from a remote Arduino/Xbee in the utility room every 5 seconds
2) Retrieve indoor temperature and indoor humidity from a USB connected Phidget Interface Board every 5 seconds
3) Retrieve outdoor temperature (metadata) online from WeatherBug every 5 minutes
4) Upload those 6 data elements to COSM for online charting every 60 seconds
5) Log the 6 data elements to a disk file on the SD card every 5 seconds
6) Perform all the calculations and decisions relative to the above functions

At one time, I was using speech on the Windows computer to speak the time & temperature and other events but had to disable it, because eventually the computer would bog down. I think that may have been due to Windows not releasing all memory after every speech call. I will probably try this later on the RPi to see if Linux handles it better.

I also don't have the RPi program turning my fireplace's gas logs on first thing in the morning and will probably add that nice little function back in later, too.

Here's a link to the COSM charts, which are in test mode, and may not always be live:
https://cosm.com/feeds/97217

And here is my Python code, subject to cleanup and further enhancements, with comments:

Code: Select all
import serial
import datetime
import os
import eeml
import csv
import sys
import urllib
from time import sleep
from Phidgets.Devices.InterfaceKit import InterfaceKit

interfaceKit = InterfaceKit()
interfaceKit.openPhidget(97505)
sleep(1)
ser = serial.Serial('/dev/ttyUSB0', 57600)
ser.flushInput()

## turn LED on
interfaceKit.setOutputState(7, 1)

API_KEY = '2OnsN4Pz6UnaIIby8vUYtfPiK1CSAKxZc2VFaE5KSGp5MD0g'
FEED = 97217
API_URL = '/v2/feeds/{feednum}.xml' .format(feednum = FEED)

timeLoop1 = 0
timeLoop2 = 0
outdoorTemp = 999

while True:
   
    ## get furnace status from remote Arduino-Xbee
    furnace = ser.readline()

    try:
   
        if float(furnace) > 1000:
            furnace = 1
        else:
            furnace = 0

    except ValueError:

        furnace = 0

    ## get vent temperature from remote Arduino-Xbee
    ventTemp = int(ser.readline())
    ventTemp = int(round(((ventTemp * .14275)-61.111)*9/5)+32)

    ## get water heater status from remote Arduino-Xbee
    waterHtr = ser.readline()

    if float(waterHtr) > 200:
        waterHtr = 1
    else:
        waterHtr = 0

    ## get indoor temperature from Phidget
    indoorTemp=int(round(((((interfaceKit.getSensorValue(7))*.2222)-61.111)*9/5)+32))
   
    ## get indoor humidity from Phidget
    humidity=int(round(((interfaceKit.getSensorValue(6))*.1906)-40.2))

    ## get outdoor temperature from WeatherBug every 5 minutes
    ## blmbl (Bloomington HS South)
    ## kbmg (Monroe Co Airport)
    ## blomn (Tri North MS)
    if timeLoop1 == 60:
        wB = urllib.urlopen("http://a4460932693.isapi.wxbug.net/WxDataISAPI/WxDataISAPI.dll?Magic=10991&StationID=blmbl")
        currentWeather = wB.read()
        parse = currentWeather.split('|')
        outdoorTemp = int(parse[3])
        timeLoop1 = 0
    else:
        timeLoop1 = timeLoop1 + 1
   
    ## print data to screen   
    currTime = str(datetime.datetime.now())[:-7]
    print currTime
    print "Furnace Status: ", furnace
    print "Vent Temperature: ", ventTemp
    print "Water Heater Status: ", waterHtr
    print "Indoor Temperature: ", indoorTemp
    print "Indoor Humidity: ", humidity
    if outdoorTemp <> 999:
        print "Outdoor Temperature: ", outdoorTemp
    print ""

    ## upload data to COSM every 60 seconds
    if timeLoop2 == 12:
        pac = eeml.Pachube(API_URL, API_KEY)
        pac.update([eeml.Data('furnace', furnace)])
        pac.update([eeml.Data('ventTemp', ventTemp)])
        pac.update([eeml.Data('waterHtr', waterHtr)])
        pac.update([eeml.Data('indoorTemp', indoorTemp)])
        pac.update([eeml.Data('humidity', humidity)])
        if outdoorTemp <> 999:
            pac.update([eeml.Data('outdoorTemp', outdoorTemp)])
        pac.put()
        timeLoop2 = 0
    else:
        timeLoop2 = timeLoop2 +1

    ## write data to disk file
    try:

        f = open('home-data.csv', 'a')

        f.writelines (currTime)
        f.writelines ("|")
       
        f.writelines (str(furnace))
        f.writelines ("|")

        f.writelines (str(ventTemp))
        f.writelines ("|")

        f.writelines (str(waterHtr))
        f.writelines ("|")
       
        f.writelines (str(indoorTemp))
        f.writelines ("|")
       
        f.writelines (str(humidity))       
        if outdoorTemp <> 999:
            f.writelines("|")
            f.writelines (str(outdoorTemp))       
        f.writelines ("\n")
       
        f.close()

    except:
        print "Unable to Update Log File"
   
    ## check to see if program should be stopped
    brk = interfaceKit.getSensorValue(3)
    if brk > 100:
        break

## turn LED off
interfaceKit.setOutputState(7, 0)

interfaceKit.closePhidget()
ser.close()

http://allenmlab.blogspot.com/
User avatar
Posts: 36
Joined: Fri Dec 28, 2012 6:37 pm
by moallen » Tue Feb 12, 2013 4:35 pm
I won't post it here, because it's part of the Phidget interface connected to my RPi. But if you are interested in how I added remote control of my fireplace's gas logs to my RPi home energy monitor & control system and the Python code, check it out here: http://allenmlab.blogspot.com/2013/02/home-energy-monitor-control-phase-4.html

It was nice to wake up this morning to a warm living room. Now I need to incorporate speech into my program, so my system can tell me it's time to get up in the morning...
http://allenmlab.blogspot.com/
User avatar
Posts: 36
Joined: Fri Dec 28, 2012 6:37 pm