Photon Remote Temperature Sensor

Pages
Contributors: jenfoxbot
Favorited Favorite 11

Introduction

Phant is No Longer in Operation

Unfortunately Phant, our data-streaming service, is no longer in service. The system has reached capacity and, like a less-adventurous Cassini, has plunged conclusively into a fiery and permanent retirement. There are several other maker-friendly, data-streaming services and/or IoT platforms available as alternatives. The three we recommend are Blynk, ThingSpeak, and Cayenne. You can read our blog post on the topic for an overview and helpful links for each platform. The code in this tutorial will need to be adjusted to work with the other data streams.

The scientific method allows us to examine the universe and its natural phenomena. Through collection and analysis of data, we discover historical trends to make predictions about future events. One such phenomenon that greatly impacts our daily, and long-term, lives is temperature. This tutorial shows you how to build your own remote temperature sensor that automatically uploads data to the data.sparkfun.com web service. This is a perfect, hands-on project for teaching, or learning, the difference between daily temperature fluctuations and average temperature over time, a particularly crucial distinction when discussing climate change.

This system uses the Particle Photon as the control device, a handy lil' microcontroller that easily connects to WiFi. The Photon reads in temperature data from the SparkFun TMP102 digital temperature sensor, then uploads the data to a web server for remote data acquisition and, if desired, subsequent analysis and plotting.

finished system enclosed

For all you visual learners, check out a video of the project below:

Materials

To follow along with this project at home, you'll need the following:

Electronics

Here's a wish list of most of the parts mentioned above for your convenience.

Casing and Installation

  • For electronics: Project box or waterproof tupperwear

    There are tons of options for cases, just be sure it is durable, waterproof, and not made of metal (will block the WiFi signal).

  • Stand for solar panel (e.g. metal post, garden sign, plant holder, tripod, etc.)

    While a stand is somewhat optional, it allows you to point the panel towards the sun and adjust it throughout the year to obtain maximum incident solar radiation. Check out your local thriftstore for inexpensive items to use as a stand. Be sure the stand and attached panel will withstand the elements (including wind). Alternatively, you can attach the solar panel directly to the temperature sensor case.

Tools

Recommended Reading

The goal of this tutorial is to give you enough information to get your remote temperature sensor up and running as quickly as possible, regardless of your background and experience with the components used in this project. As such, this tutorial provides only a brief mention of the underlying hardware and software elements. Check out the guides below for more in-depth information, including the I2C communication protocol used by the TMP102 sensor and the Phant library used by the data.sparkfun.com web service.

Hardware

Software

Measuring Temperature

In our macroscopic world, temperature is a seemingly simple concept -- we intrinsically understand fundamental differences between hot objects and cold objects. Often we can estimate temperature just by looking at the object; if our stove burner is glowing red, we know that it is likely very hot and we should avoid touching it.

