Arduino Tutorial: Temperature Sensor

An Arduino Tutorial on building a temperature sensor – and an iPhone app to connect with it! By Tony Dahbura.

Leave a rating/review
Save for later
Share
You are currently viewing page 4 of 5 of this article. Click here to view the first page.

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:

stackableheadersinstalled

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:

groveshieldsideviewarrows

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).

LEDwiringongrovewitharrows

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.

LEDwiringongroved5d6marked

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); 
  1. Include the headers for the OneWire and DallasTemperature libraries.
  2. Declare two constants indicating to which pins the temperature sensors are wired.
  3. Declare an object to communicate with the indoor sensor using a OneWire object and passing it to the DallasTemperature library.
  4. 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.

Note: The github source to the Dallas Temperature library is here. There is no API reference per se, but if you peruse the DallasTemperature.h file you will see some great comments on the different method calls available.

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!

Icanprobe

Tony Dahbura

Contributors

Tony Dahbura

Author

Over 300 content creators. Join our team.