Monitoring KWh meter : EEM12L-32A

Last Modified: November 30, 2013, at 05:39 AM
By: robtillaart
Platforms: UNO (others not tested)

Warning

This experiment involves high voltage and currents and is therefor dangerous. So:

  • Keep low and high voltage separated
  • Use appropiate insulated cabling for the high voltage part
  • Use appropiate tools for handling the high voltage
  • Be sure to disconnect high voltage before tinkering

Intro

To precisely measure how much energy is used by an appliance one can buy devices that just do that. However it is more fun to explore building such device oneselve with an Arduino, especially because one can export the measured data and do all kind of calculations with them. E.g. monitor how much energy your tropical aquarium is using during the day.

EEM12L-32A

For my experiment I bought the EEM12L-32A KWh Monitoring device, for sale at http://www.conrad.nl (article nr 125348 - 89 ). It can measure power up to 32 Amps @ 230 Volts in steps of 0.5Watt The precision is 1% so well suited for quite precise monitoring power usage.

The device comes with a leaflet explaining its usage. Most important for us is that the device has 6 connectors:

  • two for the Neutral line
  • one for Fase in
  • one for Fase out
  • two puls-lines, potential free optocoupled, one pulse per 0.5 watt = 2000 pulses per KWH

Pulses

The length of the pulses is approx. 50msec so easy for the Arduino to handle.

High - ---+ +---------+ +---
	  | |	      | |
Low  -    +-+	      +-+

In the documentation it is stated that the length of the pulse varies on the power consumption. Although not investigated It would be quite interesting if a formula could be derived.

Connection

The connection between the EEM12L-32A and the arduino board is straightforward. As the EEM12L-32A provides a pulse every 0.5 Watt we should connect it to an interrupt line of the Arduino to collect them. The hardware involves only one resistor, for which I used 10K.

 S+ ------------------------ +5V
 S- -------+---< R1 >------- GND	R1 = 10K 
	   |
	   |
	  IRQ0
        PIN2 arduino		   

Explanation of the Code

An interrupt routine called Kirq() waits for a FALLING signal and the only thing it does is increment a raw pulse counter to keep the routine as short as possible.

In the main loop every second a call is made to a function that calculates the power used since the last call. For this a second counter exists that keeps the old value. As there is one pulse per 0.5 watt I used a float as return type. The calculations are most done in 'pulses' to keep the float operations to a minimum.

Also in the main loop a call is made to a function that just converts the raw pulses to watts. Sort of SUM or TOTAL count.

As counters overflow eventually code is added to the interrupt routine Kirq() and the readKWH() routine to reset both counters after approx. 1e9 pulses. This code is 'shielded' by a simple Critical Section construction to prevent a reset when calculating watts. Note that my assumption here is that irq's are handled atomically on the Arduino, I don't know this. If not there could be one misread in 1e9 pulses == 500.000 KWh. For a small experiment quite acceptable :)

Results

My first test with a 100Watt light bulb gave one pulse every 18 seconds. This equals 1 watt every 36 seconds = 100Watt in an hour, so it worked!

Enjoy tinkering,
rob.tillaart@removethisgmail.com

CODE

/*
 *    FILE: KWh monitoring
 *  AUTHOR: Rob Tillaart
 *    DATE: 2010 03 31 
 *     URL: http://playground.arduino.cc/Main/EEM12L-32AKWhMonitoring
 *
 * PURPOSE: prototype KWh monitoring  
 *
 * Digital Pin layout ARDUINO
 * =============================
 *  2     IRQ 0    - to KW meter EEM12L-32A 
 *
 * This KWh meter gives a pulse every 0.5 Watt
 */

//
// KWH SENSOR CODE
//
// TODO - make a class
//
volatile unsigned long rpk = 0;               // raw pulse KWH counter (private)
volatile unsigned long rpk_old = 0;           // value of last read (private)
volatile boolean CS_KWH = false;              // Critical Section for KWH meter (private)

// The interrupt routine
void Kirq()
{
  rpk++;                    // just increment raw pulse counter.
  if (rpk > 1000000000)     // reset pulse counter after 10e9 pulse = 500.000 KW 
  {
    if (false == CS_KWH)    // in critical section?  // assumption IRQ-call is handled atomic on arduino.
    {
      rpk -= rpk_old;
      rpk_old = 0;
    }
  }
}

// returns KWH's since last reset
float readKWH1()
{
  return rpk/2000.0;       // one pulse = 0.5 watt.
}

// returns KWH's since last call
float readKWH()
{
  CS_KWH = true;           // Start Critical Section - prevent interrupt Kirq() from changing rpk & rpk_old ;
      long t = rpk;            // store the raw pulse counter in a temp var.
      long k = t - rpk_old;    // subtract last measure to get delta
      rpk_old = t;             // remember old value
  CS_KWH = false;          // End Critical Section
  return k/2000.0;         // return delta, one pulse = 0.5 watt.
}

//
// SETUP
//
void setup() 
{
   Serial.begin(9600);

  // KWH interrupt attached to IRQ 0  = pin2
  attachInterrupt(0, Kirq, FALLING);
}

//
// MAIN LOOP
//
void loop() 
{
    delay(1000);
	float KWH = readKWH();
	float SUM = readKWH1();
	Serial.print("KWH: ");    
	Serial.print(KWH, 4);
	Serial.print("    ");
	Serial.println(SUM, 4);
}

//
// END OF PROGRAM
//

Share