I am struggling to get my powermeter to work. I taped a light sensor in front of the blinking red led diode on my powermeter.
Here is my code:
/*
Part 5 – Pulse counting
Many meters have pulse outputs, including electricity meters: single phase, 3-phase,
import, export.. Gas meters, Water flow meters etc
The pulse output may be a flashing LED or a switching relay (usually solid state) or both.
In the case of an electricity meter a pulse output corresponds to a certain amount of
energy passing through the meter (Kwhr/Wh). For single-phase domestic electricity meters
(eg. Elster A100c) each pulse usually corresponds to 1 Wh (1000 pulses per kwh).
The code below detects the falling edge of each pulse and increment pulseCount
It calculated the power by the calculating the time elapsed between pulses.
Read more about pulse counting here:
http://openenergymonitor.org/emon/buildingblocks/introduction-to-pulse-counting
-----------------------------------------
Part of the openenergymonitor.org project
Licence: GNU GPL V3
*/
long pulseCount = 0;
unsigned long pulseTime,lastTime; // Used to measure time between pulses
double power;
int ppwh = 1; // pulses per watt hour - found or set on the meter.
void setup()
{
Serial.begin(9600);
// pulse detection interrupt (emontx pulse channel - IRQ0 D3)
attachInterrupt(1, onPulse, FALLING);
}
void loop()
{
Serial.print(power);
Serial.print(' ');
Serial.println(pulseCount * ppwh); // watt hour elapsed
delay(1000);
}
// The interrupt routine - runs each time a falling edge of a pulse is detected
void onPulse()
{
lastTime = pulseTime;
pulseTime = micros();
pulseCount++; // count pulse
power = int((3600000000.0 / (pulseTime - lastTime))/ppwh); // calculate power
}
However it seems like the output goes in overflow or something or?
Please supply a circuit of how you have wired the sensor.
You could write a simple program to blink a LED each time the power meter LED blinks. This would show if it is electronics or programming causing the problem.
Judging by the printout I suspect you are getting some kind of noise on your edge detection such that you get several interrupts for each genuine pulse. You will see that the pulsecount never advances by 1. This will generate very small intervals leading to overflowing the power calculation.
If your meter has a display of kwh then you can record that value at a particular time, run your program for a few hours then read the kwh value again. Compare the pulse count with the displayed kwh figure and see if it compares to your assumed pulse rate- my guess you will find 3 or 4 times as many pulses as you expect.
If this turns out to be the case you can address it either in hardware by putting a small capacitor in the circuit to smooth the signal or in software by calculating (pulsetime-lasttime) and rejecting any values below a threshold.
Its best practice to do the minimum possible in your interrupt routine so you should try to move the calculations back into the main loop. (see the Doing several things at once topic for how to do without delay(). You should also use the volatile keyword on the variables you update in the interupt (https://www.arduino.cc/en/Reference/Volatile)
As each pulse is a fixed amount of energy, surely you only need to count pulses. What use is the length of the pulse or time between pulses?
At a load of 1kw, you would get 1000 pulses per hour (assuming that is your meter pulse rate), or, 1 every 3.6 secs. There is a lot of computer time between pulses.
In the interrupt, you only need to return the fact that the pulse has happened. The main loop then counts and displays.
The link takes us to a page full of sensors. Which one are you using?
To be precise, you are counting pulses that represent energy, not power. Power is an instantaneous value, while energy takes into account the time.
Your submitted code has numerous issues, which is why I submitted test code using a built-in pulse generator. Now I've updated it to do a self-test (jumper wire from pin 13 to pin 3) or an on-site test (pin 3 connected to your optic sensor). See reply#4.
Well, that's probably the wrong type of sensor for your application. A photo-resistor has a slow response (perhaps up to 50ms) depending on the type of light and its level. Some types of electricity meters will output an impulse on its IRLED output, which can have a small ON interval as short as 2ms. This is to extend its lifespan.
Anyways, perhaps your meter has a pulse interval that has an adequate ON duration. The ON duration will be due to the electronic design and firmware of the meter, the pulse rate will be determined by the load.
You could test for operation of the meter's infrared LED by using a phone camera or digital camera and check for a visible blink on the screen.
To adjust the LDR, turn the pot until point where the signal just switches HIGH. Turn it just a very, very small amount more. When the meter's IRLED blinks, the LDR might respond by switching its output LOW (for the duration that the meter's IRLED is ON. The normal state of the LDR's output will be HIGH.
Similar to dlloyd I tested your code with a signal generator and saw very predictable pulse count changes.
I would be focusing on the sensor and signal produced. It was mentioned in reply#2
Judging by the printout I suspect you are getting some kind of noise on your edge detection such that you get several interrupts for each genuine pulse
The LDR sensor module is just using a LM393 comparator without the feedback used for hysteresis control in a Schmitt trigger configuration and it may be noisy.
Your code, as submitted generates an interrupt on each edge of an input signal, probably because volatile isn't being used for interrupt variables. Also, it only calculates an integer value and it only reads 1/2 power due to the extra interrupt. Also, the code should also limit power calculations to the pulse rate range of the meter ... 0Hz to 5Hz. Also, 0Hz should not overflow the timer and negative readings should not occur. Calculations should not be made in the interrupt routine.
Here, I've taken your code (unaltered) that shows the problems I've mentioned. Look at the Arduno's LED and look at the tx LED and print monitor readings. Extra lines for pulse generator are marked with //***********. Just place a jumper from pin13 to pin3.
/*
Part 5 - Pulse counting
Many meters have pulse outputs, including electricity meters: single phase, 3-phase,
import, export.. Gas meters, Water flow meters etc
The pulse output may be a flashing LED or a switching relay (usually solid state) or both.
In the case of an electricity meter a pulse output corresponds to a certain amount of
energy passing through the meter (Kwhr/Wh). For single-phase domestic electricity meters
(eg. Elster A100c) each pulse usually corresponds to 1 Wh (1000 pulses per kwh).
The code below detects the falling edge of each pulse and increment pulseCount
It calculated the power by the calculating the time elapsed between pulses.
Read more about pulse counting here:
http://openenergymonitor.org/emon/buildingblocks/introduction-to-pulse-counting
-----------------------------------------
Part of the openenergymonitor.org project
Licence: GNU GPL V3
*/
#include <TimerOne.h> //***********
long pulseCount = 0;
unsigned long pulseTime, lastTime; // Used to measure time between pulses
double power;
int ppwh = 1; // pulses per watt hour - found or set on the meter.
int led = LED_BUILTIN; //***********
volatile int ledState; //***********
void setup()
{
Timer1.initialize(1000000); // µs/pulse (1000000 = 3600 Watts) //***********
Timer1.attachInterrupt(testPulse); //***********
pinMode(led, OUTPUT); //***********
Serial.begin(9600);
// pulse detection interrupt (emontx pulse channel - IRQ0 D3)
attachInterrupt(1, onPulse, FALLING);
}
void loop()
{
Serial.print(power);
Serial.print(' ');
Serial.println(pulseCount * ppwh); // watt hour elapsed
delay(1000);
}
// The interrupt routine - runs each time a falling edge of a pulse is detected
void onPulse()
{
lastTime = pulseTime;
pulseTime = micros();
pulseCount++; // count pulse
power = int((3600000000.0 / (pulseTime - lastTime)) / ppwh); // calculate power
}
void testPulse(void) //***********
{ //***********
ledState = !ledState; //***********
digitalWrite(led, ledState); //***********
} //***********
The good results are coming in with proper resolution. The extra interrupts are due to noise that is probably combined with some mains frequency ripple on the signal.
rw950431 (reply#2) and cattledog (reply#10) were correct in their suggestions.
Editing the code managed to resolve some issues. The extra speed is evident in the extra interrupts being serviced. The 300000000.00 power reading corresponds to 12µs elapsed time. The longest spacing between good results was 90µs. Note that the 12µs is probably the quickest the Arduino can service the interrupt routine as this corresponds to 83KHz interrupt frequency.
This can be resolved with software debounce code, however this does not stop the interrupts from occurring ... it just changes how the software responds to them.
Hardware filtering will stop the extra interrupts (I suggest this method), which would be as simple as adding an RC filter to the signal. Calculated from here, if you use a series 10K resistor with 100nF capacitor connected from pin3 to GND, the response (RC time constant) would be 1ms.
EDIT: It doesn't have to be one or the other method ... both could be used where the noise component is filtered in hardware and interrupts due to mains ripple are resolved with debounce code.
It was very easy to add debounce to your onPulse() interrupt routine (the required variables are already there) so I've added 500µs debounce to the code in reply#4. Please test. Hardware filtering not required.
Just got home from sailing, but I see what you mention. I will try adjust the potentiometer and I can also test with an IR receiver that I have around.
I will also test the software debounce code. I just read that people used LDR for power measurement thats why I got that kind of sensor.
When I did this I used a cheap LDR (cant remember the part number but the kind that sells for a few cents each on ebay) and pullup resistor stuck on to my meter with blu-tack. My interrupt code used CHANGE rather than FALLING mode and didnt seem to experience any of the problems you have encountered- maybe I was just lucky.
Note that print out will only occur after each interrupt.
If you're adjusting the potentiometer, make sure there is sufficient load through the meter. For example, if the load is only 300W, the pulses will occur at 12 second intervals, which is painfully slow when making an adjustment and waiting a full 12 seconds to see if there's any response.
If an oven or dryer is turned on and the load becomes 3600W, then the pulse rate will be 1Hz, which is much easier to make adjustments and check for response. With 3600W and correct adjustments, printout will occur at 1Hz rate.
So I made some progress, the new holder makes it easy to adjust the potentiometer. So the breakout board has an inbuilt led, so i kept playing around with the settings of the potentiometer, so now its blinking in sync with the diode on the meter.
The problem is that the code still output strange values: I tried both falling and change for all the 3 versions. The codes can be found here.