Pulse counter with Energy Meter EM23

Hi,

I have a Carlo Gavazzi EM23 Din Energy Meter and I’m reading it’s pulses but getting incorrect readings.
No matter how I initialize the pinMode and attachinterrupt, the readings are not what they are supposed to be.
EM23 is showing around 5 to 8 kWh, and I am pushing to the cloud pulses at 10 seconds interval. I should of see around 8 to 15 pulses in this interval.
Depending on the way I set up pins I either get 0, 1 or ~400 pulses in 10 seconds (and not 8 to 15).

Here are the severam pinModes I tried and the pulse count in 10 seconds:
pinMode(D1, INPUT_PULLUP); //Returns 0 in 10 seconds
pinMode(D1, INPUT_PULLDOWN); //Returns 1 in 10 seconds
pinMode(D1, INPUT); //Returns 100 to 400 in 10 seconds

According to [EM23 datasheet][1]
“Pulse output: 1 output 100 pulses per kWh. Type: output connectable to the energy meter (kWh). Pulse duration >= 100ms <120msec (ON), >=120ms (OFF), according to EN62052-31."

Here is my partial code

#define READFREQUENCY 10000  // milliseconds

setup()
{
...
    // EM23 Din Energy Meter
            pinMode(D3, INPUT); 

            attachInterrupt(D3, PulseCounter, FALLING) ;
}

void loop()
{
...
    elapsedMillis=millis()-readlooptimestamp;
    if (elapsedMillis >= READFREQUENCY) {
        readlooptimestamp = millis();
        
            // D3 EM23 Din Energy Meter
            if (count[D3]>=0) {
                success = Particle.publish("librato_D3", String(count[D3]));
  
                
                count[D3]=0;
 
                
            }   
  }
  delay(500);
}

void PulseCounter(void)
{
	detachInterrupt (D3) ;
	count[D3]++;
	attachInterrupt(D3, PulseCounter, FALLING) ;
}

Any help understanding what is happening is appreciated.

Where can we see your declaration of count[]?
Make sure to have it declared volatile.

With the pulse rate you are looking at you won’t need (and should not) detachInterrupt().

Without looking at the meter datasheet (since there is no link) I’d guess it provides a discrete signal for HIGH and LOW, so you should not need a pull resistor.

You might also only reset your count when the publish succeedes.


I found a datasheet showing the suggested wiring (page 7)
But with this, I’d recommend using a pull-resistor that fits your wiring.

How does your wiring look?

Hi,
Thanks for reply and suggestion.

I am using 3-ph, 4 wire diagram shown on that datasheet.

I’ using volatile in the var declaration, and took away the detachInterrupt() but still results vary from 150 to 400…

volatile int count[24];

This is the mains wiring (page 6), but I actually asked for your signal wiring (page 7).

Just out of interest, are you actually counting 24 individual inputs?

Hi, Thanks again.
I’m using ground reference / open collector.

41 is connected to D2
42 is connected to 3V3

No, I am not using 24 individual inputs on this project. The array was generic for another purpose, thus the 24.

Looks like an interesting project.

If you’ve set it up as ground reference as shown on page 7, then don’t you also need a pull down resistor (‘Rc’), or D3 should be set pulled down? I wonder whether the reason you’re getting too many pulses when you don’t have pullup or pulldown is that the wire connected to D3 is acting as an aerial when the open collector is open.

You don’t need the “(count[D3]>=0)” clause because it will always be zero or more. That won’t solve your problem but anything that reduce the number of lines of code is always good :smile:

You say that the meter is showing around 5 to 8 kWh. The unit ‘kWh’ is a amount of energy consumed rather than a rate of energy. I think you might mean 5 to 8 kilowatts?

If you are consuming at a rate of 5 kilowatts, then in one hour you will have consumed 5kWh of energy. The meter should send 5 * 100 pulses (the specification says “100 pulses per kWh”); that’s 500 pulses in 3600 seconds or about 1.4 pulses per ten seconds. Perhaps it’s working correctly when you have D3 set to pulldown?

