# Finding PHASE between two sinusoids with FFT/DFT (ArduinoFFT w/ C)

I am having trouble finding a known phase between two data sets, lets call them data set 11 and data set 12. I am obtaining a sample size of 1024 samples, at a sampling rate of 500kHz with a total sample time of 2.048ms.

All data and code used in this question can be found at this repository - https://github.com/smake5730/fft_phase/graphs/contributors

As can be seen from the sample data below the two data sets show the voltage is leading the current by around 90°. (zoomed in)

When I compute the FFT with 1024 bins I get clear peaks. (zoomed in)

I apply the Hanning window during this and do not use zero-padding.

I use the location of the largest peak with the atan2(a/b) method to obtain the phase and find that I get the following below. The first data gives me +90° and the second data gives me -90°. The frequencies are correctly identified.

I have tried adding zero-padding to the end of the signal and it does not solve the issue. I have also tried upsampling and it does not give the correct phase either.

Does anyone have any ideas/hints on what I could try or where I am going wrong?

EDIT As was pointed out below, my code takes individual bins and incorrectly matched bins were used in the second set.

• This simplest, I should have mentioned earlier, is line up your frame on a whole number of cycles and you can read the phase values right from the bin. If you are off by one sample in 1000, that's three significant digits. On a run of say 10 1/2 cycles, assuming the tone is steady, you can expect 6 or 7, maybe more, significant digits. Depends on the signal. Again, you only need to calculate the bins of interest, not the whole DFT n either approach. Jul 20 '20 at 16:28

A couple of things I’ve noticed, the combination of which likely is at the root of the issue. First, when you apply a window, you are applying a linear phase shift to the frequency transform. You could subtract it out, and it would probably fix the issue. This wouldn’t necessarily be a problem except...

Second, your code calculates the max values for the magnitudes independently for the current and voltage. This means that you are comparing the phase for different bins. Again, this would not be an issue (mostly) if not for the phase shift resulting from the windowing.

You could either remove the phase shift from the windowing, be sure to use the same bin for voltage and current phase, or do both. Mr Dawg is right that there are other/better ways to do this, but I wanted to help out considering this technique should work.

Edit: Also, I don’t know how that library works, but you may want to restrict your search for peaks to the first half of the Transform output. Phases in the second half will be negative.

• Hi , thanks for your input. Your Your input about the incorrectly matched bin number was correct. ( I added a screenshot of this into my question. Do you have any resource on this phase shift from windowing AND how to remove it? Jul 21 '20 at 7:46
• It’s not exactly common practice, but here’s what’s up. The delay for a ‘window’ function is (L+1)/2, the mid point of the window. The phase of a linear delay kernel is e^(-j*2pikd/N), where k is the bin, d the delay, N is the length of the DFT. If you have the DFT of a windowed signal, you’d multiply by the complex conjugate of the above for k = 0 to N/2. Then X[N-k] = the complex conjugate X[k]. This will remove the delay of the window. That being said... Jul 22 '20 at 0:53
• Swap the first half of the windowed signal with the second half before taking the FFT. Since your window is an even number of samples, it won’t be exactly right, but it’s probably close enough given what you’re trying to do. It’s waaay easier. Jul 22 '20 at 0:56

You can't do better than this for accuracy in my experience.

Select a frame size of 1 1/2 cycles or 2 1/2 cycles.

You only need to calculate two bins, either 1 and 2, or 2 and 3. No need for a full DFT. So it is very efficient as well. By placing the frequency squarely near the center of the two bins you minimize noise effects and avoid needing to deal with near bin frequencies which call for a different set of equations for the fitting vector.

The alternative form is for when the frequency is really close to a bin.

There are other tricks to do it point by point. I'll let others provide those.

• Hello Cedron, thanks for your input. Your solution does help but I feel Dan's solution was more specific in solving my issue quicker. But thank you for your input Jul 21 '20 at 7:51
• @smake5730 You're welcome. It is rather complicated solution, but as far as I know the best for the most precision for very small DFT frames. The issue is with a real valued signals you actually have two complex tones in the DFT. When the samples per cycle put you close to DC or Nyquist (yours is "close" to DC), the conjugate tone interferes with measured bin tone. This is accounted for in my formulas, which is why they are more accurate. Ditch the window, for a pure complex tone (which a real tone approximates near bins) the phase shift for being off bin is linear. Jul 21 '20 at 10:59
• (con't) Ditch the window, for a pure complex tone (which a real tone approximates near bins) the phase shift for being off bin is linear. So do a Goertzel (the equivalent of a single DFT bin), and try to hit a whole number of cycles on a much smaller frame. A DFT is essentially an average. Longer frames give better noise reduction, but not better readings on a pure steady tone. Jul 21 '20 at 10:59

Supplement on the nature of your source data

While testing my pll software simulator, I ran it on the voltage/current datasets of your github reference and noticed an unusual behavior of the phase detector output (phase error). Intrigued, I've computed fft of your dataset voltages/currents.

The voltage's FFT is quite smooth, phase noise at the end of the range is due to quantization noise:

But the current's FFT shows a nonlinearity of voltage-to-current conversion (if the dataset's current is generated from the dataset's voltage by some electronic circuit). Notice third and fifth harmonics in an ABS(FFT) graph and nearly full circle phase noise in ARG(FFT):

Nonlinearity in current can be attributed to a phase modulation sort of $$cos(2\pi{\omega}t + (\alpha + \beta cos^2(2\pi{\omega}t))\gamma cos^2(2\pi{\omega}t)*normalDistRandomFunc(mu,sigma))$$ which generates FFT like in the below picture It would be interesting to know the origin of those github datasets and how they are related with phase noise/phase distortion.

This strong phase noise is hardly noticed when inspecting dataset current waveforms. Yet, when present, it aggravates processing of affected signals.