Power Outage Detector & Arduino UPS

Tim Blythman

Issue 1, July 2017

This article includes additional downloadable resources.
Please log in to access.

Log in

A UPS system might keep things running for a short time, but being able to monitor when the power goes off is invaluable, especially when using off-grid technology.

I was having problems at my place with the power going off, and shutting down the fridge and freezer, so I set up this project to notify me when it was happening.

Fortunately the router is on a UPS, so it wasn't too hard to get a message out, even if the power was off. I've got an Arduino Leonardo attached to a WiFi shield and a custom UPS shield. I guess I could have run the Arduino from the UPS as well, but I still needed to sense if the power was on or off, and when I thought about a UPS shield for the Arduino, it was easy to add power sensing. In addition, the analogue pins on the Leonardo make it easy to monitor the battery voltage, so that I can use it as a power supply for the setup to run untethered (away from power), and report battery voltage.


The final build monitors the mains power (via the USB power supply, which powers the project) and also reports the battery voltage on the UPS shield. In the future, I might add a couple of inputs to temperature sensors, so I can see how much the outages are affecting the fridge and freezer.

The other half of the project is monitoring. We have created a small Android app that looks at the data approximately every 30 seconds, and gives a notification if something has changed. 

The data can also be accessed from a browser, so you don’t need to use the app to view the information.


This project is self-powering, using a rechargeable Li-ion battery. By monitoring input voltages and comparing them to the battery voltage, we can determine whether there is external power available or not. This was a simple solution that doesn’t require monitoring of mains voltages, making it equally useful for monitoring mains power, or battery / solar power. 

You’re probably wondering why we’re using the Leonardo for this project. I find that having the hardware serial ports (on D0 and D1) separate to the USB serial port makes it so much easier to debug and upload. I can log status messages without interfering with the shield communication. It’s also got an extra 512 bytes of RAM, and this can be handy with web-related applications, because the amount of data that gets pushed around can easily overwhelm an Arduino.

The WiFi shield used is based around the ESP8266 WiFi chip, so just about any ESP8266 based shield or module should work, as long as it’s running the AT-command firmware. The sketch is quite long, so it is not included here, but it first sets up the module to connect to an access point. It then monitors the two analogue inputs, and uploads a message if the input voltage changes (or about every ten minutes even if there is no change). An update is reported if the battery voltage drops while it’s not charging, or if it increases while it’s charging. This helps to avoid unnecessary reports if there is a bit of jitter on the battery voltage. The flag is set so that an upload occurs on the first time through loop.


I had a look at two IoT services, both of which could easily be accessed with simple HTTP GET methods that an Arduino can handle. The first was, which is very easy to use; you don’t even need to set up an account to upload data. Unfortunately, the free version is not very secure. There is no authentication on the messages, and not only that, but the free messages are also posted to a page for all to see – and with enough information that anyone could upload spam messages.

I then looked at SparkFun’s Phant based services. This is a bit more complicated and requires a sign-up, but it also requires a private key to post data (though anyone can still view the data). This sounded good enough to me. 

Since we're using plain HTTP instead of HTTPS (the Arduino would really struggle with processing HTTPS), there is a chance the private key could be discovered, as it’s not encrypted. Another advantage of Phant is that it timestamps every message, so we can go back over the data and see exactly when the power goes on and off, and what the battery status is.


In order to push / pull data, we set up a stream at This is free and doesn’t require any email address. We just made sure that my stream was visible and it only had one field. If there is more than one field, then all of them need to be updated together. We just created a single field called ‘powerstatus’. Given that the fields can be strings, this gives enough flexibility in the messages we can create. When it’s successfully set up, there will be a public key, a private key and a field name. We need all of these in the Arduino sketch to upload. There should also be a link from the form:[publicKey]?

This link can be used to test data upload to the server, and retrieving the data can be tested with:[pubicKey].csv

You will understand that we don’t want to put our private keys in the links above! I found it was necessary to test both the upload and download links, to make sure they were working right.


