EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Released to GitHub an Arduino Library demo for EmonLibPro with ethernet support:

https://github.com/chaveiro/EmonLibPro

 

I've developed a new generic library for every body to use. It's called Energy monitor Library Pro .

Based on emonTx hardware from OpenEnergyMonitor http://openenergymonitor.org/emon/

  • This version is a generic library for any number of voltage and current sensors.
  • Interrupt based, implements a zero cross detector and phase-locked loop for better precision.
  • Completely line frequency independent.

  
Reports Voltage, Frequency, Current, Active Power, Aparent Power and Power Factor.
This library idea cames from ATMEL AVR465: Single-Phase Power/Energy Meter.
  
Included is a demonstration usage in main.cpp.

The library was developped in AtmelStudio 6.1. See http://arduinoinstaller.codeplex.com/
Should be easy to convert to an arduino library. No code changes required. Compiles fine on GCC/WINAVR.
Edit: Done, see https://github.com/chaveiro/EmonLibPro.

 

This is the mother off all power meter libraries, highly precise and highly configurable.
The demo is working for 1 x voltage sensor + 2 x Current sensor at 1600 samples per second.

Possible improvements:

  1. Can easily be added a KW/hr meter variable to Result data struture. No sampled data is lost at any time!
  2. Use different algorithm in HPF for DC offset removal to save cpu cycles and sample at high rate. Done!
  3. Improve some code in adc interrupt with C pointers to save cpu clocks. Not pointers but as well!
  4. Add calculations for Reactive Power (VAr). The sampled data is there already.

 

Demo printscreen:

Ready                                                
ETH: DHCP ok                                         
EmonLipPro Demo
 1 - Print cycle data. (internal vars data for each cycle)
 2 - Print Calculated data. Change interval in define CALCULATESAMPLES.
 3 - Print Lib Status.
 4 - Post to server.
Press a key...
Got: 2
Result0: 238.03VAC      50.00Hz 1.56A   283.57W 370.55VA        0.77Pfact
Result1: 238.03VAC      50.00Hz 1.58A   282.71W 377.11VA        0.75Pfact
Result0: 238.03VAC      50.00Hz 1.55A   283.00W 369.67VA        0.77Pfact
Result1: 238.03VAC      50.00Hz 1.58A   282.17W 376.11VA        0.75Pfact
Got: 3
PLL: Locked
ADC samples per Cycle: 120
VOLTSCOUNT: 1
CURRENTCOUNT: 2
SAMPLESPSEC: 2000
CALCULATESAMPLES: 100
Got: 4
ETH: Post...Sent

 

Edit: Here is the program flow for the variables that contain measured data.

 

Update 21-Jun-2013: Added support for realtime cycle monitor via browser, see github latests. Printscreen below:

Please report your experiences and improvements.

TrystanLea's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Looks nice! will take a look and test it, thankyou for sharing. 

calypso_rae's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

32 samples per mains cycles is much slower than most sketches that have been previously posted.  The standard emonLib approach with FP maths gives around 55 samples per cycle. 

At 104 uS per 10-bit ADC conversion, the absolute max rate for two samples per loop is 96 pairs per mains cycle.  Using integer maths, my Mk2i PV Router code can comfortably run at this rate.   With two current measurements per loop rather than just one, that would equate to 64 loops per mains cycle.

Although 32 sets of samples per mains cycle is well above the Nyquist frequency, I don't know whether this would be enough for reliable calculations of complex parametric values.

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Hi calypso,

There is space to improved with efficient code on the interrupt zone as i said on first post.

To clarify 32 samples per cycle for 3 sensors is 96 adc samples per cycle. You must compare equal number of sensors on different codes.

For 2 sensors: 50samples per cycle per sensor can be done.
Thats is 100 samples per cycle or 2500 samples per seccond for 50Hz line.

Sample:

Got: 2
Result0: 226.91VAC      50.00Hz 2.92A   658.17W 662.32VA        0.99Pfact
Result0: 226.96VAC      50.00Hz 2.92A   657.92W 662.04VA        0.99Pfact
Got: 3
PLL: Locked
Samples per Cycle: 50
VOLTSCOUNT: 1
CURRENTCOUNT: 1
SAMPLESPSEC: 2500
CALCULATESAMPLES: 100

The beauty of the lib is that you just change one config line to change sensors count, etc.

I see no problem with 32 samples per cycle per sensor as the pll locks ensures reading every time at the same position in the signal and that was the problem with reliable readings on every other implementation i saw that just takes a blind sample of the signal ignoring zerocrossing giving much different results for the same constant conditions.
I must say i'm very much surprised with the precision of the results of EmonLibPro.

 

I also viewed the Mk2i PV Router code and it was very inspiring. You should see same name variables on EmonLibPro.

I noticed some issues i improoved.

1 - Loosing precision on adc by running ADC prescaler to /64 = 250kHz.
2 - Hardcoded to specific line frequency NUMSAMPLES var.
3-  Because of above, frequency calculation gives strange and fixed steps.
4-  Using Arduino millis() function in code disrrupts timer interrupts (it disables interrupts procesing millis)

 

 

 

calypso_rae's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

With a perfect sinusoid, I can see the advantage of phase-locking the sampling intervals to the signal that is being measured.  But the shape of mains voltage is far from perfect so the phase-locking process will be continuously adjusting the sampling rate so as to improve its alignment.  This process introduces timing jitter, which I have never felt to be a good thing.

