Energy Monitor Proof of Concept

igoogle-pachube

The Arduino is now connected to a photoreceiver that I got at Ax-Man for $0.95, picking up IR pulses every watt-hour of usage! 

arduino-power

Since Google Powermeter still has no open API, I am uploading data to pachube.com – but they have an iGoogle plugin so Google doesn’t have to feel too bad (Hi Mike!).  I’m sure they’ll carry on without me for now.  It’s working pretty well but it’s all duct tape, chewing gum and baling twine, and you may notice a flat spot on the screenshot; the photoreceiver doesn’t work when the sun shines on the meter during the day.  Not sure how to fix that even with various shading I put over it.  Still, kind of interesting.  I’m updating pachube every 20s.  They have a pretty cool API where you can generate all sorts of type of graphs, besides the ugly pink ones:

power_history

Russell ordered some current transformers [amzn] to play with, which at least won’t be exposed to the elements; I may get a 2nd Arduino for that experimentation because I’d like this logging to keep going if I can.  So far there is strong-ish incentive to run around turning off lights to make the graph go down, but I suppose that will wear off…

Arduino code follows; it ain’t pretty but it works.  It listens on the serial port for a “p” (power) and sends the avg power over all the pulses since the last query.  Right now my mac is running crummy perl to poke the arduino board and upload the data to pachube with curl.

As I said, chewing gum and duct tape…

//
// Use interrupt to detect change on IR phototransistor
//
// So we know what's up, light up the built-in LED
//

// PIN DEFINITIONS
int led_pin = 12;              // Display LED pin
int int0_pin = 2;              // Interrupt 0 on pin 2, input

// Delays
int bounce_delay_ms = 100;     // pulse is 10ms wide
int blink_delay_ms = 100;      // LED on time; delays loop()

unsigned long counter = 0;      // Nr of pulses seen
unsigned long first_pulse_time = 0;
unsigned long last_pulse_time = 0;

// These are modified in the interrupt
volatile int pulse_seen = 0;   // Pulse was seen in interrupt

static unsigned long ms_per_hour = 3600000UL;  // ms per hour for power calcs

void setup()
{
 pinMode(led_pin, OUTPUT);

 // We want internal pullup enabled:
 pinMode(int0_pin, INPUT);
 // digitalWrite(int0_pin, HIGH);  // Turns on pullup resistors

 // And set up the interrupt.
 // RISING: -pin- goes from low to high
 // When IR detected, Axman detector emits 5V
 attachInterrupt(0, blink, RISING);
 // initialize serial communication:
 Serial.begin(9600);
}

void loop()
{
 static unsigned long avg_watts;        // average watt draw since startup
 unsigned long delta;            // Time since last interrupt
 int incoming_byte;

 // Query exists on serial port; service it.
 if (Serial.available() > 0) {
   incoming_byte = Serial.read();
   Serial.flush();
   switch (incoming_byte) {
   case 'c':
     // Just print the count since last query
     Serial.println(counter);
     counter = 0;
     break;
   case 'p':
     // print the avg watt draw since last query
     delta = last_pulse_time - first_pulse_time;
     if (delta && counter) {
       avg_watts = (counter - 1) * ms_per_hour / delta;
       counter = 0;
     }
     Serial.println(avg_watts);
     break;
   default:
     break;
   }
 }

 // IR pulse interrupt happened
 if (pulse_seen == 1) {
   counter++;

   last_pulse_time = millis();

   if (counter == 1 || first_pulse_time == 0) // we were reset
     first_pulse_time = last_pulse_time;

   // Blinky-blink
   digitalWrite(led_pin, HIGH);
   delay(blink_delay_ms);
   digitalWrite(led_pin, LOW);
   // Reset until next one.
   pulse_seen = 0;
 }
}

// Interrupt handler
// Whenever we get an IR state change our LED should change too.
//
// We get here for RISING; so when IR turns on.
//
void blink()
{
 static unsigned long last_interrupt_time = 0;
 unsigned long interrupt_time = millis();

 // If interrupts come faster than bounce_delay_ms, assume it's a bounce and ignore
 //
 // Note, millis() wraps every 50 days, be sure we cope...
 //
 if (interrupt_time - last_interrupt_time > bounce_delay_ms)
   pulse_seen = 1;  // loop() sees pulse == 1 and takes action

 last_interrupt_time = interrupt_time;
}

3 thoughts on “Energy Monitor Proof of Concept

  1. Hello Eric,

    This is great. Thank you for sharing this. When I found this post yesterday, I ran out the Radio Shack to pick up a photo-transistor, as I had all the other hardware and didn’t want to wait for my monthly parts order.

    I’ve never fiddled, with IR sensors before and was surprised to see how sensitive it was to just about any light source I exposed it to. In the near future I plan to order an assortment of infrared sensitive components to see if I can enhance things.

    Do you have any tips or techniques for how to attach / mount an IR sensor to an electric utilities “smart meter”? The smart meters my utility deployed have the IR emitter diode on the (round) face of the meter at the 12 o’clock position, just above the LCD readout.

    Best regards,

    Steve

    • Hey Steve, sorry for the late reply. I really rigged mine in a crazy way, with zip-ties, foam, pipe-end caps, and a rubber roof membrane to build a shade/hood. Without that, sunlight made it fail during the day. Maybe some putty to stick it to the face, but I dunno.

      Some utilities may get antsy if they see stuff stuck to their meter though, just a fair warning. If your meter is “smart” enough maybe you can read it with something more sophisticated?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Notify me of followup comments via e-mail. You can also subscribe without commenting.