Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

FFT frequency measurement VS measuring signal's period with timer

Status
Not open for further replies.

immortal13

Newbie level 6
Joined
Mar 31, 2013
Messages
11
Helped
1
Reputation
2
Reaction score
1
Trophy points
1,283
Activity points
1,348
Hello!

I am working around a project, in which I have to measure a frequency of the signal coming to STM32 microprocessor. The frequency is about 2210 Hz.

I have done it by measuring period of square wave (sine wave passed through comparator) with Timer and then I have tried to appoximate it (array of period measurements is of about 100 elements) using moving average and least square fitting. Both results are about the same.

So, the question is - could I improve the frequency measurement accuracy by at least one order, using ADC convertion of sine wave (without passing through comparator) and then using FFT?

Any help would be appreciated!
Viacheslav.
 

Single Freq measurement is usually done either by counting the number of cycles in a fixed period, or by measuring the time period of some fixed number of cycles.

Period measurement should give the better accuracy, independent of input freq, as long as your timer is running at a sufficiently high rate. The higher the better.
I don't think an FFT will give better resolution, unless you want to detect/ measure multiple frequencies simultaneously.
 

The main problem is time for measuring period of signal. I have only 50 ms to do it and this measurement results in about only 100 measured periods(integer values) in output array. Input signal is noisy. Smoothing this array with moving average and than getting average of the whole array gives very good accuracy, but unfortunately not enough. Approximating with least squares fitting also can't give enough accuracy.

So, I would like to know, if I have any chance to get better accuracy with FFT in such small period of measurement.

I have 12-bit ADC with maximum rate of 7.2 MSPS, so on 50ms cycle it can result in 360 kSamples.
Is it really impossible to get better accuracy?
 

Taking 360 kSamples over 50 msec. sounds like over-kill, and it does not really help very much. The time period over which the samples are taken is much more relevant, and that you say is fixed at 50 msec. Doing an FFT over 50 msec. means that the frequency bins will be 20 Hz. apart, regardless of how many points are in the FFT. So if you measured frequency by simply finding the bin with the maximum amplitude, the resolution will be 20 Hz. However there are interpolation techniques that allow you to estimate the actual frequency by using the amplitude in the peak bin together with the amplitudes in the bins adjacent to the peak. I have used such a technique to realize a 10x improvement in resolution over the simple "which bin has the largest amplitude" method. So that would bring your 20 Hz resolution down to 2 Hz. Is that good enough?

If the signal you are dealing with is essentially a sine wave of a very stable frequency plus some Gausian noise, I think something like this might be optimal:

1. Since you already know the frequency is about 2210 Hz, perform a correlation between the signal and one complete cycle of a 2210 Hz sine wave. Slide the one cycle pattern from one end of the 50 msec sample to the other. At each point take the sum of the products of the signal and the pattern. This will filter a lot of noise, but will reduce the 50 msec. sample to 49.6 msec because the pattern needs to be completely contained within the 50 msec. window.

2. Set thresholds with some hysteresis to convert the correlation function to a square wave.

3. Measure the time for ~100 cycles of that square wave to calculate frequency.

Assuming the phase of the square wave has a combined error at the beginning and the end of no more than 1/10 of a cycle at 2210 Hz (36 degrees), you have the frequency to an accuracy of 2 Hz. If you can nail the phase down to 3 degrees at both ends (6 degrees overall) then you have the frequency to within 0.33 Hz. If the noise in the signal is preventing you from locking on to the phase to the accuracy that you need, use a 2-cycle correlation pattern instead of a 1-cycle pattern. That way each point in the correlation array is the result of averaging over nearly 1 msec. of raw data. Using a 2-cycle correlation pattern also reduces the size of the correlation array by another cycle (because the sliding pattern needs to fit within the 50 msec. window), but that still leaves you with more than 49 msec. of correlation values. This process of using a larger correlation pattern can be continued until one of the following things happens:

1. The size of the correlation computation outstrips the computational capabilities of your processor.
2. The discrepancy between the 2210 Hz pattern and the actual frequency degrades the correlation values (poor pattern match).
3. The reduction in the window size down from 50 msec. due to having the correlation pattern fit at both ends means the final frequency is calculated over too few cycles of the square wave.

I think you will reach your desired frequency accuracy long before any of these three things happen.
 
Thank you very much! I hope it will help me in achieving the desired result.
 

Ok, I have gone another way and done these steps with a square wave:

1. Reduce the sampling frequency to 21.3 kHz, so it gives 1067 samples on 50 ms cycle
2. Pad it with zeroes to 2048 samples and take an FFT
3. Calc the frequency with parabolic interpolation

So, now I have 0.213 Hz standard deviation of measurements. But it has to be 0.01 Hz

But I didn't do anything with a phase of the signal. Could someone give an advice in further reducing of standard deviation?
Maybe I should do something with a phase of signal or try to do these things with a sine wave? Or anything else?

P.S.: The signal is buried in some noise. Without this noise the standard deviation of measurements is 0.043 Hz

Thanks in advance!
Viacheslav
 

Are you taking the FFT of a square wave? I thought you said the signal was originally a sine wave, which you passed through a comparator. You might get better results if you analyze the sine wave without the comparator.
 
Ok, thank you! I will try to do it.

Are you taking the FFT of a square wave? I thought you said the signal was originally a sine wave, which you passed through a comparator.

Yes, I am. I'm not good in electronics and there are some problems for me with that signal (at some moments amplitude excursion of signal is very high), so I tried to do it with square wave.. :)
 

One possible problem with converting to a square wave first is that the effect of the noise may actually be worse, especially if your conversion to a square wave involves comparators with hysteresis. If you have any hysteresis in your comparators then a very short noise pulse that would have had a small effect on the FFT of the sine wave, will instead cause a longer-lasting level change and therefore show up more prominently in the frequency spectrum. But frankly I think you are doing about as well as can be expected, getting within 0.213 Hz with only 50 msec. samples. Are you sure there is no way you can cheat? If the requirement is only to produce an updated answer every 50 msec., you might not need to limit yourself to FFTs covering only 50 msec. You might form a FIFO of samples, perhaps 500 msec. long. With each new 50 msec. sample, add that sample on to the end of the FIFO and drop the first 50 msec. Then FFT the whole thing every 50 msec. That will give you an answer every 50 msec. (assuming the signal is continuous). The only trouble is when the frequency does change it will take your FIFO a full 500 msec. to fully switch over to the new frequency. In the interim there will be calculations that gradually transition from the old frequency to the new frequency. But if this signal just appears out of nowhere, lasts only 50 msec., the disappears, then you are stuck. No cheating is possible.

I noticed you said you used parabolic interpolation. I used that on my musical instrument tuner app initially. But I found that I could do better by constructing a look-up table post-processor to the parabolic interpolation. I developed the lookup table by generating signals of various frequencies in software and then applying parabolic interpolation to them. Since I generated the signals in software, I know exactly what their frequencies are. I divided the range of +/- 1 frequency bin up into 64 table entries and then just searched the table to find the range that best fit any particular parabolic interpolation. Also, things like padding with zeroes and windowing the time series before the FFT do have an effect on the accuracy of parabolic interpolation, so if you are going to develop a lookup table, make sure you develop it using the same padding and windowing as you plan to use on the real signals. FWIW, I tried windowing, but I don't do it anymore, as it seems to affect only the low frequency end of the FFT.
 

No, unfortunately I don't have any ways to cheat and I need to get new measure every 50 ms.

The final result is the same as I've got it using CCP unit of timer. FFT could be better in this issue, but I think only for signals with very low SNR.

Thank you for your help!
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top