In this article by Andrew K. Dennis, author of the book Raspberry Pi Home Automation with Arduino Second Edition, you will learn how to build a thermostat device using an Arduino. You will also learn how to use the temperature data to switch relays on and off. Relays are the main components that you can use for interaction between your Arduino and high-voltage electronic devices. The thermostat will also provide a web interface so that you can connect to it and check out the temperature.
(For more resources related to this topic, see here.)
Introducing the thermostat
A thermostat is a control device that is used to manipulate other devices based on a temperature setting. This temperature setting is known as the setpoint. When the temperature changes in relation to the setpoint, a device can be switched on or off.
For example, let’s imagine a system where a simple thermostat is set to switch an electric heater on when the temperature drops below 25 degrees Celsius.
Within our thermostat, we have a temperature-sensing device such as a thermistor that returns a temperature reading every few seconds. When the thermistor reads a temperature below the setpoint (25 degrees Celsius), the thermostat will switch a relay on, completing the circuit between the wall plug and our electric heater and providing it with power. Thus, we can see that a simple electronic thermostat can be used to switch on a variety of devices.
Warren S. Johnson, a college professor in Wisconsin, is credited with inventing the electric room thermostat in the 1880s. Johnson was known throughout his lifetime as a prolific inventor who worked in a variety of fields, including electricity. These electric room thermostats became a common feature in homes across the course of the twentieth century as larger parts of the world were hooked up the electricity grid.
Now, with open hardware electronic tools such as the Arduino available, we can build custom thermostats for a variety of home projects. They can be used to control baseboard heaters, heat lamps, and air conditioner units. They can also be used for the following:
- Fish tank heaters
- Indoor gardens
- Electric heaters
- Fans
Now that we have explored the uses of thermostats, let’s take a look at our project.
Setting up our hardware
In the following examples, we will list the pins to which you need to connect your hardware. However, we recommend that when you purchase any device such as the Ethernet shield, you check whether certain pins are available or not. Due to the sheer range of hardware available, it is not possible to list every potential hardware combination. Therefore, if the pin in the example is not free, you can update the circuit and source code to use a different pin.
When building the example, we also recommend using a breadboard. This will allow you to experiment with building your circuit without having to solder any components.
Our first task will be to set up our thermostat device so that it has Ethernet access.
Adding the Ethernet shield
The Arduino Uno does not contain an Ethernet port. Therefore, you will need a way for your thermostat to be accessible on your home network.
One simple solution is to purchase an Ethernet shield and connect it to your microcontroller.
There are several shields in the market, including the Arduino Ethernet shield (http://arduino.cc/en/Main/ArduinoEthernetShield) and Seeed Ethernet shield (http://www.seeedstudio.com/wiki/Ethernet_Shield_V1.0).
These shields are plugged into the GPIO pins on the Arduino. If you purchase one of these shields, then we would also recommend buying some extra GPIO headers. These are plugged into the existing headers attached to the Ethernet shield. Their purpose is to provide some extra clearance above the Ethernet port on the board so that you can connect other shields in future if you decide to purchase them.
Take a board of your choice and attach it to the Arduino Uno. When you plug the USB cable into your microcontroller and into your computer, the lights on both the Uno and Ethernet shield should light up.
Now our device has a medium to send and receive data over a LAN. Let’s take a look at setting up our thermostat relays.
Relays
A relay is a type of switch controlled by an electromagnet. It allows us to use a small amount of power to control a much larger amount, for example, using a 9V power supply to switch 220V wall power. Relays are rated to work with different voltages and currents.
A relay has three contact points: Normally Open, Common Connection, and Normally Closed. Two of these points will be wired up to our fan. In the context of an Arduino project, the relay will also have a pin for ground, 5V power and a data pin that is used to switch the relay on and off.
A popular choice for a relay is the Pololu Basic SPDT Relay Carrier.
This can be purchased from http://www.pololu.com/category/135/relay-modules.
This relay has featured in some other Packt Publishing books on the Arduino, so it is a good investment.
Once you have the relay, you need to wire it up to the microcontroller. Connect a wire from the relay to digital pin 5 on the Arduino, another wire to the GRD pin, and the final wire to the 5V pin.
This completes the relay setup. In order to control relays though, we need some data to trigger switching them between on and off. Our thermistor device handles the task of collecting this data.
Connecting the thermistor
A thermistor is an electronic component that, when included in a circuit, can be used to measure temperature. The device is a type of resistor that has the property whereby its resistance varies as the temperature changes. It can be found in a variety of devices, including thermostats and electronic thermometers.
There are two categories of thermistors available: Negative Thermistor Coefficient (NTC) and Positive Thermistor Coefficient (PTC). The difference between them is that as the temperature increases, the resistance decreases in the case of an NTC, and on the other hand, it increases in the case of a PTC.
We are going to use a prebuilt digital device with the model number AM2303.
This can be purchased at https://www.adafruit.com/products/393.
This device reads both temperature and humidity. It also comes with a software library that you can use in your Arduino sketches. One of the benefits of this library is that many functions that precompute values, such as temperature in Celsius, are available and thus don’t require you to write a lot of code.
Take your AM203 and connect it to the GRD pin, 5V pin and digital pin 4. The following diagram shows how it should be set up:
You are now ready to move on to creating the software to test for temperature readings.
Setting up our software
We now need to write an application in the Arduino IDE to control our new thermostat device. Our software will contain the following:
- The code responsible for collecting the temperature data
- Methods to switch relays on and off based on this data
- Code to handle accepting incoming HTTP requests so that we can view our thermostat’s current temperature reading and change the setpoint
- A method to send our temperature readings to the Raspberry Pi
The next step is to hook up our Arduino thermostat with the USB port of the device we installed the IDE on.
You may need to temporarily disconnect your relay from the Arduino. This will prevent your thermostat device from drawing too much power from your computer’s USB port, which may result in the port being disabled.
We now need to download the DHT library that interacts with our AM2303.
This can be found on GitHub, at https://github.com/adafruit/DHT-sensor-library.
- Click on the Download ZIP link and unzip the file to a location on your hard drive.
- Next, we need to install the library to make it accessible from our sketch:
- Open the Arduino IDE.
- Navigate to Sketch | Import Library.
- Next, click on Add library.
- Choose the folder on your hard drive.
- You can now use the library.
With the library installed, we can include it in our sketch and access a number of useful functions. Let’s now start creating our software.
Thermostat software
We can start adding some code to the Arduino to control our thermostat. Open a new sketch in the Arduino IDE and perform the following steps:
- Inside the sketch, we are going to start by adding the code to include the libraries we need to use. At the top of the sketch, add the following code:
#include "DHT.h" // Include this if using the AM2302 #include <SPI.h> #include <Ethernet.h>
- Next, we will declare some variables to be used by our application. These will be responsible for defining:
- The pin the AM2303 thermistor is located on
- The relay pin
- The IP address we want our Arduino to use, which should be unique
- The Mac address of the Arduino, which should also be unique
- The name of the room the thermostat is located in
- The variables responsible for Ethernet communication
- The IP address will depend on your own home network. Check out your wireless router to see what range of IP addresses is available. Select an address that isn’t in use and update the IPAddress variable as follows:
#define DHTPIN 4 // The digital pin to read from #define DHTTYPE DHT22 // DHT 22 (AM2302) unsigned char relay = 5; //The relay pins String room = "library"; byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ip(192,168,3,5); DHT dht(DHTPIN, DHTTYPE); EthernetServer server(80); EthernetClient client;
- We can now include the setup() function. This is responsible for initializing some variables with their default values, and setting the pin to which our relay is connected to output mode:
void setup() { Serial.begin(9600); Ethernet.begin(mac, ip); server.begin(); dht.begin(); pinMode(relay, OUTPUT); }
- The next block of code we will add is the loop() function. This contains the main body of our program to be executed. Here, we will assign a value to the setpoint and grab our temperature readings:
void loop() { int setpoint = 25; float h = dht.readHumidity(); float t = dht.readTemperature();
- Following this, we check whether the temperature is above or below the setpoint and switch the relay on or off as needed. Paste this code below the variables you just added:
if(t <setpoint) { digitalWrite(relay,HIGH); } else { digitalWrite(relay,LOW); }
- Next, we need to handle the HTTP requests to the thermostat. We start by collecting all of the incoming data. The following code also goes inside the loop() function:
client = server.available(); if (client) { // an http request ends with a blank line booleancurrentLineIsBlank = true; String result; while (client.connected()) { if (client.available()) { char c = client.read(); result= result + c; }
- With the incoming request stored in the result variable, we can examine the HTTP header to know whether we are requesting an HTML page or a JSON object. You’ll learn more about JavaScript Object Notation (JSON) shortly. If we request an HTML page, this is displayed in the browser. Next, add the following code to your sketch:
if(result.indexOf("text/html") > -1) { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); if (isnan(h) || isnan(t)) { client.println("Failed to read from DHT sensor!"); return; } client.print("<b>Thermostat</b> set to: "); client.print(setpoint); client.print("degrees C <br />Humidity: "); client.print(h); client.print(" %t"); client.print("<br />Temperature: "); client.print(t); client.println(" degrees C "); break; }
The following code handles a request for the data to be returned in JSON format. Our Raspberry Pi will make HTTP requests to the Arduino, and then process the data returned to it. At the bottom of this last block of code is a statement adding a short delay to allow the Arduino to process the request and close the client connection.
- Paste this final section of code in your sketch:
if( result.indexOf("application/json") > -1 ) { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: application/json;charset=utf-8"); client.println("Server: Arduino"); client.println("Connnection: close"); client.println(); client.print("{"thermostat":[{"location":""); client.print(room); client.print(""},"); client.print("{"temperature":""); client.print(t); client.print(""},"); client.print("{"humidity":""); client.print(h); client.print(""},"); client.print("{"setpoint":""); client.print(setpoint); client.print(""}"); client.print("]}"); client.println(); break; } } delay(1); client.stop(); } }
- This completes our program. We can now save it and run the Verify process. Click on the small check mark in a circle located in the top-left corner of the sketch. If you have added all of the code correctly, you should see Binary sketch size: 16,962 bytes (of a 32,256 byte maximum).
Now that our code is verified and saved, we can look at uploading it to the Arduino, attaching the fan, and testing our thermostat.
Testing our thermostat and fan
We have our hardware set up and the code ready. Now we can test the thermostat and see it in action with a device connected to the mains electricity. We will first attach a fan and then run the sketch to switch it on and off.
Attaching the fan
Ensure that your Arduino is powered down and that the fan is not plugged into the wall. Using a wire stripper and cutters, cut one side of the cable that connects the plug to the fan body. Take the end of the cable attached to the plug, and attach it to the NO point on the relay. Use a screwdriver to ensure that it is fastened correctly. Now, take the other portion of the cut cable that is attached to the fan body, and attach this to the COM point. Once again, use a screwdriver to ensure that it is fastened securely to the relay. Your connection should look as follows:
You can now reattach your Arduino to the computer via its USB cable. However, do not plug the fan into the wall yet.
Starting your thermostat application
With the fan connected to our relay, we can upload our sketch and test it:
- From the Arudino IDE, select the upload icon. Once the code has been uploaded, disconnect your Arduino board.
- Next, connect an Ethernet cable to your Arduino. Following this, plug the Arduino into the wall to get mains power.
- Finally, connect the fan to the wall outlet.
- You should hear the clicking sound of the relay as it switches on or off depending on the room temperature. When the relay switch is on (or off), the fan will follow suit.
- Using a separate laptop if you have it, or from your Raspberry Pi, access the IP address you specified in the application via a web browser, for example, http://192.168.3.5/.
- You should see something similar to this:
Thermostat set to: 25degrees C Humidity: 35.70 % Temperature: 14.90 degrees C
You can now stimulate the thermistor using an ice cube and hair dryer, to switch the relay on and off, and the fan will follow suit. If you refresh your connection to the IP address, you should see the change in the temperature output on the screen. You can use the F5 key to do this. Let’s now test the JSON response.
Testing the JSON response
A format useful in transferring data between applications is JavaScript Object Notation (JSON).
You can read more about this on the official JSON website, at http://www.json.org/.
The purpose of us generating data in JSON format is to allow the Raspberry Pi control device we are building to query the thermostat periodically and collect the data being generated. We can verify that we are getting JSON data back from the sketch by making an HTTP request using the application/json header.
Load a web browser such as Google Chrome or FireFox. We are going to make an XML HTTP request directly from the browser to our thermostat.
This type of request is commonly known as an Asynchronous JavaScript and XML (AJAX) request. It can be used to refresh data on a page without having to actually reload it.
In your web browser, locate and open the developer tools.
The following link lists the location and shortcut keys in major browsers:
In the JavaScript console portion of the developer tools, type the following JavaScript code:
var xmlhttp; xmlhttp=new XMLHttpRequest(); xmlhttp.open("POST","192.168.3.5",true); xmlhttp.setRequestHeader("Content-type","application/json"); xmlhttp.onreadystatechange = function() {//Call a function when the state changes. if(xmlhttp.readyState == 4 &&xmlhttp.status == 200) { console.log(xmlhttp); } }; xmlhttp.send()
Press the return key or run option to execute the code.
This will fire an HTTP request, and you should see a JSON object return:
"{"thermostat": [ {"location":"library"}, {"temperature":"14.90"}, {"humidity":"29.90"}, {"setpoint":"25"} ] }"
This confirms that our application can return data to the Raspberry Pi. We have tested our software and hardware and seen that they are working.
Summary
In this article, we built a thermostat device. We looked at thermistors, and we learned how to set up an Ethernet connection. To control our thermostat, we wrote an Arduino sketch, uploaded it to the microcontroller, and then tested it with a fan plugged into the mains electricity.
Resources for Article:
Further resources on this subject:
- The Raspberry Pi and Raspbian? [article]
- Clusters Parallel Computing and Raspberry Pi Brief Background [article]
- The Arduino Mobile Robot [article]