To monitor the power status remotely, we’re pushing data to the Sparkfun Phant service. To set up your Phant stream:

Go to, and click “CREATE”

Fill in the form (only title and fields need to be entered)

Click save, and note values in the page that appears. If you have forgotten the field name, use the public URL to display the stream, and the fields will be displayed. The important things you need to know to access the Phant stream from the Arduino are public key, private key and the field name. Anyone with the public key can view the data, and anyone with public and private keys can upload data.

You’re done! Now you’re ready to push updates to a PHANT stream. It’s a good idea to download the link – the file will be JSON and can be edited. You need to keep these details safe. If they’re lost, you may lose access to the stream and you’ll have to create it again.


1 x Leonardo XC-4430 -
1 x WiFi Shield XC-4614 -
1 x Battery Charge Module XC-4502 Z6388
1 x 5V Boost Module XC-4512 Z6388
1 x Single AA Battery Holder PH-9203 S5026
1 x Rechargeable 14500 Battery SB-2300 S4979
2 x 10k0 Resistors RR-0596 R7782

You'll also need prototyping hardware such as a breadboard and jumper wires.

Note: We're showing actual quantity required, part numbers may relate to a pack.


The WiFi shield plugs straight into the headers of the Leonardo, just align and fit firmly. Then we can start wiring the battery charging module, and the 5V DC-DC controller. You can theoretically build this circuit without the resistors, but they provide some valuable current-limiting should something go wrong.

Circuit Diagram

The AA battery holder provides a convenient connection mechanism for the rechargeable Li-ion battery. 

It's important to note that the DC-DC converter module and battery charge modules have solder tabs rather than pins. You can create pins by soldering cut-off component legs (or tinned copper wire) - then they will work on the breadboard. Alternatively build this directly onto a prototype shield.

Note: Double check your wiring to ensure there’s no errors. Li-ion batteries under short circuit conditions can be very dangerous.


With the hardware all set up, I wrote some basic code to get a few readings. When coding my own setup, I just output these into serial monitor whilst I worked out what to do with them.

