Dear all

I have fed the line voltage with an isolation transformer to my MCU ADC, and I'm getting 64 samples on each cycle for a 50Hz line frequency. I have calculated zero cross for each cycle and based on that I'm calculating line frequency. But the problem is that readings are not stable and I have about 2-3 Hz error, no matter if I average frequency over 1 second"¦. Do you have any idea? Is there a better way around?

## Measuring frequency based on ADC samples

Internal RC oscillator or external crystal?

external crystal.

Shape it to a square wave with a comparator, and use the input capture to get the period at maximal resolution. Then calculate the frequency which is a reciprocal of a period.

Consider interpolation of the near zero cross at one end. One cycle should do it. My experience is 0.1Hz. Will need sanity checks, it will sort noise too. The determined frequency may used to set sampling rate. Easy way for 50-60Hz auto mode.

Your deviations are cause by the asynchronous measurement, the interpolation resolves it to be synchronous. There is much more to the story.

Consider interpolation of the near zero cross at one end

I'm interpolating the near zero samples to calculate exact zero cross for two consecutive zeros. And calculate frequency base on this formula

1600/(Second_zero â€“ first_zero)

KitCarlson would you explain your algorithm more?

To minimize math, and errors, choose the first point near zero cross, then interpolate time to match the first point analog value. To be off by 2-3 Hz indicates you are sometimes off a sample interval. The period is the the total timer ticks of the sampling interval. In your case 64 times sampling interval ticks, + - the interval correction. Use an appropriate prescaler on the sample timer, to give decent resolution.

A simple 3 point filter on the data helps. The pivot point times 2, add in adjacent points, divide by 4. Do this with adds and shifts.

**Ali_dehbidi wrote:**

Quote:Consider interpolation of the near zero cross at one end

I'm interpolating the near zero samples to calculate exact zero cross for two consecutive zeros.

And how do you interpolate then? I assume you take voltage the sample N before zerocross and sample N+1 which is after zerocross, and calculate where between samples N and N+1 the cross actually happened. You have 64 samples per sine cycle, so how many "subsamples" you have after linear interpolation?

**Ali_dehbidi wrote:**

And calculate frequency base on this formula

1600/(Second_zero â€“ first_zero)

So you calculate the frequency from zero crossings of one half-cycle only, which is only accurate to about 1-2 samples per 32 samples? That's about 2-3 Hz with 50Hz signal.

If you average inaccurate readings, the average is inaccurate.

You achieve better accuracy, if you calculate time of 50 sine cycles, because then your sampling can only vary 1-2 ADC samples per 3200 ADC samples or about 0.03 Hz with 50Hz signal.

Or you could just use a bigger sampling rate to begin with.

How do you feed the AC to AVR? Do you bias the ADC pin to VCC/2, and the AC rides on top of that bias through DC blocking cap, or do you bias the transformer pin to VCC/2 and directly measure the DC coupled secondary?

A simple 3 point filter on the data helps. The pivot point times 2, add in adjacent points, divide by 4. Do this with adds and shifts.

Would you explain it more, or do you have a snippet code?

Actually I'm using LPC1768 for MCU and AD7606 for ADC, the ADC will accept ac signals.

I will send some ADC readings and calculated zero crosses for you, as soon as possible.

this is one cycle readings from my adc

-348 -313 -273 -228 -179 -130 -82 -37 7 50 92 130 168 207 246 281 315 351 384 410 415 416 422 429 431 429 422 414 407 399 388 360 328 294 253 209 160 110 64 18 -27 -70 -111 -150 -187 -227 -265 -301 -335 -370 -403 -430 -435 -441 -447 -452 -447 -440 -433 -426 -418 -407 -379

my MCU calculate first zero to be 7.840909 and second zero is 39.4

now the ferequency is 50.6HZ

but my ferequcny meter reads the frequency to be 49.99Hz.

I get the same results.

But it only works if zero crossing is symmetric. Your positive peak is at +431 counts, and negative peak is at -452 counts. So in fact your DC offset is not at 0 counts, it is something negative, -10.5 counts if I am not mistaken.

If I add 10.5 counts to everything, the zero crossings are at 7.6022 and 39.6163 and when calculate the frequency, I get 50.02.

So you are measuring shorter positive wave than the negative wave is, so maybe that is why result is wrong? Did you try to count from one rising edge to next rising edge?

While you have shown the analog data values, what is important is the timer value used to generate the sample timing. That is your time base and is originated from the crystal clock. You can halve the measurement error by interpolation only at one end. As Jepael states, the zero is off but the slope the greatest and near constant near the zero. By having decent timer resolution, and a software PLL the errors of interpolation are small, or zero if there are precisely 64p/c. I worked with 128p/c and above sampling rates, that helps reduce errors too.

