Verify my power factor code is correct - using Coretex M4

Hi,

I’ve a Coretex M4 with a single ADC which is operating at 25KHz for two channels. It DMA burst reads repeatedly for 0.25s which is enough to capture the lowest period/frequency of the AC, the idea being to capture as a minimum at least one full period for apparent voltage & current and a bit more to capture the real current (which will start somewhere within the voltage period), then use this to calculate power factor.

The code thus looks for the zero-cross points for voltage, works out the apparent power, then looks for the zero-cross points for current, calculates the current RMS for this and works out the real power using the voltage worked out earlier.

Q1. Is this correct?
Q2. I should have minimal phase addition from the measuring side (all resistor shunt based) but how would I factor this in if needed to? I do have the time between the voltage and current zero-cross points, and the frequency of the voltage, something tells me these should be used in some way to factor phase caused by the measuring equipment?

code.c.zip (971 Bytes)

Why bother with looking at cycles of voltage and current separately? The only requirement that I know about for calculating rms values is either you have so many cycles that a part-cycle doesn’t matter, or you have an exact integral number of cycles. Nobody says you must work from zero crossing to zero crossing, it just happens to be convenient for the mathematicians. If you have 250 samples per cycle, one errant sample - even at maximum amplitude, won’t make much difference over 10 cycles. What I’d do (makes the code easier) is take the timing from the voltage, where the zero crossings are well defined because the amplitude is sensibly constant (± 10% whereas the current amplitude is 0 – 100%) and use exactly the same period for the current sample.
Then you can do all the multiplications and accumulations in one pass.

(N.B. I don’t understand what you mean by “apparent current” and “real current” at sample level.)

Where does adc.calibration.ac.voltage (and the same for current) come from? If you think those are constants - you might be in for a surprise. Over one sampling period - yes they should be constant, but over time, I doubt it very much. In emonLibCM, I take off the nominal offset first - just to keep the numbers small - and I derive the equivalents from the average of all samples over the averaging period, and then trim off the remaining offset after I’ve got the rms values and the average power.

But you have “with a single ADC” - So unless the S&H samples both channels at the same instant and then converts them afterwards, there’s a timing error - that looks like a phase shift - between your corresponding samples.

Don’t even try to use the crossing points - it only takes a bit of phase shifted harmonic to move the crossing point, whereas most of the power will be in the 50 Hz component. And in any case, you cannot do it automatically in the software. The only way is to set a defined load (a pure resistance is the easiest and most people have one - it’s called a heater but it mustn’t have a motor and a fan) and measure the error. You have about one sample every 1.44°. That might be enough to be able to get away with choosing the right pair of samples to multiply together to get the real power. If not, you probably need to interpolate between two successive samples to create a “shifted” sample as we do in emonLib. And I’d always use the voltage for that as it’s always going to be the closest to a pure sine wave, hence interpolation will introduce less distortion. Even though emonLibCM samples a lot faster than emonLib, it’s still necessary to use the interpolation approach.

The disadvantage of using a pure resistance to adjust the power factor is you’re adjusting to find the crest of a sine wave, so the peak is ill defined. If you know the mains frequency exactly, you could shift a set of samples by a defined amount and adjust for a known power factor while still using your resistive load. The obvious one is a shift of around 90° which you adjust and which will give you a well-defined zero real power and zero pf, and then the difference from 90° is your phase error. (You can do that physically with a large capacitor as the load, but unless you’re aware of the very real dangers, I strongly advise that nobody tries it.)

adc.calibration.ac.voltage - this is sampled on boot, it’s the offset for the voltage and current reads and is constant.

Apparent power - I’m using the voltage and current over one cycle (where one cycle is the voltage zero cross points).

Real power - I’m using the current between current zero cross points and the voltage from apparent power.

The single ADC will induce some minor phase shift between the voltage and current reads but it is minimal. I’m at ~4,000 reads per period (at lower AC frequency). Reads are interleaved - voltage, current, voltage, current etc. All reads are hardware driven with DMA so there’s no timing errors at all between them. As such I can work out the time between the voltage and current zerocross points.

So far the voltage and frequency points are calculating perfectly (confirmed with oscilloscope measurement).

You have a very, very, very stable reference if it won’t drift over time, if that’s the case. Unless of course you are only intending to measure for a short time before you reboot.

