This Instructable explains how I built WiFi enabled thermostats for my home. The thermostats are programmable with 6 different time periods during the day, although increasing that to any arbitrary number would be fairly trivial. They can be programmed (in the sense of setting times and temperatures) as well as controlled over the internet, and they have a touchscreen LCD display for local control as well. And, I spent (and continue to spend) a fair amount of time trying to get them to look decent; after all, this is something that hangs on my wall, and I and my family will be seeing it every day.

One obvious question is “why would anyone want to do this when there are plenty of WiFi-enabled thermostats for sale commercially?” One possible answer would be to save money. But, while it is true that these might cost less to build than some commercial models, once you factor in your time, this becomes a bad answer! Better answers would be to have fun doing it (I did), or to build a thermostat that you can program to run and interact with other devices in any way desired. I built these as part of a larger home energy management system, and perhaps I'll post another Instructable on that later. And as a bonus: the hub for the thermostats is ready to go as a hub for a complete home automation system!

A second obvious question is what sort of formal qualifications or relevant experience do I have in this area, and the answer is absolutely none – no background with HVAC systems, no background in programming, no background in electronics. So, if you decide to build your own thermostats, you should NOT just blindly copy exactly what I have here and hook it up to your wall. This project requires precise, analytic thinking, and you must understand the type of HVAC system you have, review and modify all code and circuits as appropriate, and make sure you understand what you're doing and the consequences of getting it wrong. Failure to do so could destroy your HVAC system, electrocute your loved ones, or burn down your house. Seriously! I certainly welcome feedback from anyone who does have knowledge in these areas as to how I could make these thermostats better.

And of course, I could not have done this without all of the hard work from the folks who created the various libraries used, the people who took the time to put information out on the web in Instructables, forums, and blogs, and the many people who helped me out with advice and answers to my questions. Special thanks to Mark Pendrith who was especially helpful and gave me the code that forms the foundation of the arduino sketch.

Finally, in the process of modifying files to work with just the thermostats (as opposed to the larger home energy management system) as well as remembering everything I did over time to get this to work, there will undoubtedly be some errors in here. Please let me know if you catch any and I'll try to get them corrected as quickly as possible.

With all of that out of the way, here's what I did:

