Arduino Tutorial: Networked Temperature Sensor with Swift

In this Arduino Tutorial, you’ll work with a temperature sensor and the companion iPhone app in Swift to connect with it! By Tony Dahbura.

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

Server Setup

Now let’s get the server to handle inbound requests! This is where loop() comes to life. Add the following after the end of setup(), replacing the current function stub:

void loop(void) {
  // listen for incoming clients
  EthernetClient client = server.available();
  
  if (client) {
    Serial.println("new client");
    //an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        Serial.write(c);
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n' && currentLineIsBlank) {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<html><body>HELLO</body></html>");
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        } 
        else if (c != '\r') {
          //you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(1);
    // close the connection:
    client.stop();
    Serial.println("client disonnected");
    blinkLED();
  }

}

loop() checks if a connection has come in and displays all the connection data sent by the client and responding with a HELLO.

The code reads one character at a time, looking for the blank line on the request. At the conclusion of all this, you quickly blink the LED and wait for more connections.

Compile and upload the code by selecting File/Upload.

Let’s give the web server a spin! First reopen the Serial Monitor window by selecting Tools/Serial Monitor. Then using a browser on your Mac, open the URL: http://[the IP displayed in the Serial Monitor].

Your Serial Monitor output should show something similar to the following:

serialmonitorhtmloutput

And your browser should say HELLO, which is what you put in the loop code to display!

htmlbrowserhello

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.

Back in loop(), fix the code to produce JSON by adding two variables at the top of the method:

//two variables to hold your temperatures
float temperatureIndoor;
float temperatureOutdoor;

Further down, where the same method outputs HTML, find the if statement that checks for newlines. Replace it along with its entire code block with the following:

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. You should see JSON output similar to this:

{"arduino":
	[   {"location":"indoor","celsius":"22.77"},
            {"location":"outdoor","celsius":"15.55"}
	]
}

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!

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>

//2
#define TEMPERATURE_INDOOR 5
#define TEMPERATURE_OUTDOOR 6

const int ledPin = 7;
byte mac[] = { 0x90, 0xA2, 0xDA, 0x0D, 0x7D, 0x54 };

//3
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 and getting the temperature 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 readTemperatureCelsius. Scroll down in the sketch and insert that 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.

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 server for this tutorial uses Celsius as the standard format (just a choice on my part). The temperature conversion to Fahrenheit is done on the iPhone if the user wants that.

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 to see the temperature fall :].

Note the slight delay on the reads, as the Arduino probes the bus and gets 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!

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.