Someone else please check my calculations :smile:

In this case you'd need

  pinMode(D2, INPUT_PULLDOWN); // or use ext pull-down with INPUT
  attachInterrupt(D2, PulseCounter, RISING);

But in your code you have written D3! Is this or D2 a typo?

Also, in order not to miss any (or at least less) count I'd swap round the logic here (assuming D3 to be the pin)

...
    if (elapsedMillis >= READFREQUENCY) {
        readlooptimestamp = millis();
        int cnt = count[D3];
        count[D3] = 0;
        success = Particle.publish("librato_D3", String(cnt));
    }   
...
void PulseCounter(void)
{
  count[D3]++;
}

This way there is less chance that there will be a pulse between using the last count and resetting the counter, as a register transfer will be quicker than multiple function calls (which would be otherwise).

Also reconsider the use of an array element for your counter.
When set in an ISR a var has to be declared volatile but having a whole array declared volatile just because of one element being used in an ISR seems unnecessary and handicaps code optimization.

BTW: How long are your signal wires?

Hi,
In the last reply, D2 was a typo. I meant D3.

The device has a visual led that shows each time there is a pulse. It is only on once every 1 or 2 seconds so I’m not really concerned with concurrency issues.

The pulses readings still do not make sense as they vary from 1 to 4 and are independent of energy use :frowning:

There is still something in the wiring or code …
The length of wire is less than a meter.
Here is my code:

   // This #include statement was automatically added by the Spark IDE.
#include "elapsedMillis/elapsedMillis.h"

#define TIMEOUT 250 // milliseconds
#define READFREQUENCY 10000  // milliseconds

volatile int PulseCounter;
unsigned long readlooptimestamp = 0;
unsigned long elapsedMillis = 0;
bool success;
    

// This routine runs only once upon reset
void setup()
{
	PulseCounter=0; 
      
            
   pinMode(led1, OUTPUT);
        
   // EM23 Din Energy Meter
   pinMode(D3, INPUT_PULLDOWN); 
   attachInterrupt(D3, PulseHandler, RISING) ;
}

void loop()
{
    String data;
    char payload[255];
    
    elapsedMillis=millis()-readlooptimestamp;
    if (elapsedMillis >= READFREQUENCY) {


        readlooptimestamp = millis();
	
		// D3 EM23 Din Energy Meter
		if (PulseCounter>=0) {
			success = Particle.publish("librato_D3", String(PulseCounter));
			if (success) {PulseCounter=0;}
		}   
		
     } 
     delay(500);
}

void PulseHandler(void)
{
	PulseCounter++;
}

[quote=“tiagonmas, post:8, topic:19816”]
I’m not really concerned with concurrency issues.
[/quote] This is not good practice. Copying the value of PulseCounter prior to using it IS good practice. I believe you want to publish if PulseCounter is > 0, not >= 0, no? You may want to make PulseCounter an unsigned int since it will never be a negative value.

Also, you can clean up your timer code a bit:

    if (millis()-readlooptimestamp >= READFREQUENCY) {
        readlooptimestamp = millis();
	// D3 EM23 Din Energy Meter
        unsigned int cnt = PulseCounter;
	if (cnt >0) {
		success = Particle.publish("librato_D3", String(PulseCounter));
		if (success) {PulseCounter=0;}
	} 

Note that the delay(500) in loop() means the timing will only be accurate to 500ms. Finally, with “wire length less than a meter”, the internal pull-down may be too weak. I recommend using a stronger external pull-down (4.7K to 10K) coupled with a 0.1uF capacitor (to ground) to eliminate noise on the wire. Long wires act like antennas and can be a source of frustration. The resistor/cap combination will act as a debounce (of sorts) and slow the rise time to ensure you have a clean signal. :grinning:

1 Like