The system uses a Raspberry Pi as a central hub that serves web pages so I can control the thermostats from anywhere. The hub also handles all of the wireless communication over nRF24L01+ radio modules (I know I said “WiFi,” and the nRF24L01+ radio module isn't technically WiFi, but more on that later), and maintains a MySQL database with the thermostat programming as well as any data logging I do. And finally, the hub runs two servers written in Python – one controls the thermostat (as an intermediary between the web-page and the thermostat) and the other handles data logging. I believe this could probably be done with the thermostats each serving its own simple web-page and sending data directly to the MySQL database. This would eliminate the need for the lighttpd web-server and the two python servers. But, I feel like doing this on the hub does provide the simplicity of a single web-site, and the python servers provide a lot of flexibility. Plus I don't have to update the code on the thermostats whenever I want to make changes to these aspects.

If you really dig into this, you'll probably wonder why I bother with a MySQL database instead of just writing a little data to a text file when necessary. The primary answer is that I need the MySQL database for other parts of my system, but if all I had were the thermostats, it might be fairly easy just to eliminate the database and replace it with text files.

So, the communication flow essentially works as follows.

User Updates on Web-site

A user controls or programs a thermostat on a web-site written in PHP (mostly, a little javascript).

That web-site saves any changes to the MySQL database, and sends an instruction to the python control server.

The python control server interprets those instructions, updates an internal representation of the thermostat, and sends the appropriate instructions to the physical thermostat over the RFX network.

User Updates at Thermostat

A user controls a thermostat using the touchscreen controls.

The thermostat sends the changes to the python control server.

The python control server updates an internal representation of the thermostat and saves any changes to the MySQL database.

Thermostat has data to log or messages to save

The thermostat sends data or a message to log to the python data logging server.

The data logging server either saves that data to the MySQL database or to a log file based on the type of message.

Thermostat Temperature Automatically Changed according to a Set Program

The python control server monitors the program set for the thermostat and determines when the set temperature should change.

The python control server updates an internal representation of the thermostat and sends the new set temperature to the thermostat.

So, with that overview behind us, below are details on how I set this up. The first step lists the supplies and tools I used. The next several steps of the Instructable cover how I set up the hardware and software infrastructure for the hub. Most of these will include instructions by reference – there are plenty of places to get great information on how, for example, to set up a MySQL database on a Raspberry Pi, so I don't try to replicate that. Then, when the infrastructure is in place, I give considerably more detail on how I built the actual thermostats as well as the code I use to control them.

Step 1: Materials and Tools



  • Raspberry Pi Model B, B+, or 2 (with an ethernet port) and a power cord
  • Ethernet cable to connect the Raspberry Pi to your network
  • RFX gateway kit (http://embeddedcoolness.com/home/) to allow the nRF24L01+ radio modules to be used in TCP/IP (i.e., “WiFi”) mode


Power supply:

  • Bridge rectifier (converts ~34vac from thermostat wires to ~34vdc)
  • Buck converter (I used LM2596 – steps ~34vdc down to ~5vdc)
  • Voltage regulator (I used LM1117 - takes ~5vdc down to 3v3 for power input)
  • Switch


  • 1284P microcontroller
  • 40 pin DIP socket for the microcontroller
  • 16Mhz crystal oscillator
  • 22pF ceramic capacitors (2)
  • 10k ohm resistor
  • 0.1uF capacitors (2)
  • 3x2 pin male header (for ISP connector)


  • Relays with a 3V coil (4) - I used JRC-21F
  • PN2222A transistors (4)
  • 300 ohm resistors (4)
  • diodes (4) – I used 1N4004

Temperature sensor

  • ds18b20 digital temperature sensor
  • 4.7k ohm resistor

Touchscreen LCD

  • 3v3 Touchscreen LCD (I used this one)
  • 14 pin female header
  • 2N4403 transistor (as a switch for the LED lights in the touchscreen)
  • 12k ohm resistor (to control the current to the 2N4403 transistor)
  • 100 ohm resistors (3)


  • nRF24L01+ radio module (4x2 pin header configuration; it comes in low power and high power versions – low power should work for most applications, but if your thermostat will be 4 or 5 rooms away from the hub, you may need a high power module)
  • 4x2 pin female header


  • Perf board (I used 90cm x 150cm – I also found that paying a little more for a better quality, more rigid board was worth it to me)
  • 2 Pin Plug-in Screw Terminal (5)
  • Breadboard – for testing circuits/components before soldering
  • Plenty of hook up wire in different colors
  • Solder


  • Wood
  • Plexiglass
  • Screws


  • Wire cutters and strippers
  • Soldering station
  • Multimeter
  • avrisp mkii programmer (or equivalent)
  • CNC router (I used this to construct the case)
  • Screwdrivers and other common tools

Step 2: Setting Up the Communication Hub and Testing

In my setup, the hub serves several purposes. First, all communication via the nRF24L01+ radio modules is routed through the hub. Secondly, the hub hosts a MySQL database where logging and program information can be stored, and it also hosts a website that allows for a simple user interface to program and monitor the thermostat. In my implementation at home, the thermostats are part of a larger home automation/energy management system, and the hub handles reporting and control function for those other parts as well.

I use an RFX network from Embedded Coolness. There are other WiFi alternatives out there, but this is what I used. And, I have found it to be a great product – well worth the cost in my opinion. The RFX software implements the TCP protocol (i.e., WiFi) over nRF24L01+ tranceiver packets, effectively turning nRF24L01+ packet radios into WiFi devices. The Raspberry Pi hub acts as the router and bridge for to the LAN network. A single Raspberry Pi acting as an RFX hub can connect to up to 255 nRF24L01+ equipped Arduino devices as nodes. This design fit well with my application. After a lot of headaches trying to use arduino WiFi shields, I bought this a few years ago, set it up, and it just worked.

Once you get the RFX hub, the Embedded Coolness web-site has instructions on how to set it up, and it comes with some example and test programs. So, get this set up and play with it a little bit to make sure it's working.

I would also strongly recommend installing a terminal emulator such as PuTTy. This allows you to monitor and work on your Raspberry Pi using the keyboard and screen of your laptop or other computer. It's also an easy way to keep track of your system for debugging purposes – the RFX product prints status info out from port 11000 by default on the Raspberry Pi, and this can be easily viewed in a PuTTy window. PuTTy is a great product for Windows (I have not tried it on any other platform) and can be downloaded here for free. Going forward, I will refer to the Raspberry Pi by name and use the term computer to mean a laptop or other computer used to log on to the Raspberry Pi remotely. I'm not suggesting the Raspberry Pi isn't a computer! I know it is – I'm just trying to differentiate between the two.

Here's a great link on how to use PuTTy to log on to your Raspberry Pi. It doesn't tell you how to get the IP address for your Raspberry Pi, but most routers will have a status page accessible through your browser that will show you all connected devices and their local IP addresses. For my router, I just enter the address into my browser and this brings up a status page showing the local IP address for all devices on my home network.

I would also strongly recommend loading Xming on your computer. It's also free and allows you to see graphic displays when logging on to your Raspberry Pi remotely. This is very useful for me since I use the Python IDLE editor, which is a graphic display. Here's a helpful link to installing Xming and configuring it to work with PuTTy.

Step 3: Installing the Web Server (lighttpd), Database (MySQL), and PHP on the Raspberry Pi

As noted before, I created a website to allow me to program, monitor, and control my thermostats. lighttpd is a free web-server that uses relatively few resources, making it well-suited for the Raspberry Pi. But, there are certainly other web servers available that could work. MySQL is a powerful and free database. My system uses it for a number of things, but for the thermostat specifically, the MySQL database stores the user programming of the thermostat (e.g. heat to 68 at 5am on Tuesdays) as well as the current settings of the thermostat (e.g. heat is on, temporary hold at 70 degrees, fan is on) and a history of past settings. Finally, PHP is the language I used to create the web-site that will run on the web-server and allow the user to monitor and control the thermostat.

To install lighttpd, MySQL, and PHP on the Raspberry Pi, follow the instructions here. These instructions include a section on how to get a static IP for your Raspberry Pi. I will note that I did not do this and my router has never changed my IP address, but your results may differ.

Another piece of software you might want to consider, especially if you're not familiar with databases (but even if you are), is the MySQL Workbench. This provides a relatively easy to use interface for MySQL, and it can be installed on a computer and then used to log into the MySQL database on the Raspberry Pi over your home network. You can read about it and download it here. I don't use it in this Instructable, however.

In a later step, after talking about how I built the thermostats, I'll include information on how to install the database tables and web page code on the hub for anyone who hasn't stopped reading by then...

Step 4: Building the Thermostat

Now for the fun part. And remember, I built a thermostat for my particular home system, which consists of a heat pump with a back-up heat source. Your system may be completely different, and even if it is the same, I can't warrant that this thermostat is suitable for use by anyone for any purpose. You should not install a thermostat unless you have first made sure you understand your home HVAC setup, reviewed all code and circuits, and modified them as needed.

That said, the wireless thermostats I have built consist of several main parts. You can download a schematic for this thermostat (as well as all of the code I use and some other information) this GitHub repository. The schematic is in the file Tstat_New_v1.pdf. A description of these parts is as follows:

power supply – My home is wired with 27VAC to the thermostats, and to run the 1284P microcontroller, touchscreen LCD, temp sensor, and relays, I need 3v3 DC. I use a bridge rectifier to convert the AC to DC, and a buck converter to step the DC down to about 5 volts. (NOTE: The LM2595 buck converter has a max input voltage of 40vdc, so this is really pushing it. I have had some problems with some of these.) Finally, I run the output through a voltage regulator to get to 3v3. The reason I use a buck converter before the voltage regulator is that the buck converter is much more efficient than the voltage regulator, so I get less wasted power which means less heat. You might even be able to use the buck converter to go straight to 3v3 and skip the regulator, although I haven't tried it yet, and it's possible that the signal from the buck converter might not be smooth enough to give good performance with the nRF24L01+, which can be sensitive to the smoothness of the power supply. (NOTE: the LM1117 datasheet recommends two caps with the regulator to smooth the signal, and although I seem to do fine without these, I do recommend using them. I intend to add them to the schematic at a later date and include them in my own future builds.)

microcontroller – I use the ATmega 1284P microcontroller in a 40 pin DIP configuration. This chip has plenty of memory and pins to get the job done with some left over should I want to add additional features later. The microcontroller requires several other components to function, which are included in the schematic. A great explanation of how to set this chip up on a breadboard can be found here, and this is what I used to get started. However, one difference is that I did not use the arduino bootloader. Instead, I created a simple 6 pin “plug” that was breadboard friendly and would fit an ISP programmer. I use an avrisp mkii programmer, and it seems to do a great job. I found that using a breadboard to test out all circuits before soldering up boards was extremely helpful.

interface – A TFT LCD with touchscreen is a great way to incorporate a display and controls together without having to add buttons to the circuit. The LCD touchscreen uses the same SPI pins as the ISP, and it can interfere when you're programming the microcontroller using ISP. I found that adding 100 ohm resistors between the LCD MOSI, MISO, and SCK pins and the microcontroller resolved this issue. The TFT LCD has separate MISO, MOSI, and SCK pins for the touchscreen and the display, but these can just be jumped together. I also use a transistor to switch the LED for the display on when the screen is touched. On an earlier version, I just wired the LED directly into the 3v3 power and left the display illuminated all of the time.

temperature sensor – A thermostat has to know what the current room temperature is, right? I use the ds18b20 digital temperature sensor, but there are plenty of others available, including some that measure the relative humidity as well if you're interested in seeing that.

relays – And of course, you need relays to be able to control the HVAC system. I use transistors to switch the relays based on a signal from the micrcontroller, and a flyback diode to protect the microcontroller from voltage spikes when the relay is turned off.

A great reference for understanding how to use transistors as switches is here, and for understanding relay circuits, I recommend this Instructable.

I would strongly suggest building each of these components on a breadboard to make sure they work as expected before you start soldering things together.

So, here's what I did:

  1. First I laid out my board, just trying to figure out the general location of the major components (see photo). Some thoughts about this:
    -> Make sure you leave room for connections, especially for the TFT LCD screen and around the relays. The TFT LCD screen has a lot of connections, many of which cross over one another and several of which need resistors. The relays need a transistor and resistor for the switch as well as a flyback diode.
    -> The TFT LCD screen I use generally has enough clearance that it can go over other components, including the screw terminals and relays. However, it also has a slot for an SD card on the back, and this SD card slot will not fit over the screw terminals or relays. Funny story – during final testing of one thermostat, I started to get some really wonky behavior. The power supply would shut off due to a short, the LCD touchscreen would fail, and relays would switch on and off wildly. After some debugging, I realized that the SD card slot on the bottom of the LCD touchscreen was shorting a number of pins on the 1284P when I pressed down on the touchscreen. A little electrical tape over the exposed SD card slot solved the problem.
    ->Don't forget to plan for the standoffs on the side of the TFT LCD that is not supported by header pins.
    -> The nRF24L01+ radio module has a much larger footprint that the 2x4 header it sits in, so it's a good idea to have the radio module in the header when laying out the board to make sure it doesn't interfere with any other components or extend past the edge of the board.
    -> Don't forget to plan for a hole where the thermostat wires will come in. Many thermostat wires can be fairly rigid, so don't plan on a tiny hole here. The bigger it is, the easier it will be to get all of the wires through AND manipulate the wires into the screw terminals when you are installing the thermostat on the wall.
    -> Think about whether you are likely to want to add anything in the future – maybe an IR sensor to detect when someone is home, a microphone, etc. If you think you might, try to leave some room somewhere on the board. That said, if you cram things in too tightly, soldering everything up will be much harder.
    -> When you're satisfied with the layout, take a picture of it to have as a reference when actually soldering things together.
  2. Next, I drilled holes for the standoffs and checked to make sure they were in fact positioned properly under the touchscreen LCD. (I learned the hard way that if you don't do this early and leave the standoffs connected to the board, there is a tendency to run wires where the standoffs should be positioned.) The standoffs seemed ok, so I left them attached and soldered the DIP for the microcontroller and the 14 pin header for the LCD.
  3. After that, I cut out the center section for the mounting wires to come in from the wall (I used a dremel tool). This creates a lot of dust, so it's better to do it before soldering components onto the board.
  4. Then I cleaned off the dust and soldered on the rest of the infrastructure parts – i.e. the screw terminals, ISP connector pins, and RFX header (see photo). Helpful soldering tip I learned from a friend – poster tack (putty used to hold posters to a wall) is a great way to hold components in place on the board while soldering.
  5. Now it was time to start with the components. I started with the switch, 3v3 regulator, ISP wires, and components for the microprocessor, so I could confirm that I could successfully program the processor before going further.
  6. Using a wall adapter hooked to a buck converter as my power input (see photo - I like to use a different one from the one I ultimately put in the thermostat that is a little larger but has a display showing the voltage setting of the converter), I made sure the switch was switching the power properly and that the regulator output was 3v3. Then, with the power off, I inserted a 1284P chip into the dip (indentation away from the 2x4 RFX header) and tested the ISP and microcontroller with a simple Arduino sketch. NOTE: I found I could insert the chip fairly lightly into the DIP and still get a good connection without pressing it all the way in. This made it much easier to remove the chip after testing without damaging anything. You may also want to use Atmel Studio (free download here) to make sure your fuses are set the way you want them (mine weren't - the EEPROM fuse was not set to prevent the EEPROM memory from being erased when the chip is reprogrammed. Not critical, but setting it makes testing easier.
  7. Once I verified the MCU was working, I wired up the 2x4 header for the nRF24L01+ radio module and made sure the RFX connection was working using the diagnostic6_r3 example program that comes with the RFX network. One advantage of getting this set up early is that you can very easily print diagnostic information to a port on the Raspberry Pi using the RFX connection and view it using PuTTy while debugging hardware and software. As an alternative, you could wire up headers to the TX0 and RX0 pins on the 1284P and use a USB to TTL Serial converter along with the Serial.print() function, but I think just using the RFX is much easier.
  8. The second major section I did was the touchscreen LCD display's 14 pin header (see photo). My thinking on doing this next is that it is one of the trickier parts to solder, and if I messed it up, then I would not have already soldered a lot of components on the board yet that could end up being wasted. I also realized that power and ground wires would be running right past where I planed to put the ds18b20 temperature sensor, so I went ahead and soldered this in as well. In hindsight, I wish I had just soldered in the power and ground connections for this but held off on soldering in the actual temperature sensor until the end as it often got in the way while I was trying to solder other components. I chose to put the temperature sensor in a position at the bottom of the board and to leave it with fairly long leads (the reason it got in the way while soldering other components) so that it would be in a position to get an accurate room temperature reading without heat from the electronics affecting it (placing it in the middle of or above the other components could throw off the temperature reading considerably). This will be more clear in later photos that show the case I built. To test the touchscreen, you could just load the thermostat program as discussed in step 6. Or you could just write a very simple sketch yourself to test it.
  9. After testing the touchscreen to make sure it was working properly, I added the bridge rectifier and one of the relays (see photos). For the flyback diode, I placed it on one side of the relay and bent one of the leads beneath the board under the relay to the other end of the coil.
  10. Finally, after testing this relay circuit, I soldered on the other three relays and related components.

At this point, the thermostat was ready for testing. But, before I could fully test the thermostat, I needed to get the MySQL database set up, and install the web pages and python servers on the Raspberry Pi as well as load the sketch to the MCU.

Step 5: Installing the Database Tables, Python Servers, and Webpages

If you decide to download and install the software for this thermostat, and you're working on the Raspberry Pi remotely using PuTTy, you, like me, may be wondering what is the best way to move files back and forth from your computer to your Raspberry Pi. I have found FileZilla to be a very easy to use program.

Installing the Database

As mentioned at the beginning, the database could probably be easily removed from this project and replaced with a few text files if I had nothing running on this system other than the thermostats I'm describing here. But, I do have other things on the system that need the database, so I've included it in my system...

The GitHub repository includes a file called thermostat_db.sql. This file contains the structure of the MySQL tables needed for the thermostat. To create these tables in a database, you would log into MySQL as 'root' and create a new database using the command “CREATE DATABASE [database_name];” where [database_name] is whatever name you want to use for your database. (example: “CREATE DATABASE tstat_database;”) Then, to import the table structure into the database, exit MySQL, go to the directory where you have saved the file thermostat_db.sql, and enter “mysql -u root -p [database_name] < thermostat_db.sql” and enter the password for the root user when prompted. (example: “mysql -u root -p tstat_database < thermostat_db.sql”)

Now, if you log back into mysql using the “mysql -u root -p” command, you can enter the command “use [database_name];” to select your new database, and then enter “show tables;” to see four tables listed there: thermostats, thermostat_programs, thermostat_status, and users.

The 'thermostats' table will contain one record for each thermostat you have included in your system, and each record will contain three fields:

  • user_id – just choose a user id you want to use for yourself; this will be the same for all thermostats. (example: 1234)
  • node – each thermostat will have it own unique 'node' value; this should be a number between 1 and 255. It is used by the communication software to identify each thermostat. (example: 122)
  • name – each thermostat will have its own name, and this is how the thermostat will be displayed on the webpages. This name can be up to 45 characters. (example: Upstairs Bedroom)

Once you have chosen these values, you need to insert one record into the database for each thermostat with the command “INSERT INTO thermostats VALUES ([user_id], [node], [name]);” (example: “INSERT INTO thermostats VALUES (1234, 122, 'Upstairs Bedroom');”).

Now, just to make sure everything went as expected, enter “SELECT * FROM thermostats;” and you should see the records you just added.

Next, you will need to insert a username and password into the 'users' table. The first thing you will need to do is choose a username (e.g. 'yourname'), a password (e.g. 'yourpassword'), and two salts, which should be random strings of characters, perhaps four to six characters each (e.g. salt1 = '&7tH$#' and salt 2 = '(oJ@'). Then, you will want to insert a record into the users table using the command “INSERT INTO users VALUES ([user_id], md5('[salt1passwordsalt2]'), '[username]');” (example: “INSERT INTO users VALUES(1234, md5('&7tH$#yourpassword(oJ@'), 'yourname');”).

You can then try “SELECT * FROM users;” to see this record in the table. Note that the password has been encoded using the md5() function (which may not be the best option out there at this point).

Finally, insert a record in the thermostat_status table for each thermostat showing that the thermostat is initially off using the command “INSERT INTO thermostat_status VALUES ([user_id], [node], now(), 0, 1, 0, NULL, NULL);” (example: “INSERT INTO thermostat_status VALUES (1234, 122, now(), 0, 1, 0, NULL, NULL);”). The web page needs this initial record for each thermostat in order to work initially.

The other tables will be populated later when the web pages are up and running.

Installing the Python Servers

The GitHub repository should also include three files called TstatMaster.py, TstatLogger.py, and Thermostat.py. Go ahead and copy these to some directory on the Raspberry Pi. If you don't already have Python installed on your Raspberry Pi, then you should install it now (plenty of places on the web that can walk you through that. I'm using Python 2.7.3).

If you are logged onto the Raspberry Pi remotely from another computer using PuTTy, and if you installed Xming on that computer, you can run Xming and then type 'idle' in a PuTTy window to run the idle editor on your Raspberry Pi and see it on your computer. This is a great tool for viewing and editing the Python code. Otherwise, there are various other text editors you can use in Linux such as vim or nano.

Thermostat.py is a module containing code for a Thermostat class. TstatMaster.py controls the thermostats, and TstatLogger.py receives log messages from the thermostats and writes them to a log file. These latter two will require some updates marked at the beginning of each file – those fields are clearly marked.

You will also need to create a /home/pi/Tstat_Data/ directory on your Raspberry Pi for the log files to be written, or else change the TstatMaster.py and TstatLogger.py files so that logFilePrefix references another directory.

To run the servers, go to the directory in which the server files were saved, type “python TstatMaster.py” and “python TstatLogger.py” and make sure they start up properly (no errors). But, there are two problems with this.

  1. If you are doing this through a terminal program such as PuTTy, the programs will stop as soon as you end the session. And, you will not be able to do anything else on the Raspberry Pi while these servers are running. To address this, you will want to run these in screens. To run the programs in a screen, you will need to start a screen first using the command “screen -S ”, for example: “screen -S TstatMaster”. This window will now persist even when you close the PuTTy window. There is plenty of documentation on the screen command available including options to switch between screens, list active screens, and open an existing screen.
  2. Even if you run the servers in screens, if you lose power to your Raspberry Pi and it restarts, your servers will no longer be running. To fix this, you will need to tell the Raspberry Pi to create screens and run these servers any time it reboots.

To do this, you can add the following lines to the rc.local file (more info here):

screen -dm -S TstatLogger python //home/pi/www/LCLogger.py

sleep 2s

screen -dm -S TstatMaster python //home/pi/www/LCMaster.py

sleep 3s

Installing the Web Pages

When you installed lighttpd, it should have set up a www folder for you, probably /var/www/. The GitHub repository should also include some PHP files for the web-page, and you should put these in the following directories under /var/www/ (or other web directory to which lighttpd is looking). Create these subdirectories if needed.

  • /public/ – tstat_index.php, tstat_login.php, tstat_logout.php, tstat_ProgTstat.php, tstat_SetThermostat.php, and tstat_Status.php.
  • /public/includes/ - tstat_MainHeader.php
  • /private/ - tstat_ConnDb.php

The following changes will need to be made to these files:

tstat_ConnDb.php – changes the values for DB_USER, DB_PASSWORD, and DB_NAME to those you are using for your MySQL login and database name.

tstat_login.php – change the values for $salt1 and $salt2 to be the strings you used when saving your Thermostat password in the MySQL database.

tstat_ProgTstat.php – change $service_port to be the number of the port on which the control server is running. Change $CommPwd to be the password you chose to use for the RFX communications. Change the default time zone to your preferred time zone.

tstat_SetTstat.php – change $service_port to be the number of the port on which the control server is running. Change $CommPwd to be the password you chose to use for the RFX communications. Change the default time zone to your preferred time zone.

tstat_Status.php – change $service_port to be the number of the port on which the control server is running. Change $CommPwd to be the password you chose to use for the RFX communications. Change the default time zone to your preferred time zone. Change $thermostats to be a list of the nodes you are using for your thermostats.

Now, test it out – in your browser, type in the IP address for your Raspberry Pi followed by /tstat_index.php (example You should see a login page asking for a username and password. Enter the user name and password you saved in the users table above (no salts around the password, just the password). That should take you to a Welcome page with 4 links on the top: Set Thermostat where you will be able to set your thermostats, Current Status where you can see the current status of each thermostat, Programming where you can program schedules for your thermostats, and Log out (hopefully that one is self-explanatory). Of course, since you haven't programmed the thermostats yet, these pages won't be fully functional, so on to the next step. (NOTE: If you rename the file 'tstat_index.php' to be simply 'index.php' then you should be able to get to it by typing in only IP address of the Raspberry Pi without including the filename in the url.)

Step 6: Programming the Thermostat

I program my thermostats (in the sense of loading the code into the thermostat) using the Arduino IDE and an ISP programmer, so that is what I will discuss here.

The GitHub repository should include a folder called Thermostat_v1 which contains the arduino sketch for the thermostat itself. Copy this directory to some place where you want to keep it. There are also four directories called Utouch2, which contains a library for the touchscreen, OneWire, which is a library for the temperature sensor, and Adafruit_GFX and Adafruit_ILI9341, which are libraries for the LCD display. All four of these should be copied into a folder for your Arduino libraries – on windows machines, that should be \Documents\Arduino\libraries. A special thanks to to all the folks who wrote these libraries (Jim Studt - OneWire; Adafruit - Adafruit_GFX and Adafruit_ILI93414, Henning Karlsen - Utouch, and Mark Pendrith who modified the Utouch library (UTouch2) so that the touchscreen could share SPI pins with the LCD).

Next, before programming the thermostat with the Arduino IDE, the IDE must have the necessary files to recognize the 1284P microcontroller. These can be found here. Note this is for version 1.6.3 of the IDE – there are other branches for earlier versions. This page also contains instructions on installation.

Now, when you open the Arduino IDE and go to Tools/Board you should see “Bobduino and Skinny Bob” as one of the options. Select this, and under Tools/Prorammer select AVR ISP mkII (or whatever programmer you are using).

Now, open the Thermostat sketch, and consider changing the following to suit your tastes:

Functionality – make sure the thermostat works the way YOU want it to work and that it is programmed in a manner that is suitable for your HVAC system!

#define COMM_PIN 4321 – This should be changed to whatever 4 digit PIN you have chosen to use as the RFX communication PIN. It must match the web pages and python servers.

#define TOUCH_TIMEOUT 10000UL – This is the timeout for touchscreen input (in millis) after which unsaved changes will be discarded.

#define TURN_OFF_INTERVAL 60000UL – This is the interval of touchscreen inactivity after which the LED turns off (in millis)

#define LOG_PORT 1700 – port for log server

#define MASTER_PORT 1800 – port for control server

Make sure these ports are the same as the ports on which your python servers are running.

Just below these are some options that determine how much information you want written to log files and whether you want the thermostat to print a status update to serial every 5 seconds (which can be viewed using PuTTy to log onto the port for the thermostat). Generally, DBGCHAT should be set to 0 unless you need it for debugging purposes.

#define WDT 0 - enable (1) or disable (0) the watch dog timer (might be better to disable for debugging, but best to enable it when running)

#define FAHRENHEIT 1 – change to 0 if you want the temperature to be in celsius

There are also a slew of variables starting at line 159 that control when the Auxiliary Heat turns on and off automatically due to the perceived inability of the main heat pump to keep up. These values, as well as the function aux_heat_cntrl(), control the auxiliary heat and deserve special attention.

On the tab Rfx_config.h, you will need to change #define BOARD_ID 110 to the node number of each thermostat before programming that thermostat. For example, if you are programming a thermostat tat you want to be node 127, this should read #define BOARD_ID 127. Below this, ID_STRING is a name the RFX system will use for this node, but it does not need to tie back to any other parts of the system. I found it easiest just to have lines in here for all of my thermostats and then comment out the ones I am not programming at that moment.

On the Touchscreen tab, #define TEMP_MOVE 10 tells the thermostat how many tenths of a degree to change the set temperature each time an arrow is pushed up or down (but if you go with some value other than multiples of 10, you'll probably want to change the set temperature display to show decimal values).

Once all of this is done hook the ISP up to your thermostat (careful of the orientation), choose File/Upload Using Programmer, and program the thermostat.

Now, you can play with it and test it out thoroughly to make sure it behaves as expected. Also, try using the website to change the temperature program and to change the settings to see if that all seems to work as expected.

Creating a temperature program with the web page

Now it's time to set the temperature program on the thermostat, and it's extremely easy. At the top of the page, select the thermostat you want to program and whether this program is for Heating or Cooling. Ignore the Submit and Retrieve buttons for now – you Submit when you're done with the program, and Retrieve pulls in the existing program, but there is no existing program yet.

Then, in the smaller box with the Time and Temp headings, enter the time of day when a period should start and the temperature for that period. For example, if you wanted the thermostat to heat the house up to 70 degrees at 6am and let if cool own to 60 degrees at 9pm, you would enter two rows in this box:

6:00 70

21:00 60

(sorry, I haven't implemented am/pm notation here). Then, select the checkboxes below for the days you want to use this schedule (or use the radio buttons to select multiple days at once such as Mon – Fri), and click on Update. Your schedule should appear in the larger box down below. Of course, you can also just enter each day manually in the lower box if you like.

When the schedule looks the way you want it, click on the Submit button. Now, if you come back to this page and click Retrieve (for the same Thermostat and same Heating or Cooling setting), it should populate the schedule so you can easily see exactly how you have every day programmed.

Step 7: Building a Case for the Thermostat

Next, I wanted to build a half-decent looking case for my thermostats. After all, they hang on my walls, and I see them every day (as does my family). My solution, after a little trial and error, was to rout out a case with no front from a solid piece of wood, and then rout out a front to go over it in clear plexiglass. I used Fusion 360 to design the case and cover, and the GitHub repository includes a Fusion 360 archive file for my case called Tstat_case.f3d. Note that this will only work for you as is if your perf board is the same size as mine and you place your RFX radio module and touchscreen in the exact same places that I did (for reference, my RFX radio module is on the top row through the 4th row, and the 8th and 9th columns in from the right, and my touchscreen pins start in the 8th row down from the top and the second column in from the right). If you use this design, I would suggest using a caliper to make accurate measurements of your board and adjust the design as needed.

To rout it out, I used a Shapeoko 3 CNC machine, and started with a solid piece of poplar (actually two pieces glued together since one piece wasn't quite thick enough. Once it was routed out, it still had a good half inch of base on it that I needed to eliminate, so I ran it over a planer until the backing was fairly thin. Then I rubbed a little linseed oil on the outside and coated it with polyurethane. You can now see what I was talking about earlier in terms of the placement of the temp sensor and the longer leads so it is exposed to the room and can measure the temperature accurately.

I had some trouble with the plexiglass melting when I cut it on the router, even with the router set to the slowest speed it had, and you can see the rough edges I have here. I was told that a mill with an 'O' flute is what I need to cut plexiglass, although I haven't tried it yet (here's an Instructable). A laser cutter would be a great way to go as well.

Of course, the case is a great opportunity to be creative, and the possibilities are endless. I thought a case made out of LEGOs might be kind of cool. You could also probably 3D print something great, or maybe your woodworking skills far surpass mine.

Anyway, have fun with it!

Step 8: Installing the Thermostat

Seriously? You're considering installing some thermostat in your home that you built after reading something on the internet written by somebody who has admitted to having absolutely no formal training or expertise? Well, presumably you took the time to understand your own HVAC system, read through the code, made any changes or updates needed, and tested everything thoroughly. Remember, your system might not even have a heat pump, or the heat pump reversing valve might operate backwards from my system, etc. Unlike mine, your HVAC could be a millivolt system, or operate at mains voltages. DO NOT hook up your own thermostat unless you know how your system works and you have carefully reviewed and modified the code to work for your particular system!

But, if you must, first, turn off the power to your thermostat at the breaker box. Once this is done, screw the case onto the wall through two holes drilled in the back of the case (use a level to make sure your thermostat doesn't hang crooked) with the thermostat wires coming in through the hole in the back of the case. Then, thread the wires through the hole in the perfboard and set the perfboard inside the case. Screw it onto the case to hold it in place. Hook the wires up to the screw terminals – make sure you hook the right wires to the right terminals! Make sure the switch on the thermostat is Off, and then turn the power to the thermostat back on. Now, using a voltmeter to check the level, adjust the variable resistor on the buck converter so you have about 5vdc coming out of the buck converter and into the regulator. Then, cross your fingers and turn the switch on. If you have modified the code to work with your particular system and tested everything thoroughly, you should now have your own wireless thermostat up and running! As a last step, screw the plexiglass front onto the case to protect the thermostat.

Step 9: Backing Up Your System

I have been running my Raspberry Pi for several years with no problems, but I've heard horror stories about SD cards becoming corrupted and people losing a lot of data/work. So, I like to back my system up in two ways.

  • I periodically shut down the Raspberry Pi and make a complete copy of the SD card using Win32 DiskImager (http://www.raspberry-projects.com/pi/pi-operating-systems/win32diskimager).
  • When I'm working on updates to individual programs, I will regularly save copies of the program to another computer using FileZilla.

This way, if the SD card ever does become corrupted, hopefully I won't lose too much...

Step 10: Make It Better

This project grew over time in bits and pieces (and the thermostat is just one piece of a larger project). And at the same time it was growing, I was trying to learn about all of this from scratch. I'm sure it shows in the code as well as the overall system structure and how things work together. If you do make a version of this, make it better! And please share those improvements with others (and me).

In addition to just cleaning up the code, there are an endless number of possibilities for real changes to improve on it or add new functionality. Just a few that occur to me off the top of my head are:

  • security – I'm sure the security I have on this is pretty weak. And even though my home thermostat is unlikely to be the target of sustained hacking attempts, it would be worth improving it. I may try to do this at some point, but if someone out there has any good ideas, please let me know.
  • size – I have been working on reducing the size to improve the appearance of the thermostat (my initial thermostats used arduinos and relay shields, and they were way too big). This one is much better, but still a lot of wasted space there. I'm starting to learn how to design PCBs in KiCad, which should help, but also coming up with a better way to connect the thermostat to the wires in the wall could save a lot space (just look at that big hole sitting in the middle of the board...).
  • make it smart – Maybe add an IR sensor to detect when people are in the room and adjust the temperature based on that. Or have your phone send it's position back to the Raspberry Pi so it can automatically adjust the temperature when you're on your way home.
  • make it look better – I think my case isn't bad, but it's not going to win any awards! Maybe you can come up with a really nice design for a case, or one that doesn't require access to any expensive tools to create.
  • build an app for that – The web pages look terrible on a smart phone (but it does work). A phone app that made it easy to adjust the thermostats and see the current status would be really neat.
  • improve the web pages – As I wrote that last sentence, it occurred to me that the web pages look pretty plain on any computer. Make them look much better!
  • use your imagination – These are just some ideas, but there are no doubt countless improvements/enhancements to be done.

But most importantly, have fun and be careful!

About This Instructable




More by asheville makers:Web-Enabled Home Thermostat (and Home Automation Hub) How to Make Your Brother Printer Accept a Toner Cartridge 
Add instructable to: