(For more resources related to this topic, see here.)
Building a thermometer
A thermometer is a device used for recording temperatures and changes in temperatures.
The origins of the thermometer go back several centuries, and the device has evolved over the years. Traditional thermometers are usually glass devices that measure these changes via a substance such as mercury, which rises in the glass tube and indicates a number in Fahrenheit or Celsius.
The introduction of microelectronics has allowed us to build our own digital thermometers. This can be useful for checking the temperature in parts of your house such as the garage or monitoring the temperature in rooms where it can affect the contents, for example, a wine cellar.
Our thermometer will return its readings to the Raspberry Pi and display them in the terminal window.
Lets start by setting up the hardware for our thermometer.
Setting up our hardware
There are several components that you will need to use in this article. You can solder the items to your shield if you wish or use the breadboard if you plan to use the same components for the projects in the articles that follow.
Alternatively, you may have decided to purchase an all-in-one unit that combines some of the following components into a single electronic unit.
We will make the assumption that you have purchased separate electronic components and will discuss the process of setting these up.
We recommend that you switch Raspberry Pi off while connecting the components, especially if you plan on soldering any of the items.
If your device is switched on and you accidently spill hot solder onto an unintended area of the circuit board, this can short your device, damaging it. Soldering while switched off allows you to clean up any mistakes using the de-soldering tool.
An introduction to resistors
Let’s quickly take a look at resistors and what exactly these are.
A resistor is an electronic component with two connection points (known as terminals) that can be used to reduce the amount of electrical energy passing through a point in a circuit. This reduction in energy is known as resistance.
Resistance is measured in Ohms (O). You can read more about how this is calculated at the Wikipedia link http://en.wikipedia.org/wiki/Ohm’s_law. You will find resistors are usually classified into two groups, fixed resistors and variable resistors.
The typical types of fixed resistor you will encounter are made of carbon film with the resistance property marked in colored bands, giving you the value in Ohms.
Components falling into the variable resistance group are those with resistance properties that change when some other ambient property in their environment changes.
Let’s now examine the two types of resistors we will be using in our circuit — a thermistor and a 10K Ohm resistor.
Thermistor
A thermistor is an electronic component which, 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, these being 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 a NTC, or increases in the case of a PTC.
There are two numerical properties that we are interested in with regards to using this device in our project. These are the resistance of the thermistor at room temperature (25 degrees Celsius) and the beta coefficient of the thermistor. The coefficient can be thought of as the amount the resistance changes by as the ambient temperature around the thermistor changes. When you purchase a thermistor, you should have been provided with a datasheet that lists these two values. If you are unsure of the resistance of your thermistor, you can always check it by hooking it up to a voltage detector and taking a reading at room temperature. For example, if you bought a 10K thermistor, you should expect a reading of around 10K Ohms. For this project, we recommend purchasing a 10K thermistor.
10K Ohm resistor
A 10K Ohm resistor, unlike a thermistor, is designed to have a constant resistance regardless of temperature change. This type of device falls into the fixed resistor category. You can tell the value of a resistor by the colored bands located on its body. When you purchase resistors, you may find they come with a color-coding guide, otherwise you can check the chart on Wikipedia (http://en.wikipedia.org/wiki/Electronic_color_code#Resistor_color_coding) in order to ascertain what the value is.
As part of the circuit we are building, you will need the 10K resistor in order to convert the changing resistance into a voltage that the analog pin on your Raspberry Pi to Arduino can understand.
Wires
For this project, you will require three wires. One will attach to the 5V pin on your shield, one to the ground, and finally, one to the analog 0 pin.
In the wiring guide, we will be using red, black, and yellow wires. The red will connect to 5V pin, the black to ground, and the yellow to the analog 0 pin.
Breadboard
Finally, in order to connect our component, we will use the breadboard as we did when connecting up the LED.
Connecting our components
Setting up our components for the thermometer is a fairly easy task. Once again, at this point, there is no need to attempt any soldering if you plan on re-using the components.
Follow these steps in order to connect up everything in the correct layout.
-
Take the red wire and connect it from the 5V pin on the shield to the connect point on the bus strip corresponding to the supply voltage.
There are often two bus strips on a breadboard. These can be found on either of the long sides of the board and often have a blue or red strip indicating supply voltage and ground.
-
Next take the black wire and connect it from the ground pin to the ground on the breadboard.
-
We are now going to hook up the resistor. Connect one pin of your 10K resistor to the supply voltage strip that your red wire is connected to and take the other end and connect it to a terminal strip.
Terminal strips are the name given to the area located in the middle of the breadboard where you connect your electronic components.
-
Now that the resistor is in place, our next task will be to connect the thermistor.
-
Insert one leg/wire of the thermistor into the ground on the bus strip, and place the second leg into the same row as you placed the resistor.
-
The thermistor and resistor are daisy-chained together with the supply voltage. This leaves us now with the final task, which is connecting up the analog pin to our daisy chain.
-
Finally connect one end of your yellow wire from the analog 0 (A0) on your shield to the terminal strip you selected for the preceding components.
Sanity check
The setup of your circuit is now complete. However, before switching on your Raspberry Pi check that you have connected up everything correctly. You can compare your setup to the following diagram:
Our thermometer circuit is now complete, and you can now boot up your Raspberry Pi.
Of course, without any software to return readings to the screen, the circuit is little more than a combination of electronic components!
So let’s get started on the software portion of our project.
Software for our thermometer
Now that we have the hardware for our thermometer, we will need to write some code that is capable of converting the values returned from the thermistor into a readable temperature in Celsius and Fahrenheit.
First up, we are going to look at a new code editing application. This IDE allows you to develop code in the Raspberry Pi X Window System environment and compile the code via a Makefile. We will start by looking at the Geany IDE.
Geany IDE
Geany is a lightweight Linux integrated development environment. It can be installed onto Raspbian and then used for writing code in the Arduino/C++ programming language. An added benefit of using this IDE is that we can set up a custom Makefile with the commands we have been using to compile arduPi-based projects.
By combining the Makefile and Geany, we have an IDE that mimics the functionality we would use in the Arduino IDE, but with the added benefit we can save files without renaming them and compile our applications with one click.
Installing the IDE
We are going to use the apt-get tool to install Geany on to your Raspberry Pi.
-
Start off with loading up your Terminal window. From the prompt, run the following command:
sudo apt-get install geany
-
You’ll get the prompt alerting you to the fact that Geany will take up a certain amount of disk space. You can accept the prompt by selecting Y.
-
Once complete, you will now see Geany located under the Programming menu option.
-
Select the Geany icon from the previous menu to load the application.
-
Once loaded, you will be presented with a code-editing interface.
-
Along the top of the screen, you can find a standard toolbar. This includes the File menu where you can open and save files you are working on, and menus for Edit, Search, View, Document, Project, Build, Tools, and Help.
-
The left-hand side of the screen contains a window that has a number of features including allowing you to jump to a function when you are editing your code.
-
The bottom panel on the screen contains information about your application when you compile it. This is useful when debugging your code, as error messages will be displayed here.
Geany has an extensive number of features. You can find a comprehensive guide to the IDE at the Geany website http://www.geany.org/.
For our application development at this stage, we are only interested in creating a new file, opening a file, saving a file, and compiling a file.
The options we need are located under the File menu item and the Build menu item. Feel free though to explore the IDE and get comfortable with it.
In order to use the make option for compiling our application under the Build menu, we need to create a Makefile — we will now take a look at how to achieve this.
An introduction to Makefiles
The next tool we are going to use is the Makefile. A Makefile is executed by the Linux command make. Make is a command-line utility that allows you to compile executable files by storing the parameters into a Makefile and then calling it as needed. This method allows us to store common compilation directives and re-use them without having to type out the command each time.
As you are familiar with, we have used the following command in order to compile our LED example:
g++ -lrt -lpthread blink_test.cpp arduPi.o -o blink_test
Using a Makefile, we could store this and then execute it when located in the same directory as the files using a simpler command.
make
We can try out creating a Makefile using the code. Load up Geany from the programming menu if you don’t currently have it open. If you don’t have a new document open, create a new one from the File menu. Now add the following lines to Blink_test/Makefile, making sure to tab the second line once:
Blink: arduPi.o g++ -lrt -lpthread blink_test.cpp arduPi.o -o blink_test
If you don’t tab the second line containing the compilation instructions, then the Makefile won’t run.
Now that you have created the Makefile, we can save and run it with the following steps:
-
From the File menu, select Save.
-
From the Save dialog, navigate to the directory where you saved your blink_test.cpp and save the file with the title Makefile.
-
Now open the blink_test.cpp file from the directory where you saved your Makefile.
We can test our Makefile by selecting the Build option from the menu and selecting Make.
In the panel at the bottom of the IDE, you will see a message indicating that the Makefile was executed successfully.
-
Now from the Terminal window, navigate to the directory containing your blink_test project. Located in this directory, you will find your freshly compiled blink_test file.
-
If you still have your LED example at hand, hook it up to the shield and from the command line, you can run the application by typing the following command:
./blink_test
The LED should start blinking.
Hopefully, you can see from this example that integrating the Makefile into the IDE allows us to write code and compile it as we go in order to debug it. This will be very useful when you start to work on projects with greater complexity.
Once we have written the code to record our temperature readings, we will re-visit the Makefile and create a custom one to build our thermometer application via Geany.
Now that you have set up Geany and briefly looked at Makefiles, lets get started with writing our application.
Thermometer code
We will be using the arduPi library for writing our code as we did for the LED test. As well as using standard Arduino and C++ syntax, we are going to explore some calculations that are used to return the results we need.
In order to convert the values we are collecting from our circuit and convert them into a readable temperature, we are going to need to use an equation that converts resistance into temperature. This equation is known as the Steinhart-Hart equation.
The Steinhart-Hart equation models the resistance of our thermistor at different temperatures and can be coded into an application in order to display the temperature in Kelvin, Fahrenheit, and Celsius. We will use a simpler version of this in our program (called the B parameter equation) and can use the values from the datasheet provided with our thermistor in order to populate the constants that are needed to perform the calculations.
For a simpler version of the equation, we only need to know the following values:
-
The room temperature in Kelvin
-
The co-efficient of our thermistor (should be on the data sheet)
-
The thermistor resistance at room temperature
We will use Geany to write our application, so if you don’t have it open, start it up.
Writing our application
From the File menu in Geany, create a new blank file; this is where we are going to add our Arduino code. If you save the file now, then Geany’s syntax highlighting will be triggered making the code easier to read.
Open the File menu in Geany and select Save. In the Save dialog box, navigate to the arduPi directory and save your file with the name thermometer.cpp. We will use the arduPi_template.cpp as the base for our project and add our code into it.
To start, we will add in the include statements for the libraries and headers we need, as well as define some constants that will be used in our application for storing key values. Add the following block of code to your empty file, thermometer.cpp, in Geany:
//Include ArduPi library #include "arduPi.h" //Include the Math library #include <math.h> //Needed for Serial communication SerialPi Serial; //Needed for accessing GPIO (pinMode, digitalWrite, digitalRead, //I2C functions) WirePi Wire; //Needed for SPI SPIPi SPI; // Values need for Steinhart-Hart equation // and calculating resistance. #define TENKRESISTOR 10000 //our 10K resistor #define BETA 4000 // This is the Beta Coefficient of your thermistor #define THERMISTOR 10000 // The resistance of your thermistor at room //temperature #define ROOMTEMPK 298.15 //standard room temperature in Kelvin //(25 Celsius). // Number of readings to take // these will be averaged out to // get a more accurate reading // You can increase/decrease this as needed #define READINGS 7
You will recognize some of the preceding code from the arduPi template, as well as some custom code we have added. This custom code includes a reference to the Math library.
The Math library in C++ contains a number of reusable complex mathematical functions that can be called and which would help us avoid writing these from scratch. As you will see later in the program, we have used the logarithm function log() when calculating the temperature in Kelvin.
Following are a number of constants; we use the #define statement here to initialize them:
-
TENKRESISTOR: This is the 10K Ohm resistor you added to the circuit board. As you can see, we have assigned the value of 10,000 to it.
-
BETA: This is the beta-coefficient of your thermistor.
-
THERMISTOR: The resistance of your thermometer at room temperature.
-
ROOMTEMPK: The room temperature in Kelvin, this translates to 25 degrees Celsius.
-
READINGS: We will take seven readings from the analog pin and average these out to try and get a more accurate reading.
The values we have used previously are for a 10K thermistor with a co-efficient of 4000. These should be updated as necessary to reflect the thermistor you are using in your project.
Now that we have defined our constants and included some libraries, we need to add the body of the program.
From the arduPi_template.cpp file, we now include the main function that kicks our application off.
/********************************************************* * IF YOUR ARDUINO CODE HAS OTHER FUNCTIONS APART FROM * * setup() AND loop() YOU MUST DECLARE THEM HERE * * *******************************************************/ /************************** * YOUR ARDUINO CODE HERE * * ************************/ int main (){ setup(); while(1){ loop(); } return (0); }
Remember that you can use both // and /* */ for commenting your code.
We have our reference to the setup() function and to the loop() function, so we can now declare these and include the necessary code.
Below the main() function, add the following:
void setup(void) { printf("Starting up thermometer \n"); Wire.begin(); }
The setup() function prints out a message to the screen indicating that the program is starting and then calls Wire.begin(). This will allow us to interact with the analog pins.
Next we are going to declare the loop function and define some variables that will be used within it.
void loop(void) { float avResistance; float resistance; int combinedReadings[READINGS]; byte val0; byte val1; // Our temperature variables float kelvin; float fahrenheit; float celsius; int channelReading; float analogReadingArduino;
As you can see in the preceding code snippet, we have declared a number of variables. These can be broken down into:
-
Resistance readings: These are float avResistance, float resistance, and byte val0 and byte val1. The variables avResistance and resistance will be used during the program’s execution for recording resistance calculations. The other two variables val0 and val1 are used to store the readings from analog 0 on the shield.
-
Temperature calculations: The variables float kelvin, float fahrenheit, and float celsius as their names suggest are used for recording temperature in three common formats.
After declaring these variables, we need to access our analog pin and start to read data from it.
Copy the following code into your loop function:
/******************* ADC mappings Pin Address 0 0xDC 1 0x9C 2 0xCC 3 0x8C 4 0xAC 5 0xEC 6 0xBC 7 0xFC *******************/ // 0xDC is our analog 0 pin Wire.beginTransmission(8); Wire.write(byte(0xDC)); Wire.endTransmission();
Here we have code that initializes the analog pin 0. The code comment contains the mappings between the pins and addresses so if you wish, you can run the thermistor off a different analog pin.
We are using pin 0, so we can now start to take readings from it. To get the correct data, we need to take two readings of a byte each from the pin. We will do this using a for loop.
The Raspberry Pi to Arduino shield does not support the analogRead() and analogWrite() functions from the Arduino programming language. Instead we need to use the Wire commands and addresses from the table provided in the comments for this code.
Add the following for loop below your previous block of code:
/* Grab the two bytes returned from the analog 0 pin, combine them and write the value to the combinedReadings array */ for(int r=0; r<READINGS; r++){ Wire.requestFrom(8,2); val0 = Wire.read(); val1 = Wire.read(); channelReading = int(val0)*16 + int(val1>>4); analogReadingArduino = channelReading * 1023 /4095; combinedReadings[r] = analogReadingArduino; delay(100); }
Here we have a loop that grabs the data from the analog pin so we can process it.
In the requestFrom() function, we pass in the declaration for the number of bytes we wish to have returned from the pin. Here we can see we have two — this is the second value in the function call. We will combine these values and then write them to an array; in total, we will do this seven times and then average out the value.
You will notice we are applying a calculation on the two combined bytes. This calculation converts the values into a 10-bit Arduino resolution. The value you will see returned after this equation is the same as you would expect to get from the analogRead() function on an Arduino Uno if you had hooked up your circuit to it.
After we have done this calculation, we assign the value to our array that stores each of the seven readings.
Now that we have this value, we can calculate the average resistance. For this, we will use another for loop that iterates through our array of readings, combines them, and then divides them by the value we set in our READINGS constant.
Here is the next for loop you will need to accomplish this:
// Grab the average of our 7 readings // in order to get a more accurate value avResistance = 0; for (int r=0; r<READINGS; r++) { avResistance += combinedReadings[r]; } avResistance /= READINGS;
So far, we have grabbed our readings and can now use a calculation to work out the resistance. For this, we will need our avResistance reading, the resistance value of our 10K resistor, and our thermistor’s resistance at room temperature.
Add the following code that performs this calculation:
/* We can now calculate the resistance of the readings that have come back from analog 0 */ avResistance = (1023 / avResistance) - 1; avResistance = TENKRESISTOR / avResistance; resistance = avResistance / THERMISTOR;
The next part of the program uses the resistance to calculate the temperature. This is the portion of code utilizing the simpler version of the Steinhart-hart equation. The result of this equation will be the ambient temperature in degrees Kelvin.
Next add the following block of code:
// Calculate the temperature in Kelvin kelvin = log(resistance); kelvin /= BETA; kelvin += 1.0 / ROOMTEMPK; kelvin = 1.0 / kelvin; printf("Temperature in K "); printf("%f \n",kelvin);
So we have our temperature in degrees K and also have a printf statement that outputs this value to the screen. It would be nice to also have the temperature in two more common temperature formats, those being Celsius and Fahrenheit.
These are simple calculations to perform. Let’s start by adding the Celsius code.
// Convert from Kelvin to Celsius celsius = kelvin -= 273.15; printf("Temperature in C "); printf("%f \n",celsius);
Now that we have the temperature in degrees Celsius, we can print this to the screen. Using this value we can convert Celsius into Fahrenheit.
// Convert from Celsius to Fahrenheit fahrenheit = (celsius * 1.8) + 32; printf("Temperature in F "); printf("%f \n",fahrenheit);
Great! So now we have the temperature being returned in three formats. Let’s finish up the application by adding a delay of 3 seconds before the application takes another temperature reading and close off our loop() function.
// Three second delay before taking our next // reading delay(3000); }
So there we have it. This small application will use our circuit and return the temperature. We now need to compile the code so we can give it a test.
Remember to save your code now so that the changes you have added are included in the thermometer.cpp file.
Our next step is to create a Makefile for our thermometer application. If you saved the blink_test Makefile into the arduPi directory, you can re-use this or you can create a new file using the previous steps.
Place the following code into your Makefile:
Thermo: arduPi.o g++ -lrt -lpthread thermometer.cpp arduPi.o -o thermometer
Save the file with the name Makefile.
We can now compile and test our application.
Compiling and testing
When discussing Geany earlier, we demonstrated how to run the make command from inside the IDE. Now that we have our Makefile in place, we can test this out.
-
From the Build menu, select Make.
You should see the compilation pane at the bottom of the screen spring to life and providing there are no typos or errors in your code, a file called thermometer will be successful output.
The thermometer file is our executable that we will run to view the temperature.
-
From the terminal window, navigate to the arduPi directory and locate your thermometer file.
-
This can be launched using the following command:
sudo ./thermometer
The application will now be executed and text similar to the following in the screenshot should be visible:
Try changing the temperature by blowing on the thermometer, placing it in some cold water if safe to do so, or applying a hair dryer to it. You should see the temperature on the screen change.
If you have a thermostat or similar in the room that logs the temperature, try comparing its value to that of your thermometer to see how accurate it is.
You can run an application in the background by adding an & after the command, for example, sudo ./thermometer &. In the case of our application, it outputs to the screen, so if you attempt to use the same terminal window your typing will be interrupted! To kill an application running in the background, you can type fg to bring it to the foreground and then press Ctrl + C to cancel it.
What if it doesn’t work
Providing you had no errors when compiling your code, then the chances are that one of your components is not connected properly, is connected to the wrong pin, or may be defective.
Try double-checking your circuit to make sure everything is attached and hasn’t become accidently dislodged. Also ensure that the components are wired up as suggested at the beginning of this article.
If everything seems to be correct, you may have a faulty component. Try substituting each item one at a time in the circuit to see if it is a bad wire or faulty resistor.
Up and running
If you see your temperature being output successfully, then you are up and running! Congratulations, you now have a basic thermometer. This will form the basis for our next project, which is a thermostat.
As you can see, this application is useful. However, returning the output to the screen isn’t the best method, it would be better for example, if we could see the results via our web browser or an LCD screen.
Now that we have a circuit and an application recording temperature, this opens up a wide variety of things we can do with the data, including logging it or using it to change the heat settings in our homes.
This article should have whetted your appetite for bigger projects.
Summary
In this article, we learned how to wire up two new components — a thermistor and resistor. Our application taught us how to use these components to log a temperature reading, and we also became familiar with Makefiles and the Geany IDE.
Resources for Article :
Further resources on this subject:
- Folding @ Home on Ubuntu: Cancer Research Made Easy [Article]
- Using PVR with Raspbmc [Article]
- Using ChronoForms to add More Features to your Joomla! Form [Article]