Arduino Electricity Data Logger
Please note that a new version of this project is now available here.
Over the last few months we have been working with the extremely capable Michael Margolis, author of Arduino Cookbook.
We have a few projects underway with Michael which we will reveal as they come of age but to get us going we have this rather nice electricity data logger which accurately records electricity usage over time with 1W precision. The project uses the pulse from the LED on a modern electricity meter, as this is also an output common to other types of meter you will be able to measure other pulse meter outputs such as water and gas.
This energy data logger project has been built to sense each LED pulse from, in this case, an electricity meter. The logger records how many pulses occur in the given time frame, say 5 minutes, and then records this count to the on-board SD card along with the current date and time in the CSV file format. In our case the output is 1 pulse for every watt used which makes life easy. If your meter pulses to a different, as you might find in a gas meter, then some simple maths would be needed in your spreadsheet to convert from pulses to say kWh.
Picking up the LED pulse can be interesting - we opted for an Infrared sensor which is less sensitive to ambient light but can still pick up the output from out meters red crystal LED - this make screening around the sensor less of an issue - we simply used BlueTack. If you need to increase your sensitivity to your meters LED then swapping to an ambient light sensor is the way to go with a little more effort required when mounting the sensor.
The Seeeduino Stalker sketch is nicely written and takes care of some of the pitfalls experienced with the Stalker demo code. The sketch will either create a new file on the card if it doesn't exist and start writing to it or it will append an existing file - gone are the frustrations of non-zero byte files and formatting sensitivities - it just works much better.
Michael has also included 3 status LEDs which let you know that your logging session is going to plan without having to pop the card out and have a look. The Pulse LED shows you when a pulse from the meter has been successfully counted. The Write LED shows when the pulse count is written the SD card successfully (every 5 minutes by default) and the Error LED flashes continuously when there is an error writing to the SD card.
The sketch is available below - enjoy, and please let us know how you get on via the comments section at the bottom of the page.
The parts list is:
1no. TAOS TSL261 - IR light to voltage optical sensor.
3 no. LEDs of different colours.
3 no. 100Ω resistors for the LED\'s
1no. microSD card
The wiring is simple enough:
The TSL261 Light to Voltage sensor looks like this:
Wire Sensor Pin 1 (GND) to Stalker GND
Wire Sensor Pin 2 (VDD) to Stalker 3.3V (can use the I2C header)
Wire Sensor Pin 3 (OUT) to Stalker digital pin 3
Use three colours to differentiate between the functions.
Solder a 100Ω resistor to the positive (longer) leg of each LED.
The Pulse LED is on Stalker digital pin 4
The SD Card Write LED is on Stalker digital pin 5
The Write Error LED is on Stalker digital pin 6
Now, in turn, wire the positive LED leg (with resistor attached) to the appropriate digital pin on the Stalker and the negative LED leg (shorter leg adjacent to flat on the LED housing) to the Stalker GND..... you should end up with this:
Mounting the sensor on your meter:
As previously described, the kit uses an Infrared sensor to make screening the sensor easier - if the sensor is not picking up the pulse try the TAOS TSL257 which is sensitive to visible light - it all depends on the output of you meter pulse LED. Simply use some BlueTack to first position the sensor over the meter LED (you will see your Pulse indicator LED responding when it\'s right) and then screen the sensor from ambient light with more BlueTack to avoid false readings from the surroundings.
The Arduino Sketch:
You need to download the FAT16 Arduino library from http://code.google.com/p/fat16lib/ and place the files in your ...\arduino-0019\libraries folder before you attempt to upload your sketch (downloaded from the bottom of the page).
You can adjust the logging interval using this line in the code:
const long logInterval = 300;
The 300 is the interval, in seconds, at which the data gets written to the SD card. In this case every 5 minutes. The microSD card that comes in the kit is 256Mb which is enough space to store about 8 million time stamped data records which at a 5 minute logging interval equates to about 76 years worth of data - should be enough !
You should now be set - I have assumed you have successfully uploaded the sketch below to your Stalker data logger and inserted your SD card ready to power up for your data logging session.
So, all being well, the Pulse LED will be blinking every time it detects a meter pulse and the Write LED will be blinking every 5 minutes when the data gets written to the microSD card. Once you have collected your desired data period you can download your CSV file from the microSD card which will be in the following format:
Pretty good - but even better if you graph it out in your spreadsheet:
This graph show electrical watts consumed over a 4 day period. Have fun & do share your experiences via the comments section at the bottom of the page.
You can also download the PDE directly from the link at the bottom of the page.
* SimpleMeterLogger.pde - Meter reading logic for logging
* This version logs pulses on digital pin 3
* Copyright Michael Margolis 2010
* In association with www.airsensor.co.uk
#include <Fat16.h> // the SD Card library - http://code.google.com/p/fat16lib/
#include <DS1307RTC.h> // a basic DS1307 library - http://www.arduino.cc/playground/Code/Time
const long logInterval = 300; // the interval in seconds between each log
// LED pins
const int dataLedPin = 4; // LED indicating sensor data is received
const int logLedPin = 5; // LED flashes during a log attemp
const int fileLedPin = 6; // LED turns on if a file error occurs
const char *fileName = "logdata.csv"; // the name of the log file
const int logInterrupt = 1; // ATmega 168 and 328 - interrupt 0 = pin 2, 1 = pin 3
const int interruptPin = 3;
volatile unsigned long wattSensor = 0; // Counts power pulses in interrupt, 1 pulse = 1 watt
volatile byte dataState = 0; // used to blink the Led to indicate data updates
unsigned long totalWatts = 0; // Total power used since the sketch started ???
setSyncProvider(RTC.get); // the function to get the time from the RTC
pinMode(dataLedPin, OUTPUT); // LED interrupt indicator initialization
attachInterrupt(logInterrupt, interruptHandler, FALLING);
nextTrigger = now() + logInterval; // schedule the logging time
// initialize the SD card
// initialize a FAT16 volume
// open file for append, create if it doesn't exist
if (!LogFile.open(fileName, O_CREAT | O_APPEND | O_WRITE))
// clear write error
LogFile.writeError = false;
time_t timeStamp = now();
if( timeStamp >= nextTrigger)
// write the data to the card at the end of every line
nextTrigger += logInterval;// schedule the next log time
// blink the LED to show meter pulses
if( digitalRead(interruptPin)== LOW ) // Light the LED when data pin is LOW
delay(100); // light for at least 100 ms
unsigned long wattSensorCount; //number of watts during this logging interval
uint8_t oldSREG = SREG; // save interrupt register
cli(); // prevent interrupts while accessing the count
wattSensorCount = wattSensor; //get the count from the interrupt handler
wattSensor = 0; //reset the watts count
SREG = oldSREG; // restore interrupts
totalWatts = totalWatts + wattSensorCount; //total watts counter
LogFile.print(','); // print comma to seprate from previous data
// routine handle file errors
void error(int err)
// blink forever
delay(err * 200);
void printDateTime(time_t t)
printDigits(second(t),',' ); // uncomment this to print seconds (and replace the comma above with colon)
// print a space here if you need it
// LogFile.print(year(t)); // prints year using 4 digits
LogFile.print(year(t)-2000); // prints year using 2 digits
void printDigits(int digits, char seperator)
// utility function time with leading 0
if(digits < 10)
void interruptHandler() // routine called when external interrupt is triggered
wattSensor = wattSensor + 1; //Update number of pulses, 1 pulse = 1 watt