April 29, 2013

Thermostat Software


EDIT: I don't profess to be a programmer, even though I can make my way through a few different languages. The code I present here works fine, but it's not very pretty or efficient. I think it's still useful from an educational standpoint and has a few ideas in there that are worth looking at and it's easy to get up and running. But I will soon be ditching this software in favor for some written by Wyatt Winters for his Rubustat (though I'll try to find a way to re-implement the checking of outdoor temperature to determine heating/cooling).


In this post I explained that I tasked my Raspberry Pi with controlling the furnace and air conditioner in my house. Here I describe the software that went into it.

The requirements I wanted were simple enough:
  1. Behave similarly to a commercial thermostat
  2. Schedule temperature set points
  3. Automatic switching between heating and cooling based on outdoor temperature

To satisfy requirement 1, the HVAC control algorithms behave very similar to an actual thermostat: a bang-bang controller with hysteresis. The bang-bang bit means that the HVAC is either full-on or full-off, no percent power or anything like that allowed. The hysteresis prevents the system from cycling on/off very frequently by requiring that the temperature drop below/rise above the set point by a certain amount before a new action is taken. A typical hysteresis is 0.5 degrees, but I have it set as a variable so I can change it later on if I want to tune the performance. I have also found it beneficial to define separate active and inactive hystereses to reduce overshoot. (For the hardware connections to the Raspberry Pi, look here.)

For requirement 2 I am currently scheduling the set temperature using the /etc/crontab file on the Raspberry Pi to write the set point to a file (i.e. "echo 72 > set_temp") which is read when the thermostat program is called. Using cron is fairly straight forward and there's plenty of examples of how to use cron available on the internet.

Requirement 3 was fun to fulfill. Rather than having a second temperature sensor outdoors, I decided to query the internet. The internet knows everything. Knowing the outdoor temperature the Raspberry Pi can decide whether to turn on the air conditioner if it's hot outside or make me open a window if it's cool out (with similar behavior for the reverse, of course). This will be especially helpful for the spring and fall months where the outdoor temperature is close to the set point for the indoor temperature, eliminating the need to flip a heat/cool switch back and forth.

Combining all this together into Python I came out with the following code:
#! /usr/bin/python

import sys
import subprocess
import os

indoor_temp = subprocess.check_output("get_indoor_temp.sh")
outdoor_temp = subprocess.check_output("get_outdoor_temp.sh")

file = open("set_temp", "r")
set_temp = float(file.readline())

hvac_state = int(subprocess.check_output("get_hvac_state.sh")

active_hysteresis = 0.0
inactive_hysteresis = 0.5
outdoor_temp_buffer = 5

# heater mode
if outdoor_temp < set_temp - out_temp_buffer:
    if hvac_state == 0
        if indoor_temp < set_temp - inactive_hysteresis:
            hvac_state = 1
    elif hvac_state == 1:
        if indoor_temp > set_temp + active_hysteresis:
    elif hvac_state == -1: # it's cold out, why is the AC running?
# ac mode
elif outdoor_temp > set_temp + outdoor_temp_buffer:
    if hvac_state == 0:
        if indoor_temp > set_temp + inactive_hysteresis:
            hvac_state = -1
    elif hvac_state == -1
        if indoor_temp < set_temp - active_hysteresis:
            hvac_state = 0
    elif hvac_state == 1 # it's hot out, why is the heater on?
else # it's nice out, open a window
The get_indoor_temp.sh program will be dependent on whatever temperature sensor you have hooked up to your Rasberry Pi. Currently I have a BMP085 sensor connected to an Arduino connected to my wifi network with an RN-XV wireless module. The wifi has not been a stalwart of stability so far and has resulted in some cold mornings and hot afternoons when connection was lost for extended periods of time. I will be hard wiring some DS18B20 into various rooms in the coming weeks to rectify this. get_outdoor_temp.sh uses a program called curl to download an RSS feed from AccuWeather.com which then gets parsed to find the current outdoor temperature. There may be a simpler way to do this, but this works well for me (at least until AccuWeather changes their RSS format...):
#! /bin/bash

METRIC=0 # 0 for F, 1 for C
ZIP=(your zip here)

curl -s -m 20 http://rss.accuweather.com/rss/liveweather_rss.asp\?metric\=${METRIC}\&locCode\=${ZIP} | grep -i -m1 'currently' | grep -o '\-\?[0-9]\+'
The get_hvac_state.sh program checks the current state of the gpio pins connected to the HVAC to determine if the heater, AC, or neither are active:
#! /bin/bash

HEAT=$(cat /sys/class/gpio/gpio23/value)
AC=$(cat /sys/class/gpio/gpio24/value)
FAN=$(cat /sys/class/gpio/gpio25/value)

if [ $HEAT == 0 -a $AC == 0 -a $FAN == 0 ]; then
    echo 0 # idle
elif [ $HEAT == 1 -a $AC == 0 ]; then
    echo 1 # heater acive
elif [ $HEAT == 0 -a $AC == 1 ]; then
    echo -1 # AC active
    echo 2 # something is wrong...
hvac_cool.sh, hvac_heat.sh, and hvac_idle.sh are simple scripts that write value(s) to the appropriate gpio(s). For example, hvac_idle.sh would be something like:
#! /bin/bash

echo 0 > /sys/class/gpio/gpio23/value # heater
echo 0 > /sys/class/gpio/gpio24/value # AC
echo 0 > /sys/class/gpio/gpio25/value # fan


  1. Keeping the thermostat on the right settings will surely help make the temperature more comfortable. Not to mention maximize the use of your HVAC system, so you don't waste energy and get added utility bills. So having a program that can help monitor and quickly adjust it is really helpful. Thank you for sharing this with us!

    Shelley Coday @ C & C

  2. Why did you remove the original thermostat posting (http://makeatronics.blogspot.com/2013/04/thermostat-graphs.html)?

    1. The way I was plotting them relied on constantly appending data to a Google spreadsheet. After a few months the data got big enough that there were serious performance issues (long page load times, etc).

      I started looking at other, more standard ways of collecting and viewing data, but got pulled in different directions and haven't gotten back to it yet.

  3. Hello,
    A thermostat may switch on and off at temperatures either side of the setpoint. This prevents equipment damage from frequent switching.Trane Air Conditioning Repair

  4. Thanks.. your blog is really informative.. If u r looking for a Field Service Management in India Field Power is the best choice for you..

  5. Great article with excellent idea!Thank you for such a valuable article. I really appreciate for this great information.. www.acs-advancedcooling.com

  6. That article would be helpful. Thanks for sharing.

    Heating and Cooling Etobicoke

  7. Thanks for sharing your code with us. It helped me with the program.

    Heating and Cooling Woodbridge

  8. This is of course the next level of Internet censorship, but that is not my point here. field service software