Phase angle calculation - Page 1
Forum section: electronics / projects

author: kvresto
author_rank: Regular Contributor
timestamp: April 19, 2016, 11:12:21 am
content: Hi Everyone.I’ve been trying to calculate the phase angle between two sine waves differing only in phase, and I’ve got it working in MATLAB, using the FFT of each sine wave and then applying MATLAB’s angle function. (as an example I think from the mathworks site??)Now I’m trying to do the same with the STM32F3. I’m using the DSP Lib that can be downloaded from ST, and I’ve gotten as far as the FFT part, but as I’m not at all familiar with the library, I’m hoping someone with more experience can help with some direction as to how to get the answer I’m looking for. Unfortunately I'm also a bit hazy on the math's, so not starting from a strong base, but the Lib should be able to do most of the hard work.Any ideas??thankskvresto

author: coppice
author_rank: Super Contributor
timestamp: April 19, 2016, 11:21:47 am
content: You might want to seek help with a much simpler and more accurate approach before you look for help with your current solution.One simple and effective approach is to take the inner product of the two waveforms, and the inner product of the two waveforms with one delayed by a well known amount (e.g. a whole number of samples). You now have two measures of signal correlation. If the two waveforms are exactly in phase you will see the maximum possible correlation. If they are exactly in quadrature you will get zero correlation. Apply a little trigonometry, you will get your answer with good precision.

author: JPortici
author_rank: Super Contributor
timestamp: April 19, 2016, 11:23:47 am
content: F3 has a cortex M4 with FPU, right? if it's the case you ABSOLUTELY have to use it. 512 pt fft done on a 24 MHz cortex m3 took like 100 msAnyway, you should look at the cmsis manual. if i remember correctly the fft routine returns a structure with two series of data: real and imaginary bins from 0 to Fs (or, if you want.. first is DC then for the rest the first half is from dc to Fs/2 and the other half to -FS/2 to dc)then you find out the phase in the usual mannersQuestion: you say quote "two sine waves differing only in phase"i assume that the module and the frequency is identical.. can't you find out the phase by other simpler means? (academic purpose maybe?)

author: kvresto
author_rank: Regular Contributor
timestamp: April 19, 2016, 12:19:30 pm
content: coppice, thanks for your advice, I will look into the method you described.JPortici, your comment was:Quotecan you go into a bit more detail on how to do this academically, and using the DSP Lib?Also which FFT function are you referring to, is it arm_rfft_fast_f32()?

author: JPortici
author_rank: Super Contributor
timestamp: April 19, 2016, 03:17:03 pm
content: that one, if you want to work with floating point (and you want to)the result will be of two arrays in the form a + i*b, where n is the frequency bin. from that, finding out the phase is trivial (you should also have ready made functions in the cmsis as well. again, refer to the cmsis documentation)

author: KE5FX
author_rank: Super Contributor
timestamp: April 19, 2016, 06:13:47 pm
content: Lots of ways to skin this particular cat. Rather than a full-blown FFT, you might consider running the sines through Hilbert transforms, and taking atan2(q,i) on the resulting analytic signals.

author: DanielS
author_rank: Frequent Contributor
timestamp: April 19, 2016, 11:24:10 pm
content: I like the dual convolution method: if the two signals are the same amplitude and frequency (simply normalize both to eliminate amplitude as a concern) then the result will be 0.5 if the two waveforms are in-phase, -0.5 if they are 180° out of phase, 0 if they are +/- 90° out of phase, sqrt(1/8) for +/- 45°, etc. You need the second convolution with a delayed waveform to discriminate which quadrant you are working in.

author: kvresto
author_rank: Regular Contributor
timestamp: April 19, 2016, 11:56:48 pm
content: thanks all for your comments.DanielS the waveforms will not be the same freq and ampl will change as per the application.I'm using matlabs angle function, which is actually the atan2() function. How would this same process be done in my case(DSP_Lib), and please don't say its "trivial" againPS: if your not sure, just say so, were all just learning here, I know I am.

author: coppice
author_rank: Super Contributor
timestamp: April 20, 2016, 02:52:01 am
content: Quote from: DanielS on April 19, 2016, 11:24:10 pmI assume you mean dual correlation, not dual convolutuion, and are referring to what I wrote earlier. What you describe would give very poor accuracy for a wide range of phase shifts. First, two signals would rarely be the same amplitude after some manipulation. A practical solution would need to work out their relative gains with, say, a pair of RMS measurements conducted in parallel with the correlations. You would have very poor accuracy when the signals are nearly in phase, as the difference in correlation between signals in phase and signals one or two degrees out of phase is very small. As the phase difference increases the measurement accuracy would improve. Above 20 degrees or so, the measurement would be pretty good. The whole point of using delayed and undelayed signals is to avoid this. With the results of the two correlations, and some trigonometry, you will get a fairly balanced level of accuracy for any phase shift, and the relative gains of the two channels doesn't matter.

author: kvresto
author_rank: Regular Contributor
timestamp: April 20, 2016, 05:38:29 am
content: Also KE5FX, how is what you have suggested too different from a straight up FFT?, its the atan2 part I'm looking to solve using this Lib for anyone with experience, ie how to format my fft results so as to plug them into atan2? Its probably trivial!

author: KE5FX
author_rank: Super Contributor
timestamp: April 20, 2016, 07:16:42 am
content: Quote from: kvresto on April 20, 2016, 05:38:29 amThe Hilbert transform would likely be implemented with an FIR kernel, which might or might not outperform an FFT of a given size depending on how the pipelining is done. It's just two ways of doing the same thing.I'd suggest having a look atthis threadon comp.dsp, as well as Googling "polar discriminator."

