## Measuring frequency based on ADC samples

25 posts / 0 new
Author
Message

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?

I love Digital
and you who involved in it!

Internal RC oscillator or external crystal?

- Brian

external crystal.

I love Digital
and you who involved in it!

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.

Warning: Grumpy Old Chuff. Reading this post may severely damage your mental health.

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.

It all starts with a mental vision.

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

It all starts with a mental vision.

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 calculate frequency base on this formula
1600/(Second_zero â€“ first_zero)

KitCarlson would you explain your algorithm more?

I love Digital
and you who involved in it!

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.

It all starts with a mental vision.

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?

Quote:
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?
I will send some ADC readings and calculated zero crosses for you, as soon as possible.

I love Digital
and you who involved in it!

```-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 love Digital
and you who involved in it!

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.

It all starts with a mental vision.

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.

It all starts with a mental vision.

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

I love Digital
and you who involved in it!

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 love Digital
and you who involved in it!

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.

I love Digital
and you who involved in it!

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.

It all starts with a mental vision.

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.

Quote:
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.

I love Digital
and you who involved in it!

@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.