The standard definition of temperature is a measure of the average amount of heat, or thermal energy, of the particles in a substance. Since temperature is an average measurement, typically the size of the sample is irrelevant. For example, a small pot of boiling water will be at the same temperature as a large pot of boiling water (as long as you're at the same altitude!).

On the microscopic scale, temperature is a fairly complex phenomenon that corresponds to the molecular speed of individual atoms. In other words, temperature is a measure of the kinetic energy of the atoms that make up a particular substance. In general, for a given substance, the solid phase will have the lowest temperature because the atoms are mostly rigid, followed by the liquid phase in which atoms have more kinetic energy, and then the gaseous phase with the most energetic atoms. However, since mass is also a form of energy, less massive molecules need to have more kinetic energy to be at the same temperature as more massive molecules. This is why all three phases can exist at the same average temperature (e.g. gaseous oxygen, liquid water, solid metal).

Want to learn more about temperature? Check out this great resource.

Build It

Let's begin assembling our circuit.

  1. Set up the Particle Photon.

    Go to the Photon set up page and follow the instructions to set up your Photon for WiFi. The Photon LED will slowly pulse (aka breathe) light blue (cyan) when it is successfully connected to WiFi. Run through a practice program to check that the Photon is working as expected. The classic Blink sketch is always a good choice.

    To program the Photon, we used the Particle Build Web IDE (Integrated Development Environment). Visit the Particle website to guide you through this process.

  2. Locate your specific Photon "Device ID" and the "Access Token". Store in a convenient, and secure, location.

    The device ID can be found in Particle Build by clicking the '>' next to your device name.

    Particle Device ID

    _Find your Device ID under the "Devices" tab, by clicking the carrot next to your Photon._

    Your access token can be found under the "Settings" tab.

    Access Token

    _Find your access token under the "Settings" tab._

  3. Solder header pins to the SparkFun temperature sensor (TMP102).

    alt text

  4. Solder the DC barrel jack onto the bottom of the Photon Battery Shield.

    SMD barrel jack soldered on bottom

  5. Plug the Photon into the Photon Battery Shield. Be sure that the rounded edges of the Photon line up with the rounded lines on the battery shield. Connect the battery and solar panel to the respective connectors. Check that the Photon powers on and connects to WiFi.

    Charging with USB

    Charging with barrel jack solar panel

  6. Connect the TMP102 temperature sensor to Photon battery shield pins with the breadboard jumper wires (or stranded 22 gauge insulated wire).

    schematic

    The green wire corresponds to the SDA pins, yellow wire to the SCL pins.

    This project only needs four (4) of the six (6) pins on the TMP102: VCC, GND, SDA and SCL. If you want to connect multiple temperature sensors using the I2C lines, you can use the ADDR0 pin to changes the device address for each sensor (See the I2C communication tutorial for help with this).

    Connect TMP102 VCC pin to the Photon 3.3V source and GND to a Photon GND pin. Connect the TMP102 SDA pin to the Photon D0 pin and the SCL pin to the Photon D1 pin.

    You can keep the final system on a breadboard or transfer it to a PCB board.

Program It

Read in the TMP102 Temperature Sensor

The program provided below is designed to function essentially as-is, with only a few minor changes necessary to get the system up and running. Unless you want to add more sensors, or use different sensors, you do not need to change the program code to read in the TMP102 temperature data. That said, if you are new to electronics, or I2C communication, it is still helpful to understand the basics of how the TMP102 sends data, particularly when debugging.

Quick Overview of TMP102 Data Signal

The TMP102 temperature sensor uses I2C communication, a two-wire serial interface. The two lines are SDA (Data) and SCL (Clock). The corresponding Photon pins are D0 (SDA) and D1 (SCL). The program below uses the default address of 72 (code variable TEMP102_ADDRESS) for the TMP102 sensor.

The TMP102 sensor outputs two bytes in binary (code variable BYTES_TO_READ). The first byte is the most significant byte (MSB), and the second byte is the least significant byte (LSB). The first 12 bits (out of 16) are used to indicate temperature, where one LSB is 0.0625 °C. The program is commented where these operations occur.

Review the TMP102 data sheet for more information.

Set up a Data Host

This system uses the data.sparkfun.com web service to log the TMP102 temperature data. You can remotely access the temperature data using the public URL generated when you create your data stream. To use the program provided in the next section, follow the procedure below to set up a data stream on the data.sparkfun.com server.

  1. Create a data stream on the data.sparkfun.com service by clicking the Create button.

    alt text

  2. Fill in your desired title and description.

  3. For the fields section, input "temp" and "unit". It is imperative to use these exact field names (all lower case) or the data will not upload unless you change the respective field names in the program.

  4. Save the data stream. This will redirect you to the stream's key page. Copy all of this information and store in a secure location.

    A quick overview of the keys:

    Public Key – This is a long hash that is used to identify your stream and provide a unique URL. This key is publicly visible, meaning that anyone who visits your stream’s URL will be able to see this hash.

    Private Key – The private key is necessary to post data to the stream. Only you should know this key.

    Delete Key – This key deletes the stream, so normally you’ll want to avoid this key. Only use this key if you need to fix the field names or if you truly want to delete the data stream.

    Fields – In our program, our fields are "temp", which corresponds to the temperature reading in degrees Celsius, and "unit", to let us know that our reading is in degrees Celsius. These fields set specific values and create a new log of data.

  5. The timestamp generated is given in the UTC (Universal Time Coordinate) timezone. The easiest way to handle this timezone is to convert it to your local timezone once you've downloaded the data.

  6. To monitor the Photon output, use the Particle driver download as described in the "Connecting Your Device" Photon tutorial.

    To view the particle serial monitor, in the command prompt type particle serial monitor. This is extremely helpful for debugging and checking to be sure the Photon is posting data to your host. The program provided in the next section includes print statements that indicate the status of the data acquisition and upload process to help facilitate the setup process. You can also use any of the serial terminals mentioned in our Serial Terminal Baiscs tutorial to view serial data from your Photon.

System Code

What you need to change in the program:

  1. Copy and paste your data stream public key to the array called publicKey[].

    const char publicKey[] = "INSERT_PUBLIC_KEY_HERE";

  2. Copy and paste your data stream private key to the array called privateKey[].

    const char privateKey[] = "INSERT_PRIVATE_KEY_HERE";

What you may want to change in the program:

  1. The posting rate (code variable postingRate) sets how often the temperature data is uploaded to the data stream. The current post rate is ~ 20s (20000 ms). You can set a different value in line 23 of the program, reproduced below. The maximum post rate allowed by the data.sparkfun.com host is about one data point every 10 seconds (100 posts every 15 minutes).

    const unsigned long postingRate = 20000; //post rate to data.sparkfun.com (time in milliseconds)

  2. The temperature unit (currently in °C).

    To upload data in °F, multiply temp (line 47) by 1.8 and add 32, as shown below.

    int temp = (((( MSB << 8) | LSB) >> 4) * 0.0625)*1.8 + 32;

    Be sure to update the output unit from "C" to "F" in line 51:

    postToPhant(temp, 'F');

  3. If you are comfortable with code, feel free to change anything else you want!

Photon Remote Temperature Sensor Program

You can grab the code from below, or you can get the most up to date files from the GitHub repository.


language:c
//This code was written by Ace Levenberg <acelevenberg@gmail.com> and Jennifer Fox <jenfoxbot@gmail.com>
/*
 * ----------------------------------------------------------------------------
 * "THE BEER-WARE LICENSE" (Revision 42):
 * <jenfoxbot@gmail.com> and <acelevenberg@gmail.com> wrote this file.  As long as you retain this notice you
 * can do whatever you want with this stuff. If we meet some day, and you think
 * this stuff is worth it, you can buy me a beer in return.
 * ----------------------------------------------------------------------------
 */


// This #include statement was automatically added by the Particle IDE.
//This library is used to push data to the data.sparkfun.com server.
#include "SparkFunPhant/SparkFunPhant.h"

const char server[] = "data.sparkfun.com"; // Phant destination server
const char publicKey[] = "INSERT_PUBLIC_KEY_HERE"; // Phant public key
const char privateKey[] = "INSERT_PRIVATE_KEY_HERE"; // Phant private key

Phant phant(server, publicKey, privateKey); // Create a Phant object


const unsigned long postingRate = 20000; //Post rate to data.sparkfun.com (time in milliseconds)
unsigned long lastPost = millis();

const int TEMP102_ADDRESS = 72; //Address of TMP102
const int BYTES_TO_READ = 2; //Number of bytes to read in from TMP102 (should always be 2)

void setup() {
    Wire.begin(); //Initialize serial communication library
    Serial.begin(9600);
}

void loop() {
    if (Wire.isEnabled()) //Check if receiving a signal from I2C pins
    {
        if (lastPost + postingRate < millis()) //Wait to post until ~ 20s has lapsed
        {  
            Serial.print("Requesting from :");
            Serial.println(TEMP102_ADDRESS);
            Wire.requestFrom(TEMP102_ADDRESS, BYTES_TO_READ);
            if (Wire.available() == BYTES_TO_READ)
            {
                Serial.println("Reading!");
                byte MSB = Wire.read();
                byte LSB = Wire.read();
                int temp = ((( MSB << 8) | LSB) >> 4) * 0.0625; //Remove 4 empty bits from 2nd byte (see datasheet), 
                //combine 1st byte and 2nd byte then use conversion factor to get temp in deg. C (see datasheet)
                Serial.print("Temp is :"); 
                Serial.println(temp);
                postToPhant(temp, 'C'); //Post temperature data and unit (deg C) to your data stream at data.sparkfun.com (See lines 68 and on)
                lastPost = millis();
            }
            else
            {
                Serial.println("Unable to read the temperature"); //Used for debugging TMP102 output
            }
        }
    }
    else 
    {
        Serial.println("Wire is not enabled make sure to call Wire.begin()"); //Used for debugging I2C protocol
    }
}

//Thanks Jim Lindblom <jim@sparkfun.com> for the sample code and Phant library.
int postToPhant(int temp, char unit){

    phant.add("temp", temp); //Data stream field name "temp"
    phant.add("unit", unit); //Data stream field name "unit"
    TCPClient client;
    char response[512];
    int i = 0;
    int retVal = 0;

    if (client.connect(server, 80)) // Connect to the server
    {
        // Post message to indicate connect success
        Serial.println("Posting!"); 

        // phant.post() will return a string formatted as an HTTP POST.
        // It'll include all of the field/data values we added before.
        // Use client.print() to send that string to the server.
        client.print(phant.post());
        delay(1000);
        // Now we'll do some simple checking to see what (if any) response
        // the server gives us.
        while (client.available())
        {
            char c = client.read();
            Serial.print(c);    // Print the response for debugging help.
            if (i < 512)
                response[i++] = c; // Add character to response string
        }
        // Search the response string for "200 OK", if that's found the post
        // succeeded.
        if (strstr(response, "200 OK"))
        {
            Serial.println("Post success!");
            retVal = 1;
        }
        else if (strstr(response, "400 Bad Request"))
        {   // "400 Bad Request" means the Phant POST was formatted incorrectly.
            // This most commonly ocurrs because a field is either missing,
            // duplicated, or misspelled.
            Serial.println("Bad request");
            retVal = -1;
        }
        else
        {
            // Otherwise we got a response we weren't looking for.
            retVal = -2;
        }
    }
    else
    {   // If the connection failed, print a message:
        Serial.println("connection failed");
        retVal = -3;
    }
    client.stop();  // Close the connection to server.
    return retVal;  // Return error (or success) code.
}

Test, Encase and Install

  1. Plug battery and solar panel into Photon battery shield. Check that the Photon successfully powers on, connects to WiFi (the Photon LED will be breathing cyan), and sends temperature data to your data stream (accessible via the public URL).

  2. Coat electrical connections in epoxy or other (ideally waterproof) adhesive.

    Please note that epoxy is very permanent. If you intend to modify the project or use the components for another project in the future, use an adhesive method that is removable, like hot glue.

  3. Place electronics (except solar panel) in project case. Determine where the solar panel cable will enter the case. Use waterproofing electrical tape to seal area around solar panel cable or a drill hole in the case for the solar panel cable (coat exterior in waterproofing tape or epoxy). If you place the temperature sensor inside the case, ensure that there is sufficient air ventilation to avoid turning the project case into a sauna.

    alt text

    Be sure that the wires are not stretched or bent much as this will cause breakage over time.

  4. Seal any remaining holes or other air gaps with waterproofing electrical tape or epoxy. If you are sealing the project case lid, it is highly recommended to use a removable sealant like the waterproofing electrical tape to access the electronics in the future.

    alt text

  5. Connect solar panel to stand.

    alt text

    The stand in this example is a towel rack found at a local thrift store. This was perfect for my needs because 1) it was very inexpensive and 2) the rings are adjustable, which allows me to change the orientation of the solar panel to point it towards the maximum incident solar radiation (aka sunlight) depending on where it is installed outdoors and the current season (since the sun's path changes depending on the seasons).

    alt text

    There are tons of options for a stand! Peruse your garage/basement/attic/cupboards/closets or check out the outdoor section of a local thrift store or hardware store. Look for objects that can withstand nature's elements, will maintain ridigity, and can support the solar panel weight.

  6. Once the case and stand are complete, connect the battery and solar panel to the Photon battery shield. Check that the Photon is adequately powered, connected to WiFi (pulsing light blue), and is uploading data to your data.sparkfun.com data stream.

    alt text

    The battery used in this tutorial has a capacity of 6Ah (Amp-hours), which means it can provide 6A for 1 hour. The Photon microcontroller average power consumption is between 80 - 100 mA. Assuming maximum current draw of 0.1A, this means that the battery can power the system for ~60 hours (2.5 days) without any charge from the solar panel. This is ideal/necessary for cloudy locations (like Seattle where this project was designed and built) or for remote sites that are difficult to access on a daily basis.

    If you use a different battery, calculate the total number of hours the battery can power the Photon, without being charged by the solar panel. Do this by dividing the battery capacity (given in Amp-hours) by the Photon maximum current draw (0.1A). Since the sun hides behind the other side of the planet at night, be sure that your battery can provide power for at least 10-12 hours.

  7. Install the system within reach of the WiFi signal for which it is configured -- the Photon will flash green if it is not connected to WiFi.

    Be sure to place the temperature sensor in a shady location, avoiding direct sunlight, as incident solar radiation will increase the temperature measurement.

  8. Place the solar panel in the sunniest spot available at your chosen location. Determine the optimum solar angle for your panel, and point the solar panel in that direction. You'll want to change this angle over the course of the year as the sun's angle changes (higher in the summer, lower in the winter, also highly dependent on location). Here's a great online calculator to help you determine the optimal solar angle in your particular city.

    alt text

Data Acquisition and Analysis

The data.sparkfun.com service allows you to download your data in a few different formats, so pick the format that is easiest for you to handle. Most common data analysis programs, including Excel, R, and Python, can handle CSV (Comma Separated Values) files.

Below is one method to plot your data using a program written for the R platform, a free statistical software environment.

  1. Download your data in CSV file format (button is located at the top of the data stream).

    alt text

  2. In the R workspace, run the program below to generate a plot and basic analysis of your data. You can also get the most up to date files from the GitHub repository.


#Photon Remote Temperature Sensor Data Plot and Analysis
#Code written by Jennifer Fox  


tempPlot = function(file = ''){
    default = "C:\\test\\*.txt"

    #Load in CSV text file 
    if (file == '') file = file.choose()

    #Set data into matrix
    headers = c("Temp_C", "Unit_C", "Timestamp")
    temp_raw = read.table(file, sep = ",", quote = "", skip = 1, fill = TRUE, col.names = headers)
    
    #Add in degrees Fahrenheit 
    tempF = matrix(nrow = length(temp_raw[,1]), ncol = 2, byrow = TRUE)
    tempF[,1] = temp_raw[,1]*1.8+32
    tempF[,2] = "F" 
    temp_raw[,c("Temp_F","Unit_F")] = c(as.numeric(tempF[1:length(tempF[,1]),1]), tempF[,2])
    temp = temp_raw[,c(1,2,4,5,3)]  

    #Convert UTC timestamp into local (sensor) timezone
    timestamp_raw = temp$Timestamp
    ts_placeholder = gsub("T", " ", timestamp_raw)
    timestamp = gsub("Z", "", ts_placeholder)
    UTC_timezone = as.POSIXct(timestamp, tz="UTC") 
    my_timezone = format(UTC_timezone, tz = Sys.timezone()) #Sys.timezone() outputs the local timezone

    #Replace temp data with local timezone 
    temp$Timestamp = my_timezone

    #Plot temperature data
    plot(as.POSIXct(temp$Timestamp), temp$Temp_C, main = "Temperature (°C) vs. Time", ylab = "Temperature (°C)", xlab = "Time", xaxt = "n", pch = 20)
    axis.POSIXct(1, my_timezone, labels = TRUE) #Use the "format" argument to adjust the axis label (e.g. to print hours use: format = "%H:00" )
    dev.new()
    plot(temp$Timestamp, temp$Temp_F, main = "Temperature (°F) vs. Time", ylab = "Temperature (°F)", xlab = "Time", xaxt = "n", pch = 20)
    axis.POSIXct(1, my_timezone, labels = TRUE)

    #Calculate and output basic statistical analysis
    end_date = temp$Timestamp[1]
    start_date = temp$Timestamp[length(temp$Timestamp)]
    t_F = summary(as.numeric(temp$Temp_F))
    t_C = summary(as.numeric(temp$Temp_C))

    cat("Data Stream Start Date:", as.character(start_date), "\n", "Data Stream End Date:", as.character(end_date), "\n\n")
    cat("Summary of Temperature Data (°C)", "\n", "Average (Mean) Temperature: ", t_C["Mean"] ,"\n", "Minimum Temp: ", t_C["Min."], "\n", "Maximum Temp: ", t_C["Max."], "\n")
    cat("Summary of Temperature Data (°F)", "\n", "Average (Mean) Temp: ", t_F["Mean"] ,"\n", "Minimum Temp: ", t_F["Min."], "\n", "Maximum Temp: ", t_F["Max."], "\n")
}

The following shows the plots from the set of data collected during this project.

alt text

Click image for a closer look.

Education Extension

Building this remote temperature sensor teaches practical, hands-on skills in hardware and software engineering. Beyond direct project-based learning, there are tons of ways to extend this project for classroom and other citizen science activities. Here are a few ways to use this system to teach fundamental scientific concepts.

What is Temperature?

This system measures temperature at a very specific, and known, location, which allows us to combine our direct observations with experimental data. Create your own experiment to change the temperature reading by changing the outside environment, keeping everything else the same.

For example, move the temperature sensor into direct sunlight, and gather data over a specific time interval, then move the temperature sensor back into the shade for the same amount of time. Analyze how the temperature reading changes and compare it to your own observations of outside temperature. Experiment with different ways to change the temperature reading. Be creative*, and see what tests your students think up!

* Avoid water contact unless you've thoroughly coated the electrical connections in epoxy or other waterproof adhesive.

Heat Capacity: Comparison of Temperature and Heat

Build the temperature sensor case to be air-tight, then use different material types and/or sizes of enclosures to analyze the difference between temperature and heat. Different materials have different heat capacities, or the amount of heat needed to raise the material's temperature by one degree. In other words, materials absorb and retain heat at varying rates. This helps us understand that heat is a form of energy, while temperature is a measure of that energy.

For each case, place sensor in direct sunlight and leave overnight. Determine how quickly the temperature sensor reading increases and decreases. A high heat capacity material will slowly increase and decrease in temperature, whereas a low heat capacity material will quickly heat up and cool off. Create plots of the temperature changes for various cases to determine what types of materials, and what sizes, retain heat the most. Find patterns between different material types and use those patterns to determine why certain materials have higher heat capacities.

Analysis of Data Trends: Long-Term vs. Short-Term

The difference between daily temperature and average temperature is a crucial concept in understanding climate change. It also provides a real-world application of the difference between long- and short-term trends. Fortunately, the data.sparkfun.com service makes this analysis simple and straightforward, the hardest part is waiting! It is also suggested to have a back-up battery if you live in a cloudy climate (like Seattle).

For this science lesson, gather data for a minimum of two (2) to three (3) months, ideally through a seasonal change. Download the data and find the average (mean) temperature by day, week, and month. Select a few 24-hour periods to plot temperature, and compare daily fluctuations with your calculated averages. See if you can use the temperature data to pinpoint the changing seasons!

Resources and Going Further

Looking for more weather fun? Check out these other SparkFun tutorials:

Photon Remote Water Level Sensor

Learn how to build a remote water level sensor for a water storage tank and how to automate a pump based off the readings!

IoT Industrial Scale

What does a baby elephant weigh? How much impact force does a jump have? Answer these questions and more by building your very own IoT industrial scale using the SparkFun OpenScale.

Hazardous Gas Monitor

Build a portable gas monitor to check for dangerous levels of hazardous gases.