This project got me interested in what sort of low power consumption might be achievable. I made up a test case with a LLS05-A linear light sensor.

The wiring for that is pretty simple:

// Count light pulses on a light sensor.
// Author: Nick Gammon
// Date: 18 November 2012
#include <avr/sleep.h>
const byte LED = 13;
const byte photoTransistor = 8;
// count of pulses
volatile unsigned long count;
/*
Pin change interrupts.
Pin Mask / Flag / Enable
D0 PCINT16 (PCMSK2 / PCIF2 / PCIE2)
D1 PCINT17 (PCMSK2 / PCIF2 / PCIE2)
D2 PCINT18 (PCMSK2 / PCIF2 / PCIE2)
D3 PCINT19 (PCMSK2 / PCIF2 / PCIE2)
D4 PCINT20 (PCMSK2 / PCIF2 / PCIE2)
D5 PCINT21 (PCMSK2 / PCIF2 / PCIE2)
D6 PCINT22 (PCMSK2 / PCIF2 / PCIE2)
D7 PCINT23 (PCMSK2 / PCIF2 / PCIE2)
D8 PCINT0 (PCMSK0 / PCIF0 / PCIE0)
D9 PCINT1 (PCMSK0 / PCIF0 / PCIE0)
D10 PCINT2 (PCMSK0 / PCIF0 / PCIE0)
D11 PCINT3 (PCMSK0 / PCIF0 / PCIE0)
D12 PCINT4 (PCMSK0 / PCIF0 / PCIE0)
D13 PCINT5 (PCMSK0 / PCIF0 / PCIE0)
A0 PCINT8 (PCMSK1 / PCIF1 / PCIE1)
A1 PCINT9 (PCMSK1 / PCIF1 / PCIE1)
A2 PCINT10 (PCMSK1 / PCIF1 / PCIE1)
A3 PCINT11 (PCMSK1 / PCIF1 / PCIE1)
A4 PCINT12 (PCMSK1 / PCIF1 / PCIE1)
A5 PCINT13 (PCMSK1 / PCIF1 / PCIE1)
*/
ISR (PCINT0_vect)
{
byte sensor = digitalRead (photoTransistor);
digitalWrite (LED, sensor);
if (sensor == HIGH)
count++;
PCICR &= ~_BV (PCIE0); // disable pin change interrupts
} // end of lightOn
void setup ()
{
pinMode (LED, OUTPUT);
// pin change interrupt masks (see above list)
PCMSK0 |= _BV (PCINT0); // pin 8
} // end of setup
void goToSleep ()
{
PCIFR |= _BV (PCIF0); // clear any outstanding interrupts
PCICR |= _BV (PCIE0); // enable pin change interrupts
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_enable();
byte old_ADCSRA = ADCSRA;
// disable ADC to save power
ADCSRA = 0;
// turn off various modules
PRR = 0xFF;
// turn off brown-out enable in software
MCUCR = _BV (BODS) | _BV (BODSE);
MCUCR = _BV (BODS);
sleep_cpu ();
// cancel sleep as a precaution
sleep_disable();
PCICR = 0; // cancel pin change interrupts
PRR = 0; // enable modules again
ADCSRA = old_ADCSRA; // re-enable ADC conversion
} // end of goToSleep
void loop ()
{
goToSleep ();
// do something with results here
}
I put an LED on pin 13 to see if it was working. The code counts when the light comes on (ie. the LED on the power meter flashes). You could add code to check the time (from a RTC chip) and periodically upload the results to somewhere else (after powering up the transmitter).
I measured it taking about 2 uA when asleep, which isn't too bad. Note that the darker it is, the less current drawn by the phototransistor, and thus the less power consumption. So the ideal thing would be for the sensor to be in a meter box with the door shut (or a black cloth over it or something), to keep the light out.
This was tested on a "bare bones" board. No voltage regulator, USB interface or anything like that.
See my page here for tips about turning on external things like clocks, transmitters: http://www.gammon.com.au/power
The simple thing, I think, would be to check the time when it wakes (where I have the comment "do something with results here"). Or maybe even every 5 flashes to keep it even lower consumption. After all, if the meter isn't flashing, you hardly need to upload new results.
Of course, the LED in my test uses power also. I would disconnect that when you are comfortable it is working. When testing, the LED should flash in time with the meter flash.
I tested it at 3V, it worked OK, except I needed to set the "divide clock by 8" fuse bit. The processor isn't rated to run at 16 MHz at 3V. An alternative would be to run from the internal oscillator at 8 MHz (that's OK at 3V) thus saving the need for a crystal or resonator.
2 uA is pretty good, because a AA battery will self-discharge at a somewhat faster rate than that anyway, so the battery is the limiting factor, not the power consumption of the chip.