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 Sensor:

The TSL261 Light to Voltage sensor looks like this:

TSL261

 

 

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

 

 

 

 

 


The LEDs:

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:

 Electricity_logger2


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.

meter1

meter2


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:

 spreadsheet

Pretty good - but even better if you graph it out in your spreadsheet:

log

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.

The Sketch:

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 <Wire.h> 
#include <Time.h> 
#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;

SdCard card;
Fat16 LogFile;

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 ???

time_t nextTrigger;


void setup(void)
{
  setSyncProvider(RTC.get);   // the function to get the time from the RTC

  pinMode(dataLedPin, OUTPUT);    // LED interrupt indicator initialization
  pinMode(logLedPin, OUTPUT);     
  pinMode(fileLedPin, OUTPUT); 

  pinMode(interruptPin, INPUT);    
  digitalWrite(interruptPin, HIGH);  
 
  attachInterrupt(logInterrupt, interruptHandler, FALLING); 
  nextTrigger = now() + logInterval; // schedule the logging time
 
  // initialize the SD card
  if (!card.init())
     error(1);
 
  // initialize a FAT16 volume
  if (!Fat16::init(&card))
      error(2);

  // open file for append, create if it doesn't exist 
  if (!LogFile.open(fileName, O_CREAT | O_APPEND | O_WRITE))
      error(3);
 
  // clear write error
  LogFile.writeError = false;
  LogFile.println("Start");
}

void loop(void)

  time_t timeStamp = now(); 
  if( timeStamp >= nextTrigger)
  {
     digitalWrite(logLedPin, HIGH);
     printDateTime(timeStamp);
     MeterPulseLog();
     LogFile.println();
    // write the data to the card at the end of every line
     if (!LogFile.sync())
        error(4);
       
     nextTrigger += logInterval;// schedule the next log time       
     digitalWrite(logLedPin, LOW);
  }
  // blink the LED to show meter pulses
  if( digitalRead(interruptPin)== LOW ) // Light the LED when data pin is LOW
  {
    digitalWrite(dataLedPin, HIGH);   
    delay(100);  // light for at least 100 ms
  }
  else
     digitalWrite(dataLedPin, LOW); 
}

void MeterPulseLog()
{
    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
    LogFile.print(wattSensorCount);
    LogFile.print(',');
    LogFile.print(totalWatts);       
}

// routine handle file errors
void error(int err)
{
  // blink forever
 while(1)
 {
   digitalWrite(fileLedPin, HIGH);
   delay(err * 200);
   digitalWrite(fileLedPin, LOW);
   delay(200); 
 }    
}

void printDateTime(time_t t)
{
  printDigits(hour(t),':' );
  printDigits(minute(t),':' );
  printDigits(second(t),',' );  // uncomment this to print seconds (and replace the comma above with colon)
  // print a space here if you need it
  printDigits(day(t),'//' ); 
  printDigits(month(t),'//' );  
//  LogFile.print(year(t));  // prints year using 4 digits
  LogFile.print(year(t)-2000);  // prints year using 2 digits
  LogFile.print(',');
}

void printDigits(int digits, char seperator)
{
  // utility function time with leading 0
  if(digits < 10)
    LogFile.print('0');
  LogFile.print(digits);
  LogFile.print(seperator); 
}

void interruptHandler() // routine called when external interrupt is triggered
{
  wattSensor = wattSensor + 1;  //Update number of pulses, 1 pulse = 1 watt
}

3.8/5 rating (6 votes)

