2014-01-15

Continuous temperature monitoring

Two years ago, when we returned from our skiing vacation, there was a nasty surprise waiting for us: with outside temperatures of down to -20° (celsius), our heating system had shut down. At one point, the pilot flame went out, and without it the heater could switch on again. I don’t know the reason for that (and it hasn’t happened since then), maybe there was a drop in gas pressure. Fortunately the temperatures were not so low for the vacation of last year, but for this year I decided I would like to be able to handle this problem.

Since I cannot really alert the service technician automatically (maybe I could, but he wouldn’t get into the house anyway), I want to know at least that there is some kind of a problem. Some I need some kind of temperature monitoring.

Some ideas

First I thought of using a contact-less temperature sensor (like the TMP006 or the MLX90614) to monitor the pilot flame directly. Out natural gas heater is not a completely closed one, but is has an open bottom (needed for fresh air). So I could put such a sensor underneath the heater and point the sensor directly to the pilot flame. But I didn’t dare to risk any discussion with the chimney sweeper who controls this once a year (in Germany we are required by law to do this).

Also, having electronics near a system producing a considerable amount of heat might pose interesting problems (both sensors in questions are sensitive to environmental temperature). Second, there was the question of alerting. I had an old Nokia mobile phone around, so I could use that one. Just put a prepaid card in it, and sens out an SMS in case the pilot flame goes out. So I went ahead and ordered a serial connector for it (costs just a few Euros on Ebay).

The plans they are a-changing

But I still was not really happy with that. How to detect, e.g. a power failure or any problems with the phone? I would need to send regular “I’m alive” messages from the phone, so it would accumulate in costs. And if I didn’t, the prepaid card most likely gets disabled after 12 months of inactivity.

So I kept looking for a solution which provides continuous monitoring. And when I stumbled over my mbed I had an idea. Since the mbed has everything needed to connect it to the internet (except for a RJ45 jack and ther magnetics - and I had this as breakout), I could go that route. I remembered that there was a service called Pachube which allowed live data collection (designed for the Internet of Things) and then could show the data as a nice graph. Looking after it, I discovered that it had now been renamed to Xively, and gone a more commercial route. Also, its API didn’t seemed to be that easy to use. But while looking for other, similar services, I discovered ThingSpeak. It has a reasonable free plan, and the API can be used in a rather simple way.

Having settled the display part of the problem, I looked at the temperature sensing part again. Since any solution coming near the heater were problematic, I settled for just monitoring the room temperature. After all, we keep the house at a reasonable temperature (around 18°) even when on vacation. So a considerable temperature drop below that would be a clear signal that something went wrong. And since european houses have, due to being stone-build, a large thermal mass, they don’t cool down that fast.

So looked in the parts bin and found, from a previous project, some TC77 SPI temperature sensors, mounted ready-to-use on a breakout board. These sensors are fairly accurate (±1° in the worst case) and easy to use.

A prototype

Having settled all questions, its time to start prototyping. After opening a new account at ThingSpeak, I configured a monitoring channel, and add a single field ‘temperature’ to it. Then I can look at the channel, and look for the ‘Write API key’. This key is used to authenticate the user with ThingSpeak, so only my devices can write to that channel.

Looking at the API documentation, I can see that the URL for sending new temperature values is rather simple:

http://api.thingspeak.com/update?key=WRITE_KEY&field1=TEMPERATURE

Its really as simple as that. ThingSpeak uses the write key to detect the channel I’m writing to, and appends the values for the fileds attached at the URL. The values get assigned to the current timestamp by ThingSpeak, so the mbed doesn’t need to keep track of the current time by itself.

So I fired up the mbed IDE and took a closer look at the documentation. There is a really comprehensive API available on the mbed, for nearly everything one might connect to a MCU. And its really easy to use. The same way I like the Cypress PSoC for prototyping of hardware, I like the mbed for prototyping of software (at least for embedded one). Its just amazing how much stuff one can do with a few lines of code when the API is just right.

The code I need is, basically just these few lines (skipping over error handling, debug support and some more advanced stuff):

#include "mbed.h"
#include "EthernetInterface.h"
#include "HTTPClient.h"

SPI spi(p5,p6,p7); // MOSI, MISO, CLK
DigitalOut cs(p8); // CS
EthernetInterface ethif;
HTTPClient http;

char urlBuffer[256];

char str[512];

main()
{
    spi.format(16,0);
    spi.frequency(100000);

    // initialize ethernet hardware
    ethif.init(); //Use DHCP
    r=ethif.connect();
    while (1)
    {
        cs=0;
        int16_t temp1 = spi.write(0x00);
        cs=1;
        int temp2=temp1/8;
        float temp3=(float)temp2/16.0;
        sprintf(urlBuffer, "http://api.thingspeak.com/update?key=WRITEKEY&field1=%f", temp3);
        http.get(urlBuffer, str,128);
        wait(60); // 1 minute
    }
}

Thats it. Did I mention that mbed is great for prototyping?

Having written that code, I started putting the circuit together. Yes, with the mbed one can risk doing that - the software is simple enough that I don’t need to got with building it up in incremental steps to verify that it works. So I put the mbed, the TC77 breakout and the ethernet jack on the breadboard and wired it up:

The temperature logger prototype

There is not much to it, since really everything else needed is in the mbed module. One 100 nF capacitor for the ethernet jack and two resistors for the LEDs (which also in the jack). The decoupling cap for the temperature sensor is already on the breakout. There is no PHY for the ethernet needed, since its already on the mbed module.

For testing I powered everything from my computers USB port (which is needed anyway for putting the program on the mbed flash disk), but later on I will use a small USB power supply salvaged from an old mobile phone of mine. And lo and behold, the program worked right from the beginning (at least after I discovered that the network cable I intended to use was not properly seated in the ethernet switch…).

ThingSpeak not only collects the data I send to it, but also provides some means for retrieving it later on. One of the ist the Chart API which takes the data and displays it as configurable chart. So after some days I got the following graph:

The temperature curve in my study

28%deg; Celsius might look a little bit high, but the sensor is too near to the radiator. So its gets always warmer when the room gets heated. But apart from that I now get a good reference of how warm it should be when everyting is running smooth.

Normally one can only look at its own channels when they are either public or one is logged in into ThingSpeak. But one can also create ‘ReadKey’ for the channel, and add it to the URL used for the Chart API. Doing that allows me to see the chart on any device (e.g. my tablet) without having to log in every time.

So now I’m much more confident when going to vacation - I just should not forget the phone number for our service technican, in case I need to call him…

The source code

Here is the code I’m using right now, just for reference. I have added some comments to explain how it works. In addition to the outline above I have added handling for the network going down inbetween, and some debugging help (logging to serial, and some LEDs). But its still reather simple.

#include "mbed.h"
#include "EthernetInterface.h"
#include "HTTPClient.h"

// ebug output to the PC (integrated USB2Serial bridge)
Serial pc(USBTX, USBRX);

// SPI for the TC77 sensor
SPI spi(p5,p6,p7); // MOSI, MISO, CLK
DigitalOut cs(p8); // CS

// LEDs on the ethernet connector
DigitalOut led_g(p30); // green: link
DigitalOut led_y(p29); // yellow: activity

// Network stuff
// core ethernet interface
Ethernet eth;
// basic ethernet
EthernetInterface ethif;

// ThingSpeak stuff
char* thingSpeakUrl = "http://api.thingspeak.com/update";
char* thingSpeakKey = "MYKEY";
char urlBuffer[256];

char str[512];

// remember link state
bool link_was_down=true;
bool link_up=false;

int main() 
{
    // disable TC77
    cs=1;
    // wait for ethernet to come up
    wait(2);

    // set everything to 'start'
    int led_state=0;
    int timer=0;
    led_g=1;

    // we need a HTTP client for ThingSpeak
    HTTPClient http;

    // configure SPI for the TC77 - mode 0,0 with 16 bits
    spi.format(16,0);
    spi.frequency(100000);

    // initialize ethernet hardware
    ethif.init(); //Use DHCP
    
    // we never leave this loop until poweroff
    while(true)
    {
        // get current ethernet link state
        link_up=(1==eth.link());
        // and set the link state LED
        led_g=link_up?1:0;
        if (link_up)
        {
            // if the link has come up 
            if (link_was_down)
            {
                // we configure the network stack and get an IP address
                pc.printf("starting network\n");
               
                int r=ethif.connect();
            
                pc.printf("connect status=%i\n",r);
                pc.printf("IP Address is %s\n", ethif.getIPAddress());
                // and if everything is OK now, we can go ahead
                if (0==r)
                {
                    link_was_down=false;
                }
            }
        }
        else
        {
            // if the link went down, de-configure the network stack properly
            if (!link_was_down)
                ethif.disconnect();
            link_was_down=true;
        }
        // called every 5 minutes (since we sleep for 5 seconds further down)
        if (60==timer)
        {
            // restart timer
            timer=0;
            // activate TC77, and read conversion result
            cs=0;
            int16_t temp1 = spi.write(0x00);
            cs=1;
            // shift right by 3 bits since the result has only 13 bits (out of 16)
            int temp2=temp1/8;
            // convert to float - each LSB is equivalent to 0.0626 degree celsius
            float temp3=(float)temp2/16.0;
            // debug log
            pc.printf("temperature=%f\n",temp3);

            // if there is network available
            if (link_up)
            {
                // build the request URL
                urlBuffer[0] = 0;
                sprintf(urlBuffer, "%s?key=%s&field1=%f", thingSpeakUrl, thingSpeakKey, temp3);
                // send request
                HTTPResult res = http.get(urlBuffer, str,128);
                // and verify the result
                if (res != HTTP_OK)
                {
                    // errors just get logged, there is nothing else we can do
                    pc.printf("Error %d\r\n", res);
                }
                else
                {
                    pc.printf("send temp=%f\n",temp3);
                }
                // each request toggles the activity LED, so it blinks with a 10 min period
                led_y=led_state;
                led_state=1-led_state;
            }
        }
        timer++;
        wait(5);
    }
}
Posted by Hendrik Lipka at 2014-01-15 (Google)
Categories: electronics projects