author: coppice
author_rank: Super Contributor
timestamp: April 20, 2016, 07:32:10 am
content: Quote from: KE5FX on April 20, 2016, 07:16:42 amThe effectiveness of a Hilbert transform, implemented by the traditional FIR approach, very much depends on where the frequency of the signal of interest sits in the band. Just a few FIR terms is enough to build a pretty accurate transform if the signal is near the middle of the band, but it takes a huge number of terms if the signal is near one end of the band. You can implement a pseudo-Hilbert using 2 IIR filters, which shift the signal in two directions, so their mutual outputs are 90 degrees apart at all frequencies. So, all is not lost if the signal is near one end of the band, but you need to take considerable care. You will still need to perform correlation between the analytic signals from the Hilbert transforms, and do trigonometry with the results, or the answer will be very susceptible to noise.

author: wolf32d
author_rank: Contributor
timestamp: April 20, 2016, 09:52:56 am
content: Quote from: kvresto on April 19, 2016, 11:12:21 amjust calculate the xcorr (cross correlation) between the two functions and take the absolute maximum of the result

author: kvresto
author_rank: Regular Contributor
timestamp: April 20, 2016, 01:14:57 pm
content: wolf32d, thanks, how do you then define the lag in terms of degrees phase shift?I don't know what the "absolute maximum " is all about?Have you tried this with signals of different amplitude, but with the same freq?

author: mark03
author_rank: Frequent Contributor
timestamp: April 20, 2016, 03:35:25 pm
content: Quote from: kvresto on April 19, 2016, 11:56:48 pmIf the two waveforms aren't the same frequency, the phase angle is  a continuously changing quantity. How far apart in frequency are we talking here? Most of the proposed methods assume an average over many cycles...

author: kvresto
author_rank: Regular Contributor
timestamp: April 20, 2016, 11:07:09 pm
content: mark03, its an (experiment)cct, that will measure ESR, and impedance of a capacitor(for now).Series RC with voltage measured across Rs and Cs. Freq is fixed, but ampl will change.cheers

author: kvresto
author_rank: Regular Contributor
timestamp: April 20, 2016, 11:27:04 pm
content: Also thanks everyone for some very good information. your help is very welcomed.Matlab is now running, and I've got my old text books out, having fun.kvresto.

author: wolf32d
author_rank: Contributor
timestamp: April 21, 2016, 06:49:44 pm
content: Quote from: kvresto on April 20, 2016, 01:14:57 pmThere you go:Code:% generate some signalssampling_step = 0.01;t = 0 : sampling_step : 4*pi; %generate a timebasesamples_per_period = 2*pi / sampling_step;v1 = sin(t);phase = pi/5; % manually introduce an arbitrary phase shiftv2 = sin(t-phase);plot(t, v1, t, v2);%%%%%%%%%%%%%%%%%%%%%%%% now he have v1 and v2 i.e. our simulated signalscorrelation = xcorr(v2,v1); %evaluate cross correlation[corr_max, corr_argmax] = max(correlation); %evaluate the max of correlation and its position%plot(correlation);measured_phase_in_samples = corr_argmax - length(correlation)/2; % evaluate distance of max position from the centermeasured_phase_angle = (2*pi / samples_per_period) * measured_phase_in_samples % convert to fraction of period (2 pi) i.e. agle in radians% should be equal (or very close to) "phase"%evaluate phase in degreesmeasured_phase_angle_deg = 180 * measured_phase_angle / piif you have real signals you should evaluate "samples_per_period" by other meanse.g. if you sample a 10Hz signal at a sampling rate of 1kHz you get samples_per_period = 100

author: kvresto
author_rank: Regular Contributor
timestamp: April 21, 2016, 11:26:21 pm
content: Quotegood example wolf32d. Something like 1/f *Fs should do it. EDIT: better yet decimate over a larger sample range.Also the result is about 1.5 degrees off, seems close enough, can it be improved? (I'm still testing with it).kvresto

author: coppice
author_rank: Super Contributor
timestamp: April 22, 2016, 11:42:50 am
content: Quote from: EmmanuelFaure on April 22, 2016, 10:37:50 amYour approach assumes the gains of the two signals are identical, which is unlikely to be the case. Its also assumes you aren't looking for a great deal of accuracy, because the accuracy is going to vary a lot with the size of the phase shift. The correlation approach only requires 2N multiples, and solves both issues.

author: kvresto
author_rank: Regular Contributor
timestamp: April 22, 2016, 12:21:34 pm
content: EDIT:

author: wolf32d
author_rank: Contributor
timestamp: April 22, 2016, 01:52:16 pm
content: Quote from: EmmanuelFaure on April 22, 2016, 01:28:48 pmLOL WHAT WAS I THINKING? XCORR SCALES o(len^2)I'm very attached to the xcorr function (I used it a lot to calculate delays in complicated signals where only correlation helps)... but your solution is actually VERY GOOD for sinusoidal stuff,besides, if the two signals have different gains and offsets this transform will do the trick(works a treat also with noisy stuff):Code:% REMOVE OFFSETy1 = y1-mean(y1)y2 = y2-mean(y2)% divide by rms and sqrt(2) i.e. NORMALIZE TO 1 (0 to peak)y1 = y1/(sqrt(2) * std(y1))y2 = y2/(sqrt(2) * std(y2))conclusion:trigonometric method:-pro: fast-con: a bit unreliable if signals are not stable in terms of gain and offset or are nonlinearly distortedxcorr method:-pro: robust if signals have harmonic distortion & shit-con: very slow