Often in metering calculations of sums, and sums of products are the basis of most power calculations. These include V, I, P, and DFT's to resolve phase. The similar nature of these calculations can lead to efficient code design. A meter may not have to meter every data point, it can gather a cycle, process, then repeat.

There is no need for hardware zero cross to have a simple and accurate meter. You are on the correct track in your thinking. What is important is the phase and magnitude handling in the front end, and accurate sample time base. Coincident sampling is also helpful. While the data you have shown is bipolar, it is simple to work with unipolar data.

Shirley you can just use the comparator. I would set the comparator switch level to be about half-way up the cycle. i.e. don't try to find the zero crossing.

Measure the period between negative edges. Average these values. In fact you will simply measure the time for 100 edges and divide by 100.

If you want to know the zero crossing, or the peak, you measure the positive edges too. The peaks are at the mid-point between edges. The zero-crossing is half-way between peaks.

David.

The filter is simple, it smooths the analog data. Use only to filter the signal used for frequency measurement. If you have a string of data the n is the pivot point, multiply it by 2, then add the prior and post data to that, then divide by 4.

Here is an example 10, 12, 14. Filtered pivot point (12) is (10 + 24 + 14)/4 = 12. It is a weighted average. A running average can be used as the zero compare for the first point, the last point is less than or equal, but not greater than the first point. Then interpolate the last bit of time. For me it is best to work in sample interval ticks, and implement the sample timing with no or minimal software dependence. Something like CTC on an AVR. It seems you are doing more of an input capture method. That may work too, I am not so clear on interpolation from that.

I'm running the sampling timer from the system clock which is 100MHz, and load its value to be 15625-1,

**Ali_dehbidi wrote:**

I'm running the sampling timer from the system clock which is 100MHz, and load its value to be 15625-1,

Do you load that in timer interrupt to limit count in software (measurements have jitter), or at initialization time to limit count in hardware (measurements have no jitter)?

Also, since the sampling is based on your system clock, you really make 3200 measurements per second, regardless of mains frequency, so your sampling is not synchronous to mains, and you cannot say you sample 64 times per mains cycle.

In any case, with that kind of captured ADC data, you can only determine frequency accurately from whole cycle, not from period of positive cycle, since the measurements have DC offset, or the waveform is distorted because positive and negative halves have unequal loads.

I have load that initialization time to limit count in hardware.

I have just added 10.5 to every sample and the magic just happened! Now my readings are with in less than +-0.1Hz, but there is another problem.

When the ADC input voltage is less than about 50mv, the error increase to something like 2-3Hz.

Sometimes it helps to work in a spreadsheet. Setup the ability to simulate the data, sampling rate, change offset, magnitude, frequency, harmonics and noise. I use multiple columns for summing harmonics and noise. Then test your algorithms, use integer math. There are functions to help with that.

I find it helps improve intuition, and grasp the load of the calculations. Then move to software development.

It may become apparent why adding 10.5 works, but there are better ways. Japael, is correct it takes a complete cycle.

When the signal is low, there are granularity and possibly noise problems.

The frequency of mains varies with the load of the grid, though this is limited to +/- 0.1Hz or so. On the short-term, about a 15 minutes, it's quite stable.

There is a website that measures the mains frequency in the UK, with an AVR, down to 2 decimals and presents it live and with history.

There is a website that measures the mains frequency in the UK, with an AVR, down to 2 decimals and presents it live and with history

Would you mind telling the web address.

@jayjay1974,

Have you tried measuring for yourself? That UK website looks suspiciously like a scam.

It should be relatively simple to monitor the mains frequency with an AVR.

I guess that an emergency site generator will have poorer frequency stability.

The new farmer here still has my old generator. But no serious loads to use it !

I used to notice the change of revs on the diesel engine when large refrigeration compressors started.

David.

Yes, about a year ago I did a feasibility study to use mains as a calibration source for a resonator clocked MCU with RTC; not on an AVR though, but a LPC2148.

I measured over fairly long times, like 5 minutes and used a least squares algorithm over many of these samples. Over a very long time the average frequency should be 50.000Hz or so, with the least squares I tried to find that average (inspired on time stamping frequency counters).

High experimental, and never got to actually finishing it. The long times required for testing did not make it any easier too.

Just clocking the MCU from a crystal instead of resonator was a way more sane solution then these software-fixes for bad hardware design choices :D

If you think the UK site is a scam, there are more sites that monitor the UK grid frequency, though not real time. I do remember seeing an PCB with an AVR on the site, but it seems they removed it.