Introduction: Remote Temperature Alarm Using Photon Particle

About: Retired software engineer. I love to tinker with anything with a cpu or a radio. Ham license KE5JL. When not at a keyboard or soldering iron I can be found hiking and fishing in the Colorado Mountains.

This is my first Instructable, so kindly ignore mistakes that seem obvious to most anyone else. I will learn as I go along.

Background.

I had a request from a friend who owns a cabin in a fairly remote location in the mountains of Colorado, where seriously sub-zero temperatures are common in mid-winter. His cabin is not so remote that it lacks electricity or phone, or most importantly, DSL internet. Each winter he would worry that the power would go out or that the electric baseboard heater would fail, causing the interior to drop below freezing and eventually cause his water supply to sustain severe damage. His request was for some way to monitor in Denver the temperature and power to his cabin using his existing internet & WiFi. And since I was - and still am - trying to learn about microprocessors, I offered to try to design a solution.

This project, when complete, will monitor the cabin temperature and power and send emails when either become an issue, plus trigger phone calls so a late night power failure doesn't go unnoticed until it is too late. To accomplish all this I needed access to the "cloud" and an alerting system that would send email and make phone calls.

The ideas for a solution slowly developed as I researched the problem. Many options came to me from right here - Instructables. I found the perfect micro controller - the Photon Particle with WiFi on the board and cheap. My two main requirements solved! It is reasonably small and low enough power to run from batteries long enough to call out for help. Plus it comes with a free subscription to the Photon Cloud - and I do love that "F" word. And to top it off, Photon and IFTTT (If This Then That) have teamed up to provide some framework apps that do the notifications - also free no less. The other processor that might do the job is the Raspberry Pi, but at a higher initial price and higher power requirements, and no direct cloud access (that I know of), it would stay on the shelf for another project. (Just noticed that Raspberry Pi released a Pi Zero with WiFi - for super cheap. Wow.)

Particle

I am using a Particle Photon P0 board (the device) which comes with a free cloud subscription. This allows events in my code to be "published", or sent, up to the cloud which then trigger certain applications provided by IFTTT/Particle to make phone calls and send email alerts. The calls and alerts are vital elements since they notify the homeowner of problems that may need immediate attention. In this particular case the homeowner will contact a nearby full-time resident with a key to check on the cabin.

In addition to published events the cloud also allows variables in the code to be monitored. So for example, the current temperature and battery voltage are always available to any code that wants to read them from the cloud. In my case I am using some HTML code running in a browser to display the temperature, alarm status, the battery voltage and the alarm messages, etc. Plus this works in the other direction so I can adjust the trigger temperature from the browser or set off a test email. Very handy stuff but this does require a human to sit at the computer so it is not as valuable as the published events for midnight emergencies.

IFTTT