I don’t intend to study the data sheet for your Cortex M4, but from what you’ve written, you have 1.44 electrical degrees between samples. Admittedly, that’s insignificant at unity power factor, but it will become increasingly significant as the power factor tends towards zero - which it does for things like microwave oven timers. It will turn a p.f. of 0.2 into one of 0.175 or 0.224, depending on which way it goes.

But as I wrote, I wouldn’t regard the current zero crossing as reliable. As well as harmonics moving it about, as the current falls towards zero, it becomes less and less well-defined, and there’s no need to use it at all.

Without knowing the zero cross points I can only take voltage and current reads over a period of time which is fine for apparent power, but for real power I need to shift the current in phase with voltage to calculate the real power. These two then calculate the transfer efficiency of the output device.

Inductive Source → Voltage/Current Read → Output Device (potentially with reactance tuning before the rectification)

I’m not sure how you derived 1.44 degrees because I didn’t mention the frequency. Have you assumed I’m reading main power AC? I’m not. The frequency changes. Somewhere between 1-200Hz and lots of harmonics hence the large amount of burst reads over two periods (two periods being enough to catch the start of the voltage period and the end of the current period). ADC time between voltage and current read is 10us.

I’m not sure how you calculate the real power without knowing the current zero-cross points and shifting the cycle onto the voltage cycle. I wonder if you’re calculating the power input and power output within a timeframe and deriving an efficiency rating rather than power factor (efficiency will go up as power factor increases but would also includes losses of the output device).

You need to explain to me why you think that is necessary, or even desirable.

In the world of discrete samples, real power is the average of the product of each voltage sample and a current sample taken at the same instant. If you shift one in relation to the other, other than to correct a timing error or a phase error in a sensor, you don’t get real power. Power Factor = cos(φ) only exists in the textbook world of pure sine waves.

The definition of power factor is the ratio real power ÷ apparent power.

Here’s how:
Using a parallel set of samples relating to a complete cycle, or a multiple of complete cycles (and to define a cycle, you do need a well-defined starting and ending point), you can square and average the voltage samples to obtain the rms voltage, likewise the current samples, and multiplying each voltage sample by the corresponding current sample, you get the instantaneous power and averaging that, you get the real power. Apparent power is then the product of the two rms values, and you then have all you need to know the power factor - with decent accuracy, provided that the answer is closer to unity than to zero. If the power factor you calculate is close to zero, then you need to shift your voltage samples by 90° and multiply the shifted voltage samples by the unshifted current samples to give the imaginary or reactive power, and calculate the power factor from that.

If you want to know more than that, then you’re heading towards doing a Fourier analysis, then you can calculate the power in the fundamental and each harmonic separately.

I don’t know what you mean by efficiency. So far, you’ve only mentioned one measurement of power factor, and that’s what I thought we were discussing. Surely, to calculate efficiency, which as far as I’m aware is work out ÷ work in, you need two sets of readings of real power. Remember, all I know about your objective is what you’ve written here.

Trying to conceptualise it here.

Real power - take each voltage sample, square and add to accumulator. Repeat for current samples. Divide accumulators by sample amount for RMS. Multiple both together for real power.

Apparent power - confused on how to calculate this now.

Now I have it, I’m actually already computing the apparent power.

Brilliant explanation here Learn | OpenEnergyMonitor

Yep, you’ve got it.

But I’m not sure that your C++ code has even been computing that - especially if the two rms averages have been over different periods. I think it will have been close, but not necessarily exact.

Actually, that’s what I’ve been trying to explain to you all along.

Then, because you’re operating on the two sets of samples taken over the same time frame, you can do all three multiplications and accumulations in the same pass.

You’ll find quite a lot of the basic theory in the ‘Learn’ section, so it’s worth taking a look to see just what’s there. The demonstration sketches n ‘Learn’ work, but they are deliberately kept simple to illustrate the basics. The ‘production’ code in the present sketches is rather more complicated.

It was a little incorrect before. The attached code has it working well - I’m currently sampling 25,000 reads (4 channels) over 0.35s and a Coretex M4 64MHz is computing at about 2Hz. The AC has a lot of harmonic content hence the high amount of reads.

c.txt.zip (1.2 KB)