void setup() {    
void loop() {    

I discovered that an easy way to test if the power is on or off is to compare battery voltage with input voltage. If input voltage is higher, then it is okay; if it is lower, then the battery isn’t charging and there we can safely assume that there’s no longer outside power. 

There are five things you might need to change to customise the sketch to your own setup, and they are all set as constants at the start. They are the WiFi SSID and password, the private and public keys of your stream, and the field name. The first two lines are obviously your SSID name and password, and the rest are for the Sparkfun Phant service configuration. See the sidebar for a quick guide on how to do this.

#define HOSTNAME ""
#define HOSTPORT "80"
#define PHANTPUBLICKEY "[pubic key]"
#define PHANTPRIVATEKEY "[private key]"
#define PHANTNAME "powerstatus"

The sketch effectively does the same as fetching a page in a web browser (the same as[publicKey]?private_key=[privateKey]&powerstatus=[value] above). To do this at the Arduino level, open a TCP connection to the server listening on port 80 (these are the commands the Arduino is sending to the ESP8266 chip on the WiFi shield):


Then request a page:

GET /input/[publickey]?private_

The AT+CIPSEND command says that we are sending data. The data follows, and then says we want to ‘get’ the resource listed. I’ve split it into three sends so that the actual content (the middle send) can be a variable that can be changed. Note: the message is ‘per cent encoded’, as spaces in the middle of URLs will confuse the server.The server should respond with a HTTP header (which says thins like whether the request was able to be processed or not), followed by the data, which is the same as what goes to a web browser for display. In this case, we just look for “200 OK”, which means everything worked. If this is done in a browser, all we’d see is the “1 success”. The “+IPD” part comes from the WiFi shield and indicates incoming data.

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET,POST,DELETE
Access-Control-Allow-Headers: X-Requested-With,Phant-Private-Key
Content-Type: text/plain
X-Rate-Limit-Limit: 300
X-Rate-Limit-Remaining: 298
X-Rate-Limit-Reset: 1494054685.047
Date: Sat, 06 May 2017 06:59:41 GMT
Transfer-Encoding: chunked
Set-Cookie: SERVERID=; Expires=Thu, 01-Jan-1970 
00:00:01 GMT; path=/
Cache-control: private
1 success

After that, we mark that the upload was successful, and the server will close the connection because we didn’t send any more data. Apart from that, the sketch just has a small timeout so that it’s not trying to work constantly, and some debugging messages to the serial monitor.


The feed is there for the taking, so we can easily integrate simple monitoring. We have provided a simple Android solution, as well as a web-browser monitor. The code for the Android app, and the HTML monitoring page are provided as part of the resources package.

It's important to mention that you can simply view the stream on the public Phant service, by visiting the Phant website with your custom URL. This requires no additional coding, monitoring, or anything else. It's not terribly convenient though.

Where it is more useful however, is in debugging. At least you can easily see if data is reaching the Phant server. If not, your issue is probably in the Arduino. If it is, and your monitoring app isn't picking it up, the issue likely rests with your monitoring system.


For those of you using an iPhone, you know that rolling a quick iOS app isn’t usually feasible unless you’re a developer and relatively familiar with the process. 

On Android however, it’s much easier. I’ve tried a few tools for putting together Android apps, but the easiest for me has been RFO Basic. The compiler is a completely separate tool, but it works well enough for me. Most of the apps I’ve created are simply linking an input to an output in a handy interface (eg an on screen joystick controlling a robot via Bluetooth). In this project, the app sits there and checks the feed on the Phant service repeatedly, and then notifies me if there is a change.

The app starts by reading a URL from a config file called phantmon.txt. If the file doesn’t exist, the user is prompted to enter a URL, which is saved. The main graphics routine draws four rectangles scaled to the screen size – a title, the retrieved status, a refresh button, and a hide button. The colour coding of the status box uses green for latest update okay, yellow for refreshing, and red for latest update not successful. A refresh occurs every 30 seconds or when the refresh button is pressed.

Power status is displayed, along with manual refresh / hide options.
Power status is displayed, along with manual refresh / hide options.
The app will display a notification if power status changes
The app will display a notification if power status changes.

A refresh makes a request to:[publicKey].csv?limit=1

The limit=1 parameter reduces the amount of data we need to process, and returns just the most recent update. The CSV file is parsed by looking for the first LF (to skip the column header), and then the first comma after that, and then it record everything in between. The CSV data looks like this:

  POWER OFF,2017-05-06T07:09:55.040Z

In this particular case, ‘POWER OFF’ is the string we are looking for. This is compared to the last update received, and if it is different, a notification is displayed. If the ‘Hide’ button is pressed, the app runs in the background, still checking the status every 30 seconds, and if a change occurs then it raises a notification, which can be seen in the status bar.


I also wanted to be able to keep an eye on the power status while I was working on my computer, so I set up a small standalone html page that has some JavaScript to do the same job as the app:

It uses the JSON output of the stream instead of the CSV output, as JavaScript can handle JSON easily. As per the app, the data is checked every 30 seconds, and if a change is detected, a pop up message is triggered. The button can also trigger a manual refresh.


Even without the backup battery system, the Leonardo and WiFi shield could be used for logging data to the Phant server. Looking at the other streams that are available on the Public Streams page, there are quite a few weather stations running on Phant. In my case, I’m going to add some temperature sensors to monitor the fridge and freezer that cause me trouble when the power goes off. This would be a great setup to have if you had a fridge (or any other critical equipment) running off a solar system – you could know if the solar is working or not, even rig up the temperature sensors to know if the fridge isn’t working, or even record solar battery voltage and charging, to know how it’s performing. Most of this information doesn’t need to be checked by the app, but just uploaded as a stream for graphing. There’s also another service called, which is designed to give a better interface and allow graphing of data sources like those on Phant. I might consider putting my stream on after I add a few analogue values, which can actually be plotted.