IF This Then That (https://ifttt.com) has many hundreds of pre-built apps that work with various services and hardware. Particle has provided IFTTT with a range of apps that monitor its cloud for variables and events (among other categories) which allow the user (you and I) to pick just the right triggers. I could, for example, use one of the IFTTT Particle apps to monitor the temperature for a specific value and send an alarm if the cabin dropped below that value. However, I chose to let my Photon code (C++) to do the monitoring and send (Publish) an event at the right moment. The IFTTT Particle app that responds to Published events then sends the email or dials a cell phone with a pre-recorded message.

There are some limits to Published events regarding how much data (64 Bytes) and how often sent to the cloud (once per second). On the other hand, monitored variables seem to have less restrictions since they are accessed on an as-needed basis. Inside my code I will build long character strings that convey useful information to the browser but don't need to trigger alarms. So for example, I will say "the lowest temperature in the past 24 hours was 48 degrees at 4:13 AM March 2". This is information the homeowner may, or may not, want to view on a casual basis, or perhaps after an automated phone call that notified him of a power failure.

Battery Backup

In order to be notified of a power failure there needs to be a working Photon device (just device in the future) and a working WiFi. The WiFi will be on a commercial UPS. The device will be hooked up to a 6 volt battery pack (4 AA rechargeables), a battery charger and a "wall wart" (brick) power supply. I use a couple of the device's digital pins to monitor the voltage coming from the wall wart to indicate if the AC power is up. And I use one of the device analog pins to monitor the battery voltage so if the batteries are getting weak I can put the device into low power mode so it wakes up periodically or when the power is restored. Batteries are charged with a small trickle charge of 25 milliamps which should be a safe charge even if the batteries are full. The downside to such a small charge is that drained batteries will take a day or so to recharge. An alternative - although much more expensive - would have been to use a LiPo battery and a smart charger, available for this class of microprocessor - but remember my dislike for spending $$$.

Sensor

Well, you can't have a thermometer without a sensor. There are many different types to choose from and I won't be going over all the choices. I picked the Adafruit MCP9808 breakout board because it used I2C (I-squared-C) and because it was rated accurate to 0.25 degrees C. I love accuracy! Plus Adafruit provides a working C++ library and I like playing with I2C. Finally, the price was right - of course - at $5.

Enough background - lets get serious...

Step 1: The Block Diagram.

There are 6 sub-blocks in this block diagram, outlined in red. I will discuss each one and then put together the whole package.

Power Voltage sampler (part of image #2)

This takes the input 9 to 16 VDC and drops it to a regulated 2 V. It uses a pair of resistors to limit the current and to sink any leakage from the A-0 pin when (if) the input voltage goes to zero. The green LED provides both a zener diode action at around 2 V and a visual indicator that the input voltage is present. The A-0 pin can only handle a maximum of 3.3 volts like the rest of the analog pins on the Photon, and the LED acts as the upper limit. The 2 volts is connected to the pin we use to decide if the AC power is available, and it is connected to the WKP pin which will wake the Photon up from a power saving sleep. (More on power saving when we discuss the Photon.)

LM317 Constant Current Regulator and battery pack (part of image #2 and #3)

The battery pack consists of 4-AA NiMH batteries. They will supply between 4.8 and 5.8 Volts when charged. An LM317 constant current regulator is used to charge the MiNH battery pack at a constant 25 MA regardless of the input voltage. I picked 25 MA because the battery data sheets indicated that was a safe long term charging rate. However, if the batteries are totally discharged it will take a day or two to recharge. In our application we are not in a hurry. The battery pack can be disconnected from the circuit with a switch when the device sits unused for long periods. Taking out one battery will do the same thing.

The details of the LM317 constant current regulator are well documented on the web, but in short, a LM317 regulator has its output pin and adjust pin connected with a 50 Ohm resistor. 50 Ohms comes from solving for R=1.25/.025, where 1.25 is the Voltage on the adjust pin and .025 is the current wanted in Amps. Not having a 50 Ohm resistor on hand I paralleled two 100 Ohm resistors.

Buck DC-DC Switching power supply (image #4)

This handy power supply can be purchased on Amazon/Ebay for a few dollars. If you do many of these projects you will probably want the 10 pack to lower the cost to almost nothing. They are adjustable and take a wide range of input Voltages and easily supply a regulated Amp or more. I set the output Voltage to 3.3 V which is one of the accepted Voltages needed by the Photon.

Battery Voltage Sampler (part of image #2)

This is a simple voltage divider which reduces the maximum battery Voltage down to, or slightly below, the limit of the A-1 pin (3V3 like all the other A pins). The ratio of Voltages results in some oddball resistance values however. For example, 1000/1350 will work, as will 2200/2700. But the second resistance(s) are not standard values. An easy workaround is using an adjustable 1K pot - along with a couple of 500 ohm resistors on each side - and measuring the output Voltage - keeping it close to, or slightly under 3V3 with a 5V8 input. Or find a pair of resistors that comes close and you can adjust the correction in code to come up with an accurate number. Lots of options and none of them are so critical that you can't experiment a bit.

MCP9808 Temperature Sensor (visible in Part 1 and Part 6 photos)

This tiny gem comes from Adafruit (or possibly Ebay or Amazon) for $5. It sends data over I2C and is decoded by a simple Adafruit provided C++ library - which will be discussed in the coding section. It takes the same 3V3 power that supplies the Photon. Hook up the SDA pin to the Photon D0 and the SCL pin to the D1 pin and it just works! (FYI, SDA = Data, SCL = Clock). Other pins on the 9808 can be used to change the I2C address if you want to use more than one sensor. In the final construction the temperature sensor will be mounted outside the box to minimize any influence from heating by the other parts.

Particle Photon P0 development board (image #5)

I saved the best for last. For $19 you receive a microprocessor with a WiFi chip and plenty of firmware memory for a simple project like this. It has a built in short range antenna and a standard connector for an external antenna. I have not tested the limits of either since my router is at my feet. Particle gives you access to a Web IDE (Integrated Development Environment - read "Code Editor" and libraries). Or you can download a version to your computer and save everything locally, which is what I am doing. The actual compiler resides at Particle so you need an internet connection for all development as well as operations. Particle also provides access to their version of the Cloud. There are limits to how much data you can send but they are more than adequate for this project.

The power drain is perhaps the most critical specification we need to worry about. Keep in mind that we can't send information about a power failure if the device has no power or if your router/modem has gone down. The Photon P0 uses around 80 MA in normal WiFi mode and 1 MA when the WiFi is off and no processing is being done. This is one of the sleep modes that Particle provides, and the one I found to be most useful. The 4-AA batteries can power the device for a number of hours (untested) and if the power failure continues longer the device will monitor the battery Voltage and go into sleep mode if the Voltage drops too low (say, below 4.8V). It then wakes up at an interval you code and checks if the power is on and makes a loop through the code to report the current temperature and then goes back to sleep. It can also monitors the WKP pin for a rise in Voltage and wakes up immediately. The other Deep Sleep mode uses less power but does not monitor any pins and does not retain current values - but it sure can sleep safely for weeks.

Miscellaneous Parts (mostly image #2)

There are a few Schottky diodes to direct the flow of power in the right direction. It is important to use them however the Amp and Voltage ratings are not critical in this application. Use whatever is least expensive. Also, use a few decoupling capacitors at sensitive pins like A0, A1 and the input to the LM317. Typical values are .01 micro-farad, but use whatever you have handy. Not all the capacitors are shown on the block diagram.

All together now...

How does it all go together? Rather easily in my opinion. There are no dangerous Voltages or excessive currents, no high frequencies, no microscopic signal levels, and the parts are easily handled by human fingers. So, assemble them on a a perf-board with point-to-point wiring, on a breadboard with jumpers, or even just solder part to part. I experimented with a breadboard and then transferred the parts and wire to a matching PCB board.

Next: The code!

Step 2: Coding

Where to start?

Lets start on the Particle website - https://www.particle.io. From the home page select DOCS (image #2) and review the Guide to setting up a Photon device. When purchase your Photon P0 it will come unassigned - meaning it is not associated with your WiFi network. Read the information carefully since you will need to connect the device, give it a name and learn how to find its unique ID and Access Token. Stop here and allow a couple of days to read and digest this information. Then take the plunge and part with $19 and order your Photon and set up an account so you can login to the Cloud. (Note that your Cloud pages will be empty until much later in this Instructable.)

I was not entirely successful setting up my Photon (aka "device") using the phone method. I finally resorted to using the terminal "serial" commands and the reset buttons on the device. Hopefully you will not have problems - but if you do, Particle Tech support will in fact respond via email with helpful suggestions. There is also an active user forum which is monitored by Particle developers, so you are not abandoned.

Next, download the development environment by clicking on Platform and scrolling to Development Tools (image #3). It won't hurt to download everything available for your platform and later decide which are your favorites. I am mostly using Desktop IDE (known as Dev) on a Macintosh. And as mentioned above, I also occasionally use the command line interface (CLI) in the Mac Terminal window. CLI only works with the device connected to your computer using a USB cable. After your code is well developed and running most of your interaction with the device will be through the Cloud, but at the beginning having an actual USB connection will be helpful. It gives you access to the Console where the output from print() statements will be displayed. This is likely where you will see your first "hello world".

File structure

A word or two about organizing your files. (Refer to image #1)

1. Your Particle project should be in a folder with the same name as your code (or you can easily say the reverse - name your project the same as the code). Put the code in directory SRC.

2. Your code file should end with .ino. Note that this is the same file extension that Arduino uses. In fact there is so much similarity between Particle and Arduino that most code is interchangeable and can be developed in either IDE - with one major exception. Since your Cloud account is with Particle it probably won't work or compile in an Arduino environment. (I have not tried this.)

3. Library code that you add to your project should be in directory SRC with your code. Note the presence of Adafruit code. You will need this in order to use the MCP9808 temperature sensor breakout board. (If you have made it this far, now would be a good time to visit Adafruit and purchase your temperature sensor.)

Adafruit Library Code

Visit https://www.adafruit.com and type MCP9808 into the search box. Read over the description of this board and marvel at getting so much for so little. Click on the link to the Guide (https://learn.adafruit.com/adafruit-mcp9808-precision-i2c-temperature-sensor-guide) and continue reading. After about 4 pages you will come to the "Download Adafruit MCP9808 Library" button. Download your copy of the library and move the .CPP and the .H files into your SRC directory.

TempAlarm2.ino Code

There is a file at the bottom of this step called TempAlarm2.ino. This is the main code that is loaded to your device firmware. (A note about firmware. Your code remains loaded even if all power is removed, and when power is restored it automatically executes from the beginning.)

Download, then copy and paste this code into your file that you started in the Dev-IDE (or the Build-IDE if you want to work entirely on the web). Try the Compile button and confirm there are no errors. Next, confirm that your device is powered up and "breathing" (you learned all about breathing on the Particle website - right?). If it is not breathing you are not connected to the Cloud. Stop and return to the Particle documentation, read it again and "capture" your device.

Ok, your device is "breathing" the cyan color, so go ahead and push the thunderbolt icon in the IDE and upload the code to your device. There will be lots of colorful blinking - red, green, cyan - and after a few moments back to breathing. If everything went well you should also see the the auxiliary LED blinking with mostly short flashes at one second intervals. This indicates the code is running through the endless loop.

Once you have mastered the firmware download we can move to the browser code.

Step 3: Browser Code.

Browser code (aka "monitor") provides two valuable functions. First, it lets you monitor the status of your device from any browser. And second, it provides a look at the data you might need to see while debugging but can't view if your device is not connected to a computer via a USB cable. In other words this is a substitute for the "print" statements that you may have always relied on for debugging. Various examples are in images 3-6.

This code is written in Javascript. I know virtually nothing about Javascript, and only have modified a file I "borrowed" from another Instructable called "Control a Servo Over the Internet" by ThisIsSteve in arduino. I will direct you to his project if you want to learn more than I can provide. Note that he uses a Particle Core rather than a Photon. This is an earlier version of the device but the principal is the same. I have provided this file above but you will need to add your device's ID and Access Token in order to use it. Look for the variables var deviceID and var accessToken (see image #2). Replace everything between the quote marks "" with your own information.

(You obtained your Access Token and ID back in the setup section. Go back and do this step if necessary.)

This is what the code looks like in a browser:

The blue text will change to red if any part of the internet connection is broken. The blue text - with one exception - comes directly from the C++ code running on the device. The one exception is the AC Power which the device pushes out (Publish) as a 1 or 0, for "on" or "off". This is one of the triggers that sends a phone call and email so I didn't want any ambiguity ( no maybe ). The buttons "test me", "raise temp" and "lower temp" trigger functions within the firmware. Don't worry, there will be more details on how to get the values out of the Cloud and how to signal functions.

Step 4: Code Details.

Firmware on the Particle. Or "your code".

The code running on the Particle device is C++. It will require that the Adafruit library code reside in the same directory. (Download TempAlarm.ino if you have not done so already.)

Don't plan on doing anything useful quite yet. Your code is not in a useable state but rather it is configured to be helpful for debugging. Some changes you might consider prior to installing the device for real:

  1. If you are hooked up via a USB cable you can uncomment the print statements - or add some new ones - to send data to the console. These will start with Serial.printf(...).
  2. The device may be running much faster than is necessary - helpful for debugging but not ideal in the real world. Before putting the device into real world service change the value of const int RUN_DELAY. Change the value of int too_cold to the value you want the device to use to trigger an alarm.
  3. Other values you might want to change at some point are hard coded within the statements. This example controls how long the device will delay before sending a power-off alarm. A delay is nice if you expect frequent short power outages that really have no impact - false alarms - and you want to ignore them. if ( (powerOffCounter < EMAIL_LIMIT) && ( (Time.now() - powerOffTime) >=STANDARD_DELAY)) ) { // Power has been off for X minutes As written, no alarm will be sent for 30 seconds. In real life 5 or 10 minutes might work better as long as your router and modem will be powered up by the UPS for that long, so change the constant "standard_delay" to something realistic, or keep it short for testing.
  4. Another useful change would be to the "sleep" time. There will be more discussion about sleeping but for now remember that sleep disconnects the device from the internet and saves backup battery power, for a period of time determined by the last parameter. System.sleep(WKP, RISING,STANDARD_DELAY); // Awake on power rising OR after a few minutes to check the temperature in the main loop. As written, the device will sleep for 30 seconds or until the power is restored. During this time the values can not be sent to the Cloud and the device will appear to be disconnected - which it is, actually. This also defaults to "standard_delay". Change it to anything that suits you, or keep it short for testing.

Using the Cloud

The Cloud is your gateway to sending and recieving data to and from the device. Special statements are provided by Particle for this purpose. Look for the statements Particle.variable and Particle.function.

  • Particle.variable("public_name", "variable_of_interest"); This exposes the variable_of_interest to the Cloud as outgoing data - device to Cloud, in other words. The public_name must be 12 characters or less, or you will get annoying cryptic errors from the compiler. The variable_of_interest can be any String or char[]. No other types are supported. I use either a strcpy() function or sprintf() to move stuff of interest into the target string. That is all you need to do to "pull" the data - as is done in the HTML code in the previous step. On occasions you want to "push" the data out to the Cloud, which I do occasionally to monitor the state of things from the Cloud console. (Console is another web page provided by Particle.) Console will be empty until a Publish statement is executed. Cloud variables can also be monitored in your IDE but I have found that the HTML sees these much quicker.
  • Particle.function("public_name", "function_in_code"); Exposes the function to the HTML. I use a couple of simple functions to send a test alarm (to see if the entire chain is functional) and to change the value of the critical temperature trigger.
  • You should read the Particle documents to understand more about the Cloud functions and variables. I have not covered much detail - just the bare minimum to get this working.

There are limits to Publish. Only 63 Bytes of data can be sent at once, on average only one Publish statement per second (thus the numerous Delay(1000) statements after a Publish, going over the limits will result in a 4 second timeout for Cloud data. This can be annoying so I try to keep Publish down to a minimum. The primary reason in my mind to use a Publish is to trigger the email alarms and/or phone messages from IFTTT. IFTTT will deserve an entire step later on.

Sleeping

Sleeping is designed to save battery power. This is important if you are using rechargeable batteries to run your device during a power failure. Using up all the power in a rechargeable battery will shorten its lifespan.

There are a couple of sleep options provided by Particle. I use this command to sleep: System.sleep(WKP, RISING, STANDARD_DELAY); It says "shut down WiFi, pause the application (this firmware code), wait until the WKP pin rises with power resuming or until a period of time has passed". System.sleep cuts the power use from 80 Milliamps down to 1 or 2 Milliamps. The Cloud indicator ("breathing" led) goes out and the program halts on this line. When the time is up or WKP receives an "up" transition, the code resumes on the next line. All variables are retained and the effect is no different than a Delay() call.

Deep Sleep

There is another sleep mode called Deep Sleep. It saves more power - 100 MicroAmps instead of 1-2 MilliAmps. But it doesn't respond to rising power and it turns off the RAM memory. So when the timer expires the code has to start back from the beginning. Memory can be retained if transferred to flash memory but this gets complicated. I will leave Deep Sleep to the reader to investigate if so inclined. I tried it but the benefits were out weighed by the PIA factor.

Analog Pin Averaging

Notice that some values that are read from the analog pins or from the temperature sensor are kept in running average arrays. This provides some protection from "jitter" where the values seem to jump around from sample to sample even when nothing is changing. Averaging does slow up response time a bit, but this is slow moving code where a few minutes either way doesn't really matter. Feel free to adjust the averaging routines as you see fit if you want faster response or smoother data.

Alarm Limits

With my primary user's input we decided that three email notices and phone calls were enough warning. Either that got his attention or his phone was off. You can change this number to anything that suits your requirements. After the limit is reached no more alarms will be sent until the power or temperature returns to normal. See const int EMAIL_LIMIT = 3;

Publishing in a while loop

In a couple of places you will notice ! Particle.publish() in a while statement. If the Cloud is not responding Publish returns false. Using this logic allows multiple attempts to connect to the Cloud, and we can do some fancy LED blinking to indicate a problem.

Most of the code is reasonably well documented and what isn't should be discoverable with a Google search. So on to IFTTT...

Step 5: IFTTT, or What Is Wrong With Picture?

What's wrong?

Imagine this: You are down in sunny Mexico in the middle of winter. A cold snap has hit your home town so you stay in your hotel room watching the browser monitor, looking at the temperature readings and the AC power all day while your friends surf and scuba dive. Or - you purchased a fancy ski condo in the Colorado high country where the nighttime temperature drops to -20F. You check your laptop and note that the temp inside is 68 and the power is on. What you don't know is that a mouse just ate through a thermostat wire and your furnace shut down. Wake up next morning and after breakfast check the monitor only to discover the indoor temperature is 17 degrees and your pipes are likely frozen. What's wrong with this picture?

Notifications by IFTTT

What is wrong is that notifications have not been sent. So, do you really want a phone call and/or email when something bad happens to your power or temperature? You bet! Easy, set up an account with IFTTT (IF This Then That) for free and they will monitor the Cloud for you, and bug you to do something.

Start by going to ifttt.com and opening up a free (love that word) account. Once you have your account go to My Applets and select New Applet. On the next screen click on the "If Plus +" symbol which brings you to the Chose a Service page. Type in Particle to see what apps Particle has already written. You will have to decide what variables to monitor, either for a specific value or for a Publish Event. I like Events because they are all or nothing. If you agree with me, pick the New Event Published app and fill in the Published "public_name" and the value of the variable that you want to monitor. (Recall: Particle.variable( "Power_State" , powerState ); Power_State is the event name in this case, powerState is the variable in the code.) This works with the statement: Particle.publish("Power_State", powerState);

You get to decide if you want email, phone call, maybe a text message or posting to facebook, or whatever catches your attention. There are a couple of examples at the top of this step. Save the configured Apps and turn them on or off as needed. Pushing the Test button in the browser monitor will trigger the "This_Is_Bad" event and if you set up an app to monitor "This_Is_Bad" then your notice will be sent. This may take a minute or two as IFTTT doesn't guarantee instant response times. (They say up to 1 hour. Remember - the "free" word). IFTTT also has a limit - 750 notices per day.

Step 6: Summary

Photo of completed monitor.

Ok, you have your router/modem on a UPS. You have your Particle on a battery backup. You have a Cloud account at Particle and an account with IFTTT with apps set up. Now if the AC power fails or your indoor temperature drops below your chosen value, you get email, phone calls, or whatever, with the bad news. Well, that's what you wanted - isn't it?

What's easy, what's hard

I found the easy part to be buying and assembling the hardware. Some simple soldering or just plugging parts into a breadboard. Common parts like resistors, LEDs, capacitors, LM317, all easy to find. We're looking at less than $100 if you have to purchase absolutely everything. Amazon and Ebay can help keep the cost down.

The hard part for me was understanding the difference between monitoring variables (pulled up to the browser monitor) vs Publishing events with variable values. This took a lot of reading on the Particle website docs. And the initial issues I had setting up initial configuration of the Photon were a real pain. Hopefully you won't have the same problems.

Also, learning how to use IFTTT apps was interesting but looking at real world examples I provided should help with the mystery.

The C++ and HTML code was somewhere in-between. Javascript (browser monitor code) was a total mystery to me but I think I have managed a functional example. The Particle firmware code in C++ was not a problem but I needed to learn the Photon commands. Steep learning curve for me, for sure, since this is my first dive into the Cloud.

I am hoping that if you run into difficulties you will do what I do. Beat your head against the wall at first, then get some more chocolate (or more coffee) and do exhaustive Google searches until you find the answers to Life's Persistent Questions, and finally solve the problem. I know it can be done - I did it.

Thanks for looking,

Alan