Consider the effect of a phase-angle controlled load which turns on at a particular place within each cycle.  With a phase-locked system, the Nth sample in each cycle would either catch the turn-on event, or miss it.  The same error, albeit small, would be exactly the same in every cycle. 

With a free-running system, these errors would average themselves out.  Random signals add less rapidly than coherent ones (hope I've got that right!)

 

MartinR's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

chaveiro said: I see no problem with 32 samples per cycle per sensor as the pll locks ensures reading every time at the same posicion in the signal and that was the problem with reliable readings on every other implmentation i saw that just takes a blind sample of the signal ignoring zerocrossing giving much different results for the same constant conditions

Clearly you are aware that I posted a PLL implementation on this site back in December since I can see many of my comments still in your code.

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Martin,

There are much code lost in the forum an no body did a reliable lib. So i'm sorry if i mixed up authors.

I did saw your code, read my posting above as follow:

"I also viewed the Mk2i PV Router YOURs code and it was very inspiring. You should see same name variables on EmonLibPro.

I noticed some issues i improoved.

1 - Loosing precision on adc by running ADC prescaler to /64 = 250kHz.
2 - Hardcoded to specific line frequency NUMSAMPLES var.
3-  Because of above, frequency calculation gives strange and fixed steps.
4-  Using Arduino millis() function in code disrrupts timer interrupts (it disables interrupts procesing millis)"

 

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

calypso: "With a perfect sinusoid, I can see the advantage of phase-locking the sampling intervals to the signal that is being measured.  But the shape of mains voltage is far from perfect"

Exactly, that is the reason you dont want to sample random time. The shape is preety much stable near zero cross. See some real graphs witout pll (dots mark a read) the top of the shape is strange but near zero cross is't stable.

Consider the graph and try to understand why you got a differnet cycle data if you start summing for one cycle at dot1 and at dot 46.
Now imagine what happen if you sample many of this random differences for some time and get an average. The average foats a lot every time it's calculated from recent data.

You are also considering the line freq as stable. That is not true. So the pll does it job when line freq changes or cpu timing gets wrong. Also to contribute, sampling freq is expected to devide by typical line freq so in normal runtime, no gitter is added.

Plus this lib syncs to any frequency so you got real frequency measurement and no error in calculations is added when samples per cycle chages as they are considered.

 

I lost many nights tinking of this.

 

Just test and report differences, i'd like to know what can be improoved.

TrystanLea's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Hello chaveiro, Just tried your code, its not phase locking, Im not sure that I can see from your code how you select the voltage ADC pin and only apply zero crossing on the voltage waveform (zero crossing detection on small current waveforms not being reliable), on the emontx the voltage input pin is analog input 2, maybe a couple of additions to setup for setting system analog pins to use and a setting for system voltage, I see you have it set in the header to 4.95V.

Id like to echo Martin's comment, First I know how it is to spend a long time developing something like this as you say you have spent many nights which makes you want to say your approach is the next best thing but its good to be clear that PLL has been a topic of extended discussion here already with Martin's code and zero cross detection to avoid ' taking blind samples' has been a feature in EmonLib for a long time, see line 85 [emonlib.cpp] (despite its many other flaws like non-continuous sampling) which I've been working on fixing albeit slowly ;)

Edit: I remember now the AVR465 example that you mentioned your code is inspired from does not indeed implement zero cross detection, it samples for a fixed number of samples that fit an integer times into either 50 or 60Hz. So by other implementations maybe you where referring to AVR465 rather than implementations on this site?

Anyway thanks for your efforts in wrapping this as an arduino library.

 

calypso_rae's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Sorry, I still don't see why phase-locked measurements are better than free running ones. 

A perfect phase-locked arrangement would produce an identical result for every cycle.  Then, if you changed the starting point slightly, you could get a slightly different result for every cycle.  Which result is the right one?  Maybe you should try lots of different starting points and then average all the results.

Free-running samples may be "blind", but they are evenly spaced in the time domain, and that is surely all that matters.  We're not trying to characterise the mains waveform over only one cycle.  We're measuring it over many cycles, so it's surely better to use a free-running process which will average out any 'lumpy' bits of the waveform.

Well, that's my preference anyway.

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

TrystanLea:

The lib expects firsts ADC channels to be Volts, and rest Current.

#define VOLTSCOUNT 1            // Number of V sensors installed, can be 1 or CURRENTCOUNT number of voltage sensors
#define CURRENTCOUNT 3    // Number of CT sensors installed.

Translates to:

ADC0 = Volt sensor
ADC1-3 = Current sensors

My base was that AD0 is voltage from this schematic: http://solderpad.com/openenergymon/emontx-shield/

For config of sensor calibration, just folow the math in the comment:

#define V1CAL 245.23   // calculated value is 243:10.9 for transformer x 11:1 for resistor divider  (on ADC0)
#define I1CAL 10            // calculated value is 20A:0.02A for transformer / 100 Ohms for resistor = 10 (on AD1)
#define I2CAL 10            // this is for CT2 on ADC2
#define I3CAL 10            // this is for CT3 on ADC4

Must uncomment lines in CalDataStructure for new sensors.

Zero cross is signed at exact moment in Sample[ADCx].FlagZeroDetec variable and used at the end of the cycle.

Lib only works using zerocross and PLL lock on ADC0 voltage sensor for now. And realy we have not much cpu time to do it for more sensors without lossing sample rate... But is possible to write a var with real angle measured between each current sensor for 'real' power factor calculations.

See this code part where it does the pll thing. It only goes there at the end of a cycle, when next zero cross is detected but before saving new values to Accumulator vars.

   // Last sensor reading
    if (EmonLibPro::AdcId == VOLTSCOUNT + CURRENTCOUNT - 1)
    {

        // Quatrant 0, Cycle start. Only for Voltage sensor 0 this time.
        if (EmonLibPro::Sample[0].FlagZeroDetec) {
            // One New CYCLE Starts
            EmonLibPro::Sample[0].FlagZeroDetec=false;
            EmonLibPro::FlagCYCLE_FULL=true;

            EmonLibPro::SamplesPerCycle=EmonLibPro::SamplePerAcc / (VOLTSCOUNT + CURRENTCOUNT) ;    //Samples per cycle per sensor
            EmonLibPro::SamplePerAcc = 0;
           
            // ### PLL processing ###
            // The idea is to adjust timer to get a close to 0VAC read on the first measure of the next cycle.
            // Without PLL max resolution is 1/SAMPLESPSEC (0.83 ms for 1200samples/s)
           
            TCNT1 = TCNT1 + ((unsigned int)EmonLibPro::Sample[0].Calibrated * (double)(PLLTIMERDELAYCOEF));

 

 

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Calypso, this lib, does not work in a timed sample window. On the contrary, it does not loose any cycle and samples each cycle the same way. (or tries to with the pll)

As it never skips sampled data, it can even measure KW/h like the company meter.

Works like this:

Interrupt driven code:
1- Read ADC value and process raw data to Sample[ADCx].Calibrated var.
2- Sums Sample[ADCx].Calibrated in Accumulator struture.
3- Zero cross detected: Guesses next zero cross and programs timer to match it on next cycle. (the pll)
4- Copy Accumulator to Cycle struture. Sums Cycle struture in Total struture.
5- Desired CALCULATESAMPLES (means number of zero crosses) reached. Signal FlagCALC_READY to true.

User polling code:
1- FlagCALC_READY is true: User code calls calculateResult().
2- calculateResult() calculates average results based on all taken summed samples in Total structure from last call to calculateResult() to Result var.
3- User code uses Result var.

User code must call calculateResult() before Total structure overflows.
Overflow depends on measured currents, more increase vars fast. A few seconds pooling is ok.

MartinR's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

chaveiro, just to answer your comments on my code...

1 - Loosing precision on adc by running ADC prescaler to /64 = 250kHz.

I did this to get the voltage and current sampling points as close together as possible. Linear interpretation is an approximation with increasing error as the samples get further apart. This becomes increasingly significant as the number of current samples rises. The shorter ADC time also allows more samples per mains cycle.
My justification for doing this is in AVR120 which states: :"For optimum performance, the ADC clock should not exceed 200 kHz. However, frequencies up to 1 MHz do not reduce the ADC resolution significantly."

2 - Hardcoded to specific line frequency NUMSAMPLES var.

It's only hard coded in the sense that NUMSAMPLES and TIMERTOP are defined constants. It's a simple matter to choose values suitable for 60Hz. Are you saying that your code automatically locks to 50 or 60Hz?

3- Because of above, frequency calculation gives strange and fixed steps.

I'm not sure what you mean by this. The resolution of the frequency measurement is NUMSAMPLES x clock period which is 3.125µs at 16MHz. This equates to 0.0078Hz at 50Hz perfectly adequate for displaying frequency to 2 decimal places.

4- Using Arduino millis() function in code disrrupts timer interrupts (it disables interrupts procesing millis)"

Calling the millis function has no affect on timer interrupts, it simply returns the latest value. Timer 0 is used for millis and it is running continuously so it will introduce some jitter, even if you don't call millis, but the time spent in the interrupt handler will be tiny so the affect will be very small.

TrystanLea's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Hello Chaveiro, great yes, the emontx shield pin out is the more logical pin out that we're also following with the next version of the emontx, the present version v2 unfortunately follows a different pin out, voltage is on analog input 2. Would you be able to add options for different pin out arrangements in your code? I can then do side by side testing of your library using the emontx? I based my approach to do this on jorg becker and pcunha'scode, see here there is an array at the top of the example which holds the analog pin read order, this array is then cycled through to select analog input pins.

john.b's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Rather than using a zero cross detector and phase locking to improve accuracy, would it make sense to use a more robust method of integration, such as trapezoidal or simpsons?

Trapezoidal integration could be implemented without much processor overhead and would improve accuracy.

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

MartinR:

Your code does a fine job, take my comments constructively.

1- It does loose precision a bit. Easy way to test is without any sensor connected and a simple code that prints raw ADC data at fast pace, the expected 512adc value changes a bit with that prescaller. Even at 125khz it does change from time to time due to surrounding electronics noise. In the Atmel documentation it states: " If a lower resolution than 10 bits is needed, the input clock frequency to the ADC can be higher than 200kHz to get a higher sample rate."
Anyway, your code work will work with the 125khz setting, adc calc is faster than the code you execute in the adc interrupt.

2- I see no problem if the line freq is fixed. My aprouch was to not hardcode any line frequency in code calculations. It adjusts automaticaly by matching zerocrosses with timer value at that time. No expected errors if line frequency does not change.

3- My experience relates to testing different line frequencies (simulated with a signal generator). Because it expects fixed freq in NUMSAMPLES, the reported values are off for other freqs. But again if line frequency expected to be almost constant, no problem then.

4- In millis() function at arduino-1.0.4\hardware\arduino\cores\arduino\wiring.c you see a disable interrupts instruction cli() if you got a timer or adc interrupt at that exact time you will loose it. beeing a free runing interrupts measurement, i was loosing many, see the arduino code :

unsigned long millis()
{
    unsigned long m;
    uint8_t oldSREG = SREG;

    // disable interrupts while we read timer0_millis or we might get an
    // inconsistent value (e.g. in the middle of a write to timer0_millis)
    cli();
    m = timer0_millis;
    SREG = oldSREG;

    return m;
}

 

MartinR's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

mmm, interesting about millis, I hadn't seen that, thanks for pointing it out.

I was expecting to see an sei at the end of that function, so when/how do interrupts get re-enabled?

 

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

The cli() function changes a bit in SREG, at SREG = oldSREG it sets it again.

MartinR's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

duh! of course, so we're looking at microseconds, I can't see that affecting anything.

You surely won't lose any timer interrupts, they will remain pending and as soon as interrupts are re-enabled they will be serviced?

Petrik's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Good stuff - havent looked the code but everything said so far makes sense. Its good to challenge the old domain and push the envelope to The next level ! I know from experience that sometimes it takes some convincing to bring in the rationale, but at the end its worth it for the community. Every cloud has a silver lining so lets push for it.

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

MartinR, with the PLL every uS counts.

I've posted a fix request at http://forum.arduino.cc/index.php?topic=168586.0

Thanks Petrik.

The problem with arduino IDE thinking is that people are guessing the code does what it's expected to do. If you start simulating with AVR Studio you will see thinks that occour differently on the uS scale.

I programmed in assembly as an hobby about 10 year ago when you had less than 1Kb of progam memory to play. Without simulating you had many strange things happening that missed your control. I try to have the same low level control inspecting the generated assembly of the C compiler when dealing with time precise tasks. May i say that even this lib has a 0-2 'random' timer counts added when we execute the first C instruction in Timer Interrupt due to context saving code that depends on where you where when the interrupt ocoured and is not visible in C code.

When progamming this kind of time sensitive stuff, we realy need to think inside the box! :)

dBC's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

chaveiro: cli() if you got a timer or adc interrupt at that exact time you will loose it. beeing a free runing interrupts measurement, i was loosing many

Why were you loosing them?  Surely there'd have to be two interrupts from the same source during the disabled window before you'd lose anything?   Otherwise the interrupt just gets delayed until they're globally re-enabled.  Looking at millis() for example, it disables them for about 9 cycles, or 562.5 nsecs at 16MHz.    So worst case, if an interrupt fired just as they were disabled, that event would get delayed by 562.5 nsecs.   Is the PLL code really that sensitive that it can't cope with 1/2 usec of jitter in the timer interrupt?

JBecker's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

I've posted a fix request at http://forum.arduino.cc/index.php?topic=168586.0

I think that the changes you suggest there are not possible. All interrupts have to be disabled to make 

unsigned long m = timer0_millis;

atomic.

 

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

What do you mean with atomic?

Int is disabled so timer0_millis is not changed in the middle of the copy to m.

dBC's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Each timer uses an internal temporary register for accessing the high byte of 16-bit registers.  The datasheet contains more details under "Accessing 16-bit Registers".

JBecker's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

What do you mean with atomic?

Int is disabled so timer0_millis is not changed in the middle of the copy to m.

You are perfectly right!

If you know that (the global variable) timer0_millis is only modified in the Timer0 overflow interrupt, then it is better to only disable that individual interrupt when reading the value of timer0_millis.

What I still do not understand is why you lose interrupts when doing cli(); sei(); ?

 

MartinR's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

MartinR, with the PLL every uS counts.

chaveiro, if your PLL can't cope with a few microseconds inside an interrupt routine then your library isn't really a practical replacement for EmonLib. Remember you have to be able to cope with radio transmission which will definitely involve many interrupts if you use the standard library.

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

TrystanLea

Try the version attached, i've not tested it.

Change adc_pin_order in .H to your hardware.

I believe is this:

const byte adc_pin_order[] = {2,0,1,3,4,5};     // ADC pin sampling order remap. First values must be Voltage, last Current.

 

The lib will only read ADCpin up to the max number of configured sensors.  You can leave non used pins or remove from the array.

AttachmentSize
EmonLibPro-1.01test.zip 8.39 KB
dBC's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

If you know that (the global variable) timer0_millis is only modified in the Timer0 overflow interrupt, then it is better to only disable that individual interrupt when reading the value of timer0_millis.

Even if you can ensure that, there is still a hazard.   There is another hidden "global variable" involved in that transaction:  the high-order byte temporary register inside the cpu.   With the proposed change to millis(), you would need to ensure that no interrupt handler  reads or writes any 16-bit TIMER0 h/w registers.  

Actually, I take that back.  millis() only reads memory, not timer registers, so it should be safe.

 

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

john.b : I've created a new thread for your comment: http://openenergymonitor.org/emon/node/2412

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

For the skeptics of the PLL implementation.

I've been doing tests of the performance of the pll by measuring Voltage and Frequency of my home mains line.

The test consists of running an arduino sketch that publishes the Result structure every 2 seconds to EmonCMS.

The measurement is made by the lib v 1.0 and disabling pll was just done by commenting the line bellow on the .cpp file :

// TCNT1 = TCNT1 + ((unsigned int)EmonLibPro::Sample[0].Calibrated * (double)(PLLTIMERDELAYCOEF));

Freq is calculated with this formula:
1 - Find zerocross. -> save current timer count
2-  Keep saving timer overflows.
2 - Find next zerocross ->  see what time passed since step 1 including overflows.  Do a simple 1/t() and report in HZ.

The graphs are self explanatory of what difference is makes to do calculations having random sampling or, equal timed sampling on each cycle with the pll active.

- Left is PLL Active ( pll is consired locked if first sample was obtained at voltages between 0-16V in the cycle (512/32) )

- Right is no PLL working, sampling timer is divisabble by 50hz. (1600/32 = 50)

Lib Status was:
Samples per Cycle: 32
VOLTSCOUNT: 1
CURRENTCOUNT: 2
SAMPLESPSEC: 1600
CALCULATESAMPLES: 100

 

Self explanatory, 0.01 precision with pll. 0.05 precision without:

 

 

Each RMS voltage pixel in the graph is an average of all cycles rms taken every 2 seconds

Mains is not very stable here, we are seeing a 2V rms difference on this 55min window.

But clearly we can see a difference on the noise induced by the calculations without the pll (about 0.5Vpp noise).

On the left with the pll the line is clear to follow.

john.b's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

If your preference is to measure and display mains frequency and Vrms in real time then PLL may have some benefit to you.  If however, you are primarily interested in the flow of real energy through the meter then I don’t see the benefit.

Energy used over any period of time, irrespective of whether it’s over whole cycles or not is simply the integral of instantaneous power over that period of time, as below:

So Robin is right it’s more important that the sample intervals are equal so an accurate integration can be accomplished.  If you start varying the sample interval then you will not be measuring the energy accurately.

So it depends on what you are trying to accomplish?

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

The sampling frequency does not change with the pll.
Only the start time of measurement for the first sample of a cycle is adjusted to get a zero cross as close to first measurement as possible.

There is a var that reports PLL state. When locked, start sample time is synchronized with zero crosses.
When unlocked it works like no pll is there.

How much data you need to average to get a 'good' result with free run sampling?
And what happens when sample window end before cycle ends? - Since there is not even zero cross detector.
Answer: You get cuted cycle samples added to the mix. It's random data or noise. Remember, most home charges are not perfect resistors and take current in an un-uniform way relative to the cycle. (eg. SMPSs) So that's why i decided to have a time base of a cycle, just like other app notes out there do.

I prefer a precise Lib that has the versability to get all parameters from line and not just active (or real) power.
With this all line parameters can be obtained from just one line cycle.

The objective is to get the best precise results from this lib. Hint: Pro is in the name.
For satisfatory solutions there are already many methods.

 

Please test, read the lib code and point constructive things (good or bad) about the results.

JBecker's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Only the start time of measurement for the first sample of a cycle is adjusted to get a zero cross as close to first measurement as possible.

I think this is exactly the weak point (if this really matters at all, see following thoughts).

It means that one sample interval has a different size and so its 'weight' in the calculation is wrongly determined. If for example this interval is only half as long as the others, the energy calculated from this interval is double its 'real' value. Together with the very low number of measuring intervals per full cycle this could lead to an error in the percent region (1 sample out of 32).

But, as this sample is always located very near to the voltage zero crossing, the error will in fact be much smaller (voltage is near zero, so power and energy for this interval will be small compared to a sample where voltage AND current are high, usually near voltage maximum for near resistive loads).

BR, Jörg.

 

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

JBecker, you describe the scenario where the pll is unlocked. Most of the time it should be locked so all sample times are 'almost' equal for each cycle.

If requested, i will add an option to disable the pll stuff of the lib.

MartinR's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Just for the record, this isn't how my PLL works.

I adjust the timer period so that 50x the period is equal to the current supply cycle period (within the resolution of the timer which is 62.5ns). All the sample intervals are always the same within one supply cycle since the adjustment is made at the end of the cycle.

Under normal circumstances, when the supply frequency is stable, the variations in timer period are tiny. There is probably a similar amount of variation with the "fixed" sampling approach caused by servicing other interrupts, like the serial port.

JBecker's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

JBecker, you describe the scenario where the pll is unlocked. Most of the time it should be locked so all sample times are 'almost' equal for each cycle.

Yes, true. If I calculate correctly, the biggest correction you do in the locked state is ~612/10000, so the error should really be negligible.

If requested, i will add an option to disable the pll stuff of the lib.

No, why? I really like your implementation. I would prefer a much higher sampling rate, more like 5000-10000 samples per second. But I cannot proof that this is really necessary, it is just a result derived from of a lot of projects with AC mains measuring and synchronization.

We should not forget that in this special case of energy monitoring we usually average over a very long time (lots of periods), before we send this averaged value via RF (5, 10, 20 ....? seconds transmit interval). This should also help to get 'good enough' results, with or without PLL.    

dBC's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

I just did some experiments with the data discussed in this thread:

http://openenergymonitor.org/emon/node/2296

The original source data was sampled at 2000 samples per mains cycle.  I then just used every 62nd sample to give a sampling rate of about 32 samples per main cycle (none of it particularly sync'd to zero-crossings).  Looking at energy calculations for single cycles (i.e. 20 msecs), the error introduced by the slower sampling rate varied from as small as 0.33% to as high as 2.92%.  Looking at the entire 5 cycles, the error was 1.55%.

Screenshot-41.png
TrystanLea's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Thanks Chaveiro for the adc_pin_order mod, rms voltage and frequency is now working, its not yet giving the correct results on the current channels, not sure why at the moment.

It should be reading 250W but Im getting:

Result0: 244.94VAC 50.00Hz 0.00A 0.00W 0.00VA 1.00Pfact
Result1: 244.94VAC 50.00Hz 0.03A -0.10W 6.21VA 0.02Pfact

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

TrystanLea ,

Please tell me in what ADC pins you have what sensor. adc_pin_order should be like this:

VOLTSCOUNT: 1
CURRENTCOUNT: 2
adc_pin_order[] = {_ADCV1_pin_,_ADCI1_pin_,_ADCI2_pin_,dontcare,..};

 

VOLTSCOUNT: 2
CURRENTCOUNT: 2
adc_pin_order[] = {_ADCV1_pin_,_ADCV2_pin,_ADCI1_pin_,_ADCI2_pin_,dontcare,..};

 

 

TrystanLea's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Yes sure, this is what I have defined:

#define VOLTSCOUNT 1
#define CURRENTCOUNT 2

const byte adc_pin_order[] = {2, 3, 0, 1, 4, 5};

CT1 on the emontx is analog 3

CT2 on the emontx is analog 0

CT3 on the emontx is analog 1

I have tried the CT in CT1 and CT2 neither give the correct result.

I've also set calibration to be according to the emontx I have here which has 22ohm burder resistors and 120k / 10k AC-AC voltage divider.

#define V1CAL 275.0        // calculated value is 243:10.9 for transformer x 11:1 for resistor divider = 122.61
#define I1CAL 90.9            // calculated value is 20A:0.02A for transformer / 100 Ohms for resistor = 10
#define I2CAL 90.9            // this is for CT2

and supply voltage is 3.3V

#define SUPPLY_VOLTS 3.3

On another note, the graphs above are great! Il try and replicate that kind of test with different configurations, maybe we can start to establish things like standard deviation improvement by different implementations. That would make an interesting series of documentation pages for people coming to this anew wanting to understand why the code is implemented in a particular way.

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Conf seems fine.

Please post some lines of the cycle data print (press 1) and lib status (press 3) for each of the 4 scenarios:

1- Voltage on ADC4 + CT to ADC3 - 0W load
2- Voltage on ADC4 + CT to ADC0 - 0W load
3- Voltage on ADC4 + CT to ADC3 - 250W known fixed load
4- Voltage on ADC4 + CT to ADC0 - 250W known fixed load

Please give a link for the schematic for your circuit. Also what is the number of turns of your CT?

May need to change serial speed to 250000 and use a terminal program that supports it to print the fast cycle data.

 

 

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Released my sketch to post sensor data via ethernet:

https://github.com/chaveiro/EmonLibPro/tree/master/examples/EmonLibPro_E...

TrystanLea's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Thank Chaverio, I will get back to you on the above soon.

MartinR's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

that real time cycle monitor looks really neat chaveiro - well done!

trunet's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

is this library suitable for 2 phase system? I have 2 x 110v hot and 1 neutral. I have a 220v transformer plugged on both hot and one CT on each hot.

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Yes. The lib will report the 2 phases current and one voltage by default.

The power reported will be doubled for each phase as P=U*I and you are measuring 2x 110V. But no problem, you can calibrate V1CAL to report 110V from the 220V transformer, or add a division by 2 in emonCms.

jmomjo's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Should it be possible (i.e. an 8-bit counter/timer should be sufficient) to easily switch Timer1 by Timer2 ?

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

I don't understand your question. Please explain what you want. to accomplish by that.

jmomjo's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

I want to add energy monitoring to the Open EVSE project.

As I need to keep latency as low as possible (50 ms maximum) for security reasons, the standard library for OpenEnergyMonitor isn't convenient. So I'd like to use an interrupt driven calculation method for current, voltage and power.

OpenEVSE project needs Timer1 to drive a 1 kHz PWM signal in order to communicate with the electric vehicles.

As I want to keep millis() and delay() available, I need to preserve Timer0.

That's why I ask you if it should be possible to replace Timer1 by Timer2 in EmonLibPro.

 

borland's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

jmomjo,

Don't forget that Open EVSE board needs to keep available interrupts for handling GFCI faults.  An interrupt based power monitoring addition to Open EVSE needs to be performed by an independent microcontroller.

I'm developing an energy monitoring solution for Open EVSE's I2C serial port.  My approach is to use the SCT-013-000 current tap, and a ATTiny85 microcontroller for data logging/processing, with data for display by communication over I2C.  Since I'm only going to sample current and will be estimating kWh power consumption for one type of load (EVSE), the project is greatly simplified.

The ATTiny85 has an internal clock which is not real accurate, so I intend to use a similar PLL, like has been done here, to lock with the grid for sampling interrupt intervals, but also to synchronize the ATTiny85's internal clock with the much more precise grid frequency.

jmomjo's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

borland,

Thanks for this reply and these informations.

I will have a look at the Atmega 328p datasheet. GFCI needs only one external interrupt (on digital pin 2).

Be careful in only sampling current, EV aren't full resistive charges.

Here are my measurements (with EmonLib) with a Renault Zoé in a typical charge from 20% to 100% in 3h40mn (32A single-phase current - 230V) :

Current (A) Real power (W) Duration (h:m:s) Power factor
30.2 6900 03:10:00 1.00
26.6 5900 00:00:15 0.99
20.2 4400 00:01:00 0.98
14.5 3100 00:08:00 0.94
10.0 1900 00:20:00 0.83

 

 

 

 

 

 

borland's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

We're getting off topic, but the AVR interrupts are not interruptible.   Relay response times are pretty long (>30ms), so you don't need any further delays to have GFCI trip times exceed acceptable standards.

The point of wave sampling is to calculate the RMS value for when the wave pattern deviates from a pure sine wave.  That's what Emon library does for various types of loads.  I'm doing the same sampling for EVSE.

I also understand the charge curves for Li-ion.  Sure your power factors are accurate?

If you want to discuss EVSE further, PM me so as to not destroy this interesting discussion thread.

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

jmomjo, you can user Timer2 for this lib, just ensure it occurs in the same frequency as the original implementation with Timer1 do.

However, i dont recommend servicing other interrupts that run code inside interrupt handler as it will disrupt time sensitive calculations of EmonLibPro.

Prefered methode is to try to merge your requirements on the same interrupt EmonLibPro uses, and it's then a new lib with your requirements.

Or have a dedicate chip to do the calculation and use i2c to send the calculated data as borland pointed out.

jmomjo's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

chaveiro,

Thank you for your answer.

The interruption mentioned by borland is a GFCI trip. If this event occurs, it doesn't really matter if EmonLibPro reports wrong values ;)

In this case, the important thing is that EmonLibPro doesn't delay the handling of the hardware interrupt tripped by the GFCI.

Do you know the delay between two interruptions in EmonLibPro ?

As you perfectly know your code, do you think it should be difficult to replace the 16-bit timer by an 8-bit one ?

Last question, how much RAM needs EmonLibPro to work ?

Thanks in advance for your help.

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

The minimal delay is the sample rate defined in SAMPLESPSEC variable, about 0.5ms.

How does the gfci works, is a separated device that cuts power? Why is PWM needed?

You can signal a imbalance in neutral / phase with emon lib by monitorig L and N and define a max variance allowed between the two. Minimal reaction time may be as little as 1.5ms (num_sensors * SampleSSec = 3 * 0.5). High precision is subject to small variations by sensors error/noise.

Regarding RAM it's not much if you disable realtime wave cycle monitor.  I cant give you precise value right now.

Thinking about other implication on changing to 8bit Timer is with the PLL. Having less range to play with may be bad. Testing must be made.
 

 

 

jmomjo's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Borland is right, we're getting off topic ;)

If you want to get more information about the OpenEVSE project you can have a look here and there.

I'm going to study your source code and to do some testing.

Thanks.

chaveiro's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Thanks for the links jmomjo,

Good luck with the source code digging. If you have any doubt or discover an improvement, let me know.
 

Basic sketch with cycle variable off and no help menu serial.print's:
                Program Memory Usage     :    8186 bytes   25,0 % Full
                Data Memory Usage         :    560 bytes   27,3 % Full

Default demo non ethernet + cycle variable (that takes 3*41bytes):
                Program Memory Usage     :    8484 bytes   25,9 % Full
                Data Memory Usage         :    988 bytes   48,2 % Full

 

You can reduce further RAM usage if strings (eg. used in serial print) are saved in flash. See http://www.arduino.cc/en/Reference/PROGMEM

jmomjo's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

I have finally forsaken the interrupt based method to add energy monitoring to the Open EVSE project.

This method isn't compatible with simultaneous 1 kHz pilot voltage readings (also with ADC).

Instead, I have chosen to optimize the EmonLib calcVI function and to sample only 3 mains cycles to keep EVSE latency under 100 ms.

And I have finally got the maximum ADC sample rate for ATMega328P (~9600 samples/s @ 10-bit resolution = 96 current+voltage samples per mains cycle @ 50 Hz).

I join the source code. If someone has time to check it and eventually to put it on GitHub, it could help the community.

I would like to thank MartinR, Robin Emley, Pcunha, Jorg Becker, Robert Wall, chaveiro and especially Trystan Lea for their ideas and source codes.

Last edited : bugs fixed

AttachmentSize
EmonLib.zip 4.48 KB
anil.yesilkaya's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

It looks pretty solid estimation method for frequency detection.Here are some observations of mine about accuracy of the library in attachment.The problem i've faced with is,im trying to monitor 3 phase system and each phase has its own frequency value. When i simply changed the VOLTSCOUNT it is measuring frequency of voltage source1 which is connected to analog0 and prints same frequency values for 3 of them even if they are way too different.   

// Timer 1 interrupt handler
ISR(TIMER1_COMPA_vect) {
    ADMUX   = _BV(REFS0) | adc_pin_order[0]; // [AVCC with external capacitor at AREF pin] | [PIN=ADC0]
    ADCSRA = adc_sra | _BV(ADSC);            // Start ADC conversion

I suppose these adc_pin_order[0]; part is just sampling voltage at analog0 port for frequency measurement.I couldn't get over that problem.

AttachmentSize
freq_measurement.pdf 19.02 KB
calypso_rae's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

The problem i've faced with is,im trying to monitor 3 phase system and each phase has its own frequency value. When i simply changed the VOLTSCOUNT it is measuring frequency of voltage source1 which is connected to analog0 and prints same frequency values for 3 of them even if they are way too different.   

Sorry if I've mis-understood something, but how can the frequency be different on different phases?  Do you mean that the amplitudes (voltages) are different on each phase?

glauco.b's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

This is an old thread, but I am upping it because I have started using this library in my own monitoring project.

My setup does not use the wall wart and CT sensors suggested for the emontx and instead uses an Allegro ACS712 hall effect CT sensor and a PCB-based 220V to 9V transformer with a resistive divider to sense voltage.

The library works impressively great for all the measurements but the phase.

I have tried it using a very simple test plant with a simple incandescent light bulb and the Arduino board powered via USB (should be an almost pure resistive load, apart from some minor noise effect from the digital stuff). The library always reports a power factor of 0.77 (should be close to 1), no matter the phase calibration factor I use to configure it.

I have a suspect that the ACS712 is introducing a significant phase shift (it is a complex sensor that produces a precise linear voltage output).

The library does not allow me to set a "phase shift" adjustment for the current measurement and I haven't any clue where to put my hands on the code to introduce it

Can someone help me in this?

TNX

glauco.b's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

ok, I am giving myself a partial answer

based on the indications in the library code for phase calibration, I got a phase error of 37.8°

The code comment says the maximum phase delay that can be interpolated is 27°. My delay is well above this angle.

Now I am stuck. To be able to interpolate that delay I should reduce the sampling frequency. Is this correct? What should be the correct sampling rate? (I am only using 2 sensors)

glauco.b's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

well, after all sometimes questions turn out to be quite silly...

It seems like the ACS712 breakout I'm using introduces a significant phase shift (around 30°). 

This is a fixed skew, so eventually I ended up recalculating the power factor in my code by subtracting the 30° angle from the value detected by the library.

 

 

glauco.b's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

Just a last update, I promise!

After some wrestling with the ACS712, tests with an oscilloscope and and after switching to the standard Emonlib, I came out with the following, that I'd like to share:

1. The ACS712 (the 20 amps version) works well, it is very precise and it gives galvanic isolation from the load and it is not bulky like the split core c-t sensors. OK, yes, you have to insert it in-line with the load, so it is good for a plug-in energy monitor, not good for a breaker-based monitor. Plus: it is quite cheap, actually much cheaper than the split-core CT sensors.

2. It is not a shunt resistor, so it also detects magnetic effects and noise, meaning that the sensor always reads an rms current that is not exactly zero, but close to (like 0.05 A).

3. the phase delay is close to zero (forget my previous posts, I just miswired the sensor...), limited only to the artificial phase delay given by Arduino. After trying it with several different resistive loads (heaters, incandescent bulbs, oven, ...) I always got  PF very close to 1. 

4. You don't need any amplification stage, as the output voltage range is 2.5V +- 1.5V at 16A. It is better to use a precise 2.5 voltage reference to bias the voltage signal (an op amp instead of a resistive divider), to avoid and wrong artificial phase differences

5. The Standard EmonLib works perfectly without any modification, just feed the output of the ACS712 to an analog input of the arduino. The calibration factor for the ACS 712 is around 5.0.

6. My circuit uses a standard, linear transformer based PSU (just a 9V transformer, bridge, capacitor and linear regulator) to power up everything and also to provide the voltage measurement to emonlib. Do not use an SMPS as it will introduce noise in the current sensor. 

Robert Wall's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

That is useful information - thank you. However, as you say the device does require a direct connection into the circuit being monitored so this limits its usefulness to places where you can safely and legally break into the circuit.

fredrike's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

This looks really promising..

I want to use this library with a http://wiki.openenergymonitor.org/index.php?title=EmonTx_Arduino_Shield reading 4 CT's (one per incomming phase (3) and one for our SPA), but I also like to read pulses from a meter connected to my heater. Will that pulsecounting affect the readings of this sketch?

How should I configure as I have one http://shop.openenergymonitor.com/ac-ac-power-supply-adapter-ac-voltage-sensor-euro-plug/ connected to my Sheild? 

Also, I'm planning to use a ethernet module to send the readings to emoncms, any inputs on that?

Robert Wall's picture

Re: EmonLibPro Released - Multi sensor, Interrupt based, implements a zero cross detector and PLL.

I deleted your duplicate post.

Unfortunately, I have no experience with Chaveiro's library and I have seen few comments and hardly any discussion about it, and Chaveiro has not been active for a while. However, an experienced programer did express some concerns about some aspects of the library.
Also, I believe that I have seen that someone had a problem using the EmonTx shield with an Ethernet module, but I cannot remember the details. You might find it if you search this site.

I'm sorry I can't be very much help.