Arduino Electricity Monitor

Arduino Electricity Monitor

I’ve had my eye on some of the commercially available home energy monitors for a while. They all utilise a current transducer that clips or clamps around the main cable coming into the house. I wasn’t too keen on these, as in order to correctly, and accurately, measure the current flowing, you need to accurately know the voltage too. Without making serious modifications to the supply cabling, this isn’t possible. Making changes to the supply cabling is pretty dangerous and not to mention, very illegal.

However, those of us lucky enough to have a modern, digital electricity meter, may have spotted an LED on the front that flashes whenever a certain amount of electricity has been consumed. In my case, it flashes 1000 times per kWh, which is once per Wh.

I found an excellent Arduino sketch over at openenergymonitor.org that counts these pulses from the meter. There’s a very simple circuit feeding 5v to an LDR which is sitting in one half of a voltage divider. The output of this voltage divider is then wired to pin1 on the Arduino. Of course, pin1 supports interrupts, so we can get the Arduino to do something whenever that interrupt happens.

As it’s a ‘normal’ LDR and not limited to infra-red or anything, I needed to shield it from ambient light. If someone switched the light on, we’d probably get an errant pulse being recorded. The first thing that sprung to mind when I saw the size of the disc surrounding the LED on the meter was the small canisters 35mm photographic film comes in (remember that lovely stuff?!) So i dug one out and cut a hole in the base for the cable. Perfect fit. I need to fashion some kind of more robust bracket, probably involving velcro and strips of aluminium at some point. For now Blu-Tack will just about do.

elecmeter_canister

I’ve modified the code to include parts of the standard ‘web client repeating’ sample sketch. I want to be able to log the data in a mySQL database so that I can graph it and do further analysis on it later. So the Arduino posts the measurements whenever there is a pulse to a PHP script that then inserts everything into a database.

There are a number of issues with this script as it stands. If I change the value in the ‘power’ equation (towards the bottom of the code), it breaks the script. With the numbers as they are, I get figures in the region of 600kWh, which is more like a small factory, rather than a domestic dwelling! For now, I’ve done a division in the PHP script to get this number to something more realistic. I need to get my maths head on, and do some thinking.

The other problem is that the Arduino seems to stop after a few hours. I can’t wok out what’s causing it. It’s powered up and the network lights flash in unison on the Ethernet Shield, network switch and Raspberry Pi (that’s where the PHP script is). But nothing is appearing in the database…

Anyway, feel free to use this code, but please let me know of any improvements or changes you make.

 

#include <SPI.h>
#include <Ethernet.h>

//Adapted from a sample Arduino sketch and openenergymonitor.com, by chris at tinkerfailure.com

// assign a MAC address for the ethernet controller.
// fill in your address here:
byte mac[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
// fill in an available IP address on your network here,
// for manual configuration:
IPAddress ip(192,168,xx,xx);

// fill in your Domain Name Server address here:
IPAddress myDns(8,8,8,8);

// initialize the library instance:
EthernetClient client;

char server[] = "192.168.xx.xx";

unsigned long lastConnectionTime = 0;          // last time you connected to the server, in milliseconds
boolean lastConnected = false;                 // state of the connection last time through the main loop
const unsigned long postingInterval = 60*1000;  // delay between updates, in milliseconds

//Number of pulses, used to measure energy.
long pulseCount = 0;   

//Used to measure power.
unsigned long pulseTime,lastTime;

//power and energy
double power, elapsedkWh;

//Number of pulses per wh - found or set on the meter.
int ppwh = 1; //1000 pulses/kwh = 1 pulse per wh

void setup()
{
  Serial.begin(115200);

  // give the ethernet module time to boot up:
  delay(1000);
  // start the Ethernet connection using a fixed IP address and DNS server:
  Ethernet.begin(mac, ip, myDns);
  // print the Ethernet board/shield's IP address:
  Serial.print("My IP address: ");
  Serial.println(Ethernet.localIP());

  // KWH interrupt attached to IRQ 1 = pin3
  attachInterrupt(1, onPulse, RISING);
}

void loop() {
  // if there's incoming data from the net connection.
  // send it out the serial port.  This is for debugging
  // purposes only:
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if there's no net connection, but there was one last time
  // through the loop, then stop the client:
  if (!client.connected() && lastConnected) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
  }

  // if you're not connected, and ten seconds have passed since
  // your last connection, then connect again and send data:
  if(!client.connected() && (millis() - lastConnectionTime > postingInterval)) {
    httpRequest();
  }
  // store the state of the connection for next time through
  // the loop:
  lastConnected = client.connected();
}

// this method makes a HTTP connection to the server:
void httpRequest() {
  // if there's a successful connection:
  if (client.connect(server, 80)) {
    Serial.println("connecting...");

// prepare the variables  
  char powerString[8] = "";
  char elapsedString[8] = "";
  //convert to strings  
  dtostrf(power, 7, 4, powerString);
  dtostrf(elapsedkWh, 4, 3, elapsedString);
  String valueOne = powerString;
  String valueTwo = elapsedString;
  //assemble query  
  String stringOne = "GET /energymonitorscript.php/?power=";
  String stringTwo = "&elapsed=";
  String stringThree = " HTTP/1.0 \r\n";
  String stringOut = stringOne + valueOne + stringTwo + valueTwo + stringThree; 

    // send the HTTP PUT request:
    client.println(stringOut);
    client.println("User-Agent: arduino-ethernet \r\n");
    client.println("Connection: close \r\n");
    client.println();

    // note the time that the connection was made:
    lastConnectionTime = millis();
  } 
  else {
    // if you couldn't make a connection:
    Serial.println("connection failed");
    Serial.println("disconnecting.");
    client.stop();
  }
}

// The interrupt routine
void onPulse()
{

//used to measure time between pulses.
lastTime = pulseTime;
pulseTime = micros();

//pulseCounter
pulseCount++;

//Calculate power
power = (3600000000.0 / (pulseTime - lastTime))/ppwh;

//Find kwh elapsed
elapsedkWh = (1.0*pulseCount/(ppwh*1000)); //multiply by 1000 to pulses per wh to kwh convert wh to kwh

//Print the values.
Serial.print(power,4);
Serial.print(" ");
Serial.println(elapsedkWh,3);

//make the http request
httpRequest();
}