Arduino Tutorial: Temperature Sensor
An Arduino Tutorial on building a temperature sensor – and an iPhone app to connect with it! By Tony Dahbura.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
Arduino Tutorial: Temperature Sensor
45 mins
- What You’ll Need
- Installing the Arduino IDE
- A Little Electronics Theory
- Installing the Libraries
- Wiring It All Together
- Wiring the LED onto the Breadboard
- Talking to the Network
- Serving Up Some JSON
- Installing the Grove Shield
- Reconnecting the Status LED
- Reading Temperatures
- At Long Last, the Starter Project
- Where to Go from Here?
Serving Up Some JSON
The wonderful thing about the server is that you can control what it serves. And you need to serve JSON-formatted data to make reading and parsing it by external callers as easy as possible.
Note: If you are not sure what JSON is or why it’s useful, check out our Working with JSON in iOS 5 Tutorial.
Note: If you are not sure what JSON is or why it’s useful, check out our Working with JSON in iOS 5 Tutorial.
Back in loop()
, fix the code to produce JSON by adding two variables at the top of the method:
void loop(void) {
//two variables to hold your temperatures
float temperatureIndoor;
float temperatureOutdoor;
// listen for incoming clients
EthernetClient client = server.available();
Further down, where the same method outputs HTML, replace all the code inside the if
statement with the following changes:
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
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();
temperatureIndoor = 22.77;
temperatureOutdoor = 15.55;
client.print("{\"arduino\":[{\"location\":\"indoor\",\"celsius\":\"");
client.print(temperatureIndoor);
client.print("\"},");
client.print("{\"location\":\"outdoor\",\"celsius\":\"");
client.print(temperatureOutdoor);
client.print("\"}]}");
client.println();
break;
}
Select File/Upload to compile and upload the code again to the Arduino. Open your Serial Monitor.
Using your web browser, reload the HTML page to the Arduino. You should see JSON output similar to this:
{“arduino”:
[ {“location”:”indoor”,”celsius”:”22.77″},
{“location”:”outdoor”,”celsius”:”15.55″}
]
}
File/Save this sketch as LEDBlinkAndEthernetFakeTemperatureJSON.
Take a break and enjoy the fruits of your labor. You have an Arduino microcontroller talking JSON and serving content on your network. Try pressing the reset button on the Ethernet Shield and give the system a second – it will come right back up, ready to serve up more content!
Installing the Grove Shield
You might have initially thought about plugging the Grove Shield in first, then placing the Ethernet Shield on top of that. Unfortunately, this won’t work due to the Grove Shield not passing the 6 pins on the back through to the front.
This brings up an important point regarding Arduino shields: they are not built identically. Many times you need to come up with creative ways to mix and match different shields. The stackable headers lift the boards far enough apart to avoid shorting pins.
To install the Grove Shield, first turn off your Arduino by disconnecting it from the USB connector. Since you’ll be plugging in more components, you need to reduce the possibility of damage to the sensitive electronics. Once you’ve disconnected the board, take the two wires (blue and orange) out of the header pins.
Next, insert the four stackable headers into the header pins on the Ethernet Shield. You need to do this because the Ethernet Shield’s RJ45 connector (the place where you plug the Ethernet cable in) is large enough to short out the headers on the Grove Shield (basically, an electric charge might flow from the metal of the RJ45 connector to the Grove Shield, causing major problems!)
Each header matches the pin counts on one of the Ethernet Shield’s headers. When you’re done, your board should look like this:
Carefully place the Grove Shield board in place onto the stackable headers without bending or missing any pins. The Grove Shield has only six pins going into the right and left headers, which have eight on the Ethernet Shield. Align the back pins away from the RJ45 connector and don’t worry about the two missing pins.
Upon installation, the Grove Shield should look like this:
Note the two missing pins on the side facing you (indicated by the arrows) and on the opposite side. All other pins should be seated inside of the headers.
Reconnecting the Status LED
Looking down on the Grove Shield, reconnect your two LED wires. Plug the blue (GND) wire into the fifth pin from the front on the right side. Insert the orange wire into the ninth pin from the front on the left side (the first pin in the second connector).
Plug the two temperature sensors into the white jacks labeled D5 and D6, respectively. The connectors will only go in one way. The D5 and D6 jacks are circled in the image below.
Reconnect the Ethernet RJ45 cable and finally, connect the USB cable to power the circuit. Your LED should come on solid during address acquisition and then turn off.
Open the Serial Monitor to watch the messages. Using your browser, connect to the server and make sure it is still serving the JSON data correctly.
If your LED didn’t come on, there could be a few problems:
- You may have the wires in the wrong header pins. Double check the picture above.
- Make sure that all of the pins for the Grove Sheild and stackable headers are in their slots, and that none are bent (missing their slots).
- You might not have pushed the Grove Shield or Stackable Headers down firmly enough.
If you aren’t sure if they are connected correctly, open your TestLEDOnPin7 sketch and upload it. The LED should blink as before.
Once you’ve got it working, whoohoo! You finally have all of the pieces in place to start reading the temperatures.
Reading Temperatures
Open the LEDBlinkAndEthernetFakeTemperatureJSON sketch and File/Save As… as LEDBlinkAndEthernetTemperatureJSON. This file is where you’re going to interface with the temperature sensors.
At the top of the sketch file, add the following code (replacing the current lines up until setup):
#include <SPI.h>
#include <Ethernet.h>
#include <OneWire.h> //1
#include <DallasTemperature.h>
//The data wire for the indoor sensor is plugged into pin d5 on the Arduino
// on pin 5 & 6 (a 4.7K resistor is necessary) - the temperature probe has one built in.
//2
#define TEMPERATURE_INDOOR 5
#define TEMPERATURE_OUTDOOR 6
const int ledPin = 7;
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x7D, 0x54 };
//3
//setup an instance to communicate with your sensor
OneWire oneWireIndoor(TEMPERATURE_INDOOR);
DallasTemperature sensorIndoor(&oneWireIndoor);
//4
OneWire oneWireOutdoor(TEMPERATURE_OUTDOOR);
DallasTemperature sensorOutdoor(&oneWireOutdoor);
EthernetServer server(80);
- Include the headers for the OneWire and DallasTemperature libraries.
- Declare two constants indicating to which pins the temperature sensors are wired.
- Declare an object to communicate with the indoor sensor using a OneWire object and passing it to the DallasTemperature library.
- Repeat the code to create an object for the outdoor sensor.
The sensor on pin 5 will be your indoor sensor, while the sensor on pin 6 will be placed outdoors.
The DallasTemperature
object uses pieces of the Arduino OneWire
library to support communications on the bus. Hence, you need to define both objects.
Inside setup()
, add calls to sensorIndoor.begin()
and sensorOutdoor.begin()
:
void setup(void) {
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
Serial.println("LED Pin setup for output on pin ");
digitalWrite(ledPin, HIGH);
sensorIndoor.begin();
sensorOutdoor.begin();
// start the Ethernet connection and the server:
Serial.println("Trying to get an IP address using DHCP");
Now on to the loop()
code, which does the heavy lifting of responding to user requests from the network and producing the temperature as part of the results.
Earlier in the JSON section, you had two variables, temperatureIndoor
and temperatureOutdoor
, that for testing purposes had hard-coded temperature values. Now comes the magic of the sensors: you’ll use these same variables, but store real temperatures in them.
Change the two lines that set values for temperatureIndoor
and temperatureOutdoor
to instead call the readTemperatureCelsius()
subroutine:
client.println();
temperatureIndoor = readTemperatureCelsius(sensorIndoor);
temperatureOutdoor = readTemperatureCelsius(sensorOutdoor);
client.print("{\"arduino\":[{\"location\":\"indoor\",\"celsius\":\"");
You may be wondering about the source of this magical subroutine called readTemperatureCelsius
. Let’s cover that next!
Scroll down in the sketch and insert the following subroutine above the blinkLED
subroutine:
float readTemperatureCelsius(DallasTemperature sensor) {
sensor.requestTemperatures();
float temperature = sensor.getTempCByIndex(0);
Serial.print("Celsius Temperature for device is: ");
Serial.println(temperature); //zero is first sensor if we had multiple on bus
return temperature;
}
This subroutine takes a DallasTemperature
sensor object and executes a requestTemperature
command on the proper bus. It returns the temperature as a floating point value using sensor.GetTempCByIndex()
. This method requests the Arduino to signal the bus and communicate with the first probe present (position 0) on the bus.
Since you only have one probe on the bus, it will return the temperature of that probe in Celsius. If you wanted the temperature in Fahrenheit, you would make the call to GetTempFByIndex()
.
The OneWire library and documentation is available here. This web page includes basic usage instructions plus more than enough information on OneWire bus and protocols.
The OneWire library and documentation is available here. This web page includes basic usage instructions plus more than enough information on OneWire bus and protocols.
The server for this tutorial uses Celsius as the standard format (just a choice on my part), and you will convert it to Fahrenheit on the iPhone if the user desires that. The temperature reads take a fair amount of time to complete, so it is more efficient for your microcontroller to read the temperature once versus twice for each probe and do the conversion on the iPhone.
Save the sketch and upload to your Arduino by clicking File/Upload. Hit the server with a browser. Open the Serial Monitor to watch the output. You should see the temperature of the room in which you’re working!
Try holding your hand around one of the sensors and reading the temperature a couple of times to watch it rise. Let go of the sensor and access it again to see the temperature fall. Resist the temptation to stick the probe in a bodily orifice of an unwilling creature. :]
Note that there’s a slight delay on the reads, as the Arduino must probe the bus and get the results back before it can send them out. Also note that your browser sometimes sends multiple GET requests each time you browse to a URL (behind the scenes, it is trying to find a icon for the web page, which of course doesn’t exist in your case). Your iOS application will be more efficient than this!
OK! At this point you have a dedicated hardware-assembled temperature monitor. WOOHOO!