Comments (14)

  • xan
    14 April 2011 at 13:45 |

    Hi,

    This example has been really useful; I've been working on making my own device to do the same thing!

    I'm trying to run mine off a LiPoly battery however and it doesn't live for very long (~10 hours). I was wondering if you or anyone else knows if there's a sensible way to get the arduino to go to sleep or into a power saving mode between LED pulses?

    Cheers.

    • Administrator
      26 October 2011 at 18:27 |

      Hi, I hope to have a new version of the Energy Monitor out soon - it runs on Lipo using sleep code so might be useful for you? Stay tuned :-)

      • Bob Axford
        07 January 2012 at 16:26 |

        I am looking for an energy monitor like described here - you said a new one will be out soon, any idea when? thanks.

        • Administrator
          10 February 2012 at 21:57 |

          Hi Bob, Sorry for the slow reply - I hope to have the project up on the website this month, all being well.

          • Administrator
            11 March 2012 at 22:31 |

            Hi, A quick note to say that I finally have the MKII Energy Monitor project published - hope it helps & sorry for the delay.

  • 12 April 2011 at 19:07 |

    Hi, based on this blog I made a solar meter. I made some enhancements. First of all, the clock on my Arduino seems to shift rapidly. So, I included an NTP sync function that syncs time every hourm (I stacked an Ethernet shield for this purpose). Second, instead of storing the data on an SD card, I upload the data every hour to my Apache server through a Perl script, so I can monitor output in real time graphically through a web page. Everything is running without errors for 2 months now. Thank you very much for putting me on the right track with your blogpost!

    • Hugo
      20 April 2012 at 18:22 |

      Hello Sander,

      I have also made an Arduino script for an energy logger. The script writes directly to a SD-card and is also sending it, at the same time, to PHP. The PHP script is saving the data in a MySQL DB.
      When I shutdown my PC (server) then the logging doesn’t work anymore.

      The data logging is still working on my SD Card. Do you know if there is a method that can send the CSV file to my pc (With HTTP POST, GET or over TCP/IP)?

      In your post I read that you can send the data with an interval of 1 hour. How do you first store the information on a SD-card and then send this later to your computer?

      I hope you can help me, or maybe you can send me your script?

      Best Regards, Hugo

    • AndyH
      08 September 2011 at 17:00 |

      Hi Sander,

      I am very interested in getting an Ethernet shield for my setup but would really appreciate any help from someone who has done it. Could you advise how you got everything up and running? The PERL script you wrote would also be very useful as I'd rather upload to my server than use an SD card. Your help would be much appreciated.

  • Polidano
    17 February 2011 at 07:42 |

    If i would like to connect this.. to a display.. would it be easy? I was going to opt for something like this display
    http://openenergymonitor.org/emon/node/45#comment-1547
    but for that display i will be using the arduino mega.. so can I connect all of the above with that arduino and connect the display with it also??

  • J.F. van den Berg
    02 February 2011 at 06:48 |

    Problem solved!!

    Just add this two lines in de sketch and it works perfect!

    // the next two lines can be removed if the RTC has been set
    setTime(17,05,0,1,3,10); // set time to 17:05:00 1 Mar 2010
    RTC.set(now()); // set the RTC to the current time (set in the previous line)

  • Jeroen van den Berg
    27 January 2011 at 10:56 |

    Very nice, and good working Seeeduino.
    I only have some problems with the date and time.
    Thay start every time with all zero's.
    Hoe do i get the actual date and time on this postions?
    Can anyone give me some more information about this problem?

  • Harry
    11 January 2011 at 18:57 |

    Thank you - a very useful sketch. I've just got it up & running, and am looking forward to see my graphs.
    2 points worth mentioning.
    1/ I could only compile using the downloaded version of fat16 "fat16lib20100818", the later versions show errors when compiling.
    2/ the downloaded .pde is missing a "/" in the opening line - the version in the windows above is correct.

    Hope that helps someone - its a good project to start off on.


    Cheers - Harry

  • Cameron
    08 January 2011 at 12:14 |

    Hi, I use Excel for post processing but I expect there are plenty of other options available including free ones like OPEN OFFICE.

  • Malcolm Trundle
    06 January 2011 at 12:28 |

    Hi, Just ordered your energy monitor.
    Which SW were you using to produce the graphs from the spreadsheets in the example ?

    Regards M.Trundle

Leave a comment

Please login to leave a comment.