DSPRelated.com
Forums

extracting ultra accurate phase with FFT

Started by myjtag 6 years ago9 replieslatest reply 6 years ago446 views

Hi

Hi,
I was doing some experiments in Matlab, and write this code to experiment with it! I want to know if it's possible to extract accurate with in -+0.01 Degree phase info from samples of an ADC, the matlab FFT function says Sure we can! But it's wired somehow!  It would get me very accurate results, is it doable in a real-world scenario?

I assumed a 64 Sample per Cycle in my Wave under test.

Here is the matlab code

t=0:2*pi/64:2*pi-2*pi/64;
 R=sin(t+pi*178.03/180);
 FFT=fft(R);
 angle(FFT(2))*180/pi

After this code I start to do some measurements on my Real hardware, and I have Increased my sample rate to 128 samples per cycle.

I have made some measurements with my System, which is a Cortex M4@200MHz device and an external ADC, I have a precision source injecting Voltages and currents to my ADC which is connected to  CT and PT's, the first 4 channels are CT’s and the last 4 channels are PT's. I have Injected some sin waves to the system from 40Hz to 400Hz and in the 50Hz zone I have incremented the frequency by 0.1Hz, also I have tested the system with various phase angles with the channels, the sampling frequency of my ADC is 6400 sample/sec and my ADC is a true simultaneous one! Here is the results, when I extract the phases respect to the V0 channel and in the 50Hz region, with different phases the extracted Phase is with in good ranges, but as the frequency changes the error would increase, I have only 128 samples in a full 50Hz cycle and I cannot increase my sample rate higher due to my system over head, also I should extract all the phase and frequency of the waves from this 128 samples, roughly 5ms Regarding that I have a ton of other things to do! fill free to play with these data to see if you could suggest a good enough solution to extract phase and frequency info with under 0.1 degree for phases and 0.01Hz for frequency. and all the extracted waves are ready to be injected into matlab 


Here you can get the wave files 

https://ufile.io/5b7y5

[ - ]
Reply by OlegBelovJune 13, 2018

FFT is not a good solution for this task. If your signal is clean enough and if you know the frequency with high precision you can build the not orthogonal basis of sine and cosine waves of this frequency and, probably, from the constant and then to solve a least squares problem.

basis = [sin(2*pi*f*t), cos(2*pi*f*t), ones(t)]  // where t is columnar

y = (basis' * basis) \ (basis' * x)

If the signal is dirty (contains components with non-Gaussian distribution or a significant noise out of band in interest) you should use zero-phase filtering. Be careful - if you want to use filtering in FFT domain use a window with a flat plateau and apply LS only to this part of epoch. More robust is a filtering in time domain by symmetric FIR or by IIR in forward and backward directions, but you should have extra data before and after the analysed epoch.

If the frequency is not known with enough precision then you can make iterations with calculation the phase in first and second halves of epoch and correction of the frequency estimation by the phase difference.

[ - ]
Reply by myjtagJune 13, 2018

Thanks OlegBelov for your suggestions,

I'm almost newbie into DSP world, I think my signal is reasonably clean,but I do not know it's frequency with precision, actually I should measure the frequency with the samples taken from ADC too. Also would you please explain more on the build the not orthogonal basis of sine and cosine waves, I do not get it fully and so I can not impelement it in my hardware, do you recommand and tutorial or articles or books on this subject?

[ - ]
Reply by OlegBelovJune 13, 2018

For the theory in depth see https://en.wikipedia.org/wiki/Non-linear_least_squ... as a starting point. Really you don't need to understand all this theory, because your case is very simple. The basis is almost orthogonal and the convergence is excellent.

Try to build basis and to solve the system as in my previous post. (I am not sure that Matlab function 'ones(matrix)' produces the matrix of ones of the same size as it's argument, I use Scilab). For phase calculation take argument of the complex number built from cos and sin components, returned by LS.

The initial guess about frequency you can find from FFT or by the measurement of distance between zero crosses.

For implementation in hardware your should have the procedure for inversion of matrix 3x3 (if your data contain constant part) or 2x2. The last one is attached.  

ls2rt.h

ls2rt.c

[ - ]
Reply by myjtagJune 13, 2018

Thanks OlegBelov, relay appriciate your help in here, Big thumbs up.

[ - ]
Reply by Y(J)SJune 13, 2018

Why not use a PLL ? 

Y(J)S

[ - ]
Reply by myjtagJune 13, 2018

Because there are 8 chanles of data, and the product does not have enough space for additional circuits.

[ - ]
Reply by Y(J)SJune 13, 2018

I meant a PLL in software (no additional circuitry).

It is much less work than an FFT and much better at finding phase of a sine in noncorrelated noise (that is what it is for).

Y(J)S

[ - ]
Reply by myjtagJune 13, 2018

Dear Y(J)S

Thanks for the update, I did noy know we have had PLL's in software!!! Would you please intrduce furture learning material? where should I start? is there any tutorial or sample code?

[ - ]
Reply by Y(J)SJune 13, 2018

It's very easy. Assuming that you want a PLL and not an FLL (frequency locked loop) you run an oscillator (called the NCO) of the correct frequency, deduce the phase difference (multiply and use some nonlinearity - there are various types), pass the difference through the loop filter (usually an IIR filter) and feedback the filtered error. There is a huge literature on the options.

Google "digital PLL software" and I am sure you will find example code.

Y(J)S