I want to estimate the phase of harmonic distorted tones when having input tones with random initial phase within [-pi;pi]. I used atan2, build-in function of Matlab, however the phase jump at -pi or pi makes my calculation of phase difference having trouble.
The problem is as follow: there is a nonlinear system, and I want to estimate system's response (amplitude and phase responses). I insert many tones as x[n] = Acos(2pifn*t+b), where fn is frequency, b is the initial random phase within [-pi;pi], and it changes with various tones. If a tone has initial phase b, then 2nd order harmonic distortion (HD) has phase of c=2b, and 3rd HD has phase of d=3b. The phase differences of the HD2 and HD3 could be c/2-b and d/3-b, respectively. Because of the memory effect of the system, the phase differences are no longer zero.
Issues: if the phase of input signal is large, e.g., 70 degree, then HD3 phase is 210 degree, when the phase angle >180, atan2 operation makes a jump to -180 and the HD3 phase become -150 degree instead of 210. Theoretically, cosd(210) = cosd(-150). However, what I want to find is the phase difference. That why, (-150/3-70) leads to a wrong results (it should be 0 if there is no memory effect). Similar situation for the case if input signal has large negative phase and for both HD2 and HD3. The major cause is antan2 limitation of [-pi;pi], and I want to expand to [-3pi;3pi].
Please help.
Thank you very much.
Regards
The function you want is unwrap, e.g.,
>>> angles=[-0.7*pi -0.9*pi 0.9*pi 0.7*pi]
angles =
-2.1991e+00 -2.8274e+00 2.8274e+00 2.1991e+00
>>> unwrap(angles)/pi
ans =
-7.0000e-01 -9.0000e-01 -1.1000e+00 -1.3000e+00
Related
From my understanding, when using the cpsd function as such:
[Pxy,f] = cpsd(x,y,window,Ns,NFFT,Fs);
matlab chops the time series data into smaller windows with size specified by you. And the windows are shifted by Ns data point. The final [Pxy, f] are an average of results obtained from each individual window. Please correct me if I am wrong about this process.
My question is, if I use angle(Pxy) at a specific frequency, say 34Hz. Does that give me the phase difference between signal x and y at the frequency 34Hz?
I am having doubt about this because if Pxy was an average between each individual window, and because each individual was offset by a window shift, doesn't that mean the averaged Pxy's phase is affected by the window shift?
I've tried to correct this by ensuring that the window shift corresponds to an integer of full phase difference corresponding to 34Hz. Is this correct?
And just a little background about what I am doing:
I basically have numerous time-series pressure measurement over 60 seconds at 1000Hz sampling rate.
Power spectrum analysis indicates that there is a peak frequency at 34 Hz for each signal. (averaged over all windows)
I want to compare each signal's phase difference from each other corresponding to the 34Hz peak.
FFT analysis of individual window reveals that this peak frequency moves around. So I am not sure if cpsd is the correct way to be going about this.
I am currently considering trying to use xcorr to calculate the overall time lag between the signals and then calculate the phase difference from that. I have also heard of hilbert transform, but I got no idea how that works yet.
Yes, cpsd works.
You can test your result by set two input signals, such as:
t=[0:0.001:5];
omega=25;
x1=sin(2*pi*omega*t);
x2=sin(2*pi*omega*t+pi/3);
you can check whether the phase shift calculated by cpsd is pi/3.
I have two sensors seperated by some distance which receive a signal from a source. The signal in its pure form is a sine wave at a frequency of 17kHz. I want to estimate the TDOA between the two sensors. I am using crosscorrelation and below is my code
x1; % signal as recieved by sensor1
x2; % signal as recieved by sensor2
len = length(x1);
nfft = 2^nextpow2(2*len-1);
X1 = fft(x1);
X2 = fft(x2);
X = X1.*conj(X2);
m = ifft(X);
r = [m(end-len+1) m(1:len)];
[a,i] = max(r);
td = i - length(r)/2;
I am filtering my signals x1 and x2 by removing all frequencies below 17kHz.
I am having two problems with the above code:
1. With the sensors and source at the same place, I am getting different values of 'td' at each time. I am not sure what is wrong. Is it because of the noise? If so can anyone please provide a solution? I have read many papers and went through other questions on stackoverflow so please answer with code along with theory instead of just stating the theory.
2. The value of 'td' is sometimes not matching with the delay as calculated using xcorr. What am i doing wrong? Below is my code for td using xcorr
[xc,lags] = xcorr(x1,x2);
[m,i] = max(xc);
td = lags(i);
One problem you might have is the fact that you only use a single frequency. At f = 17 kHz, and an estimated speed-of-sound v = 340 m/s (I assume you use ultra-sound), the wavelength is lambda = v / f = 2 cm. This means that your length measurement has an unambiguity range of 2 cm (sorry, cannot find a good link, google yourself). This means that you already need to know your distance to better than 2 cm, before you can use the result of your measurement to refine the distance.
Think of it in another way: when taking the cross-correlation between two perfect sines, the result should be a 'comb' of peaks with spacing equal to the wavelength. If they overlap perfectly, and you displace one signal by one wavelength, they still overlap perfectly. This means that you first have to know which of these peaks is the right one, otherwise a different peak can be the highest every time purely by random noise. Did you make a plot of the calculated cross-correlation before trying to blindly find the maximum?
This problem is the same as in interferometry, where it is easy to measure small distance variations with a resolution smaller than a wavelength by measuring phase differences, but you have no idea about the absolute distance, since you do not know the absolute phase.
The solution to this is actually easy: let your source generate more frequencies. Even using (band-limited) white-noise should work without problems when calculating cross-correlations, and it removes the ambiguity problem. You should see the white noise as a collection of sines. The cross-correlation of each of them will generate a comb, but with different spacing. When adding all those combs together, they will add up significantly only in a single point, at the delay you are looking for!
White Noise, Maximum Length Sequency or other non-periodic signals should be used as the test signal for time delay measurement using cross correleation. This is because non-periodic signals have only one cross correlation peak and there will be no ambiguity to determine the time delay. It is possible to use the burst type of periodic signals to do the job, but with degraded SNR. If you have to use a continuous periodic signal as the test signal, then you can only measure a time delay within one period of the periodic test signal. This should explain why, in your case, using lower frequency sine wave as the test signal works while using higher frequency sine wave does not. This is demonstrated in these videos: https://youtu.be/L6YJqhbsuFY, https://youtu.be/7u1nSD0RlwY .
I'm trying to recover the phase of a simple (audio) signal in matlab:
In matlab I do the following:
% This wave is perfectly periodic in the sample. That is,
% there are exactly 1000 periods.
swave = sin( 2 * pi * (0:10000) * 441/44100);
% Find the fft
sFFT = fft(swave);
% Remove the duplicate data in the FFT
sFFT = sFFT(1:length(sFFT)/2);
% Take a look a the amplitudes from the FFT and it checks out
freqs = 44100/ 2*linspace(0,1,length(sFFT);
plot(freqs, abs(sFFT));
% Now to get the phase
plot(freqs, angle(sFFT));
This result makes almost no sense to me. Because this is a sin wave (not a cos wave). I expect to see 1/2*pi = 1.57079 for the value of the 441hz bin. Instead I see a nearly discontinuous jump from (441, -1.539) to (445, 1.603). Why is 441 so far from the correct value? Why is 445 so close?
The value for all of the bins besides 441 hz are a mystery to me. I've also tried several other methods of recovering the phase including unwrap(angle(sFFT)) and atan2(imag(sFFT), real(sFFT)); These change the output but also do not make any sense to me. Why are bins besides 441 any value but 0 (like the abs(FFT) shows?). Why is the 441 bin close but not the correct value?
Thanks for the help!
To better estimate the phase, change the 0 phase reference to the center of the window by doing an fftshift, which should eliminate most of the alternating phase discontinuities, and then interpolate, but noting that you have changed your 0 point.
Note the the phase of a vector of length zero is meaningless in most cases, and thus anything close is likely just numerical noise (near zero vectors in various random directions) due to finite precision math.
Thus some people just clamp the plotted phase to zero for any magnitude below some noise floor.
I am using the FFT function in Matlab in an attempt to analyze the output of a Travelling Wave Laser Model.
The of the model is in the time domain in the form (real, imaginary), with the idea being to apply the FFT to the complex output, to obtain phase and amplitude information in the frequency domain:
%load time_domain field data
data = load('fft_data.asc');
% Calc total energy in the time domain
N = size(data,1);
dt = data(2,1) - data (1,1);
field_td = complex (data(:,4), data(:,5));
wavelength = 1550e-9;
df = 1/N/dt;
frequency = (1:N)*df;
dl = wavelength^2/3e8/N/dt;
lambda = -(1:N)*dl +wavelength + N*dl/2;
%Calc FFT
FT = fft(field_td);
FT = fftshift(FT);
counter=1;
phase=angle(FT);
amptry=abs(FT);
unwraptry=unwrap(phase);
Following the unwrapping, a best fit was applied to the phase in the region of interest, and then subtracted from the phase itself in an attempt to remove wavelength dependence of phase in the region of interest.
for i=1:N % correct phase and produce new IFFT input
bestfit(i)=1.679*(10^10)*lambda(i)-26160;
correctedphase(i)=unwraptry(i)-bestfit(i);
ReverseFFTinput(i)= complex(amptry(i)*cos(correctedphase(i)),amptry(i)*sin(correctedphase(i)));
end
Having performed the best fit manually, I now have the Inverse FFT input as shown above.
pleasework=ifft(ReverseFFTinput);
from which I can now extract the phase and amplitude information in the time domain:
newphasetime=angle(pleasework);
newamplitude=abs(pleasework);
However, although the output for the phase is greatly different compared to the input in the time domain
the amplitude of the corrected data seems to have varied little (if at all!),
despite the scaling of the phase. Physically speaking this does not seem correct, as my understanding is that removing wavelength dependence of phase should 'compress' the pulsed input i.e shorten pulse width but heighten peak.
My main question is whether I have failed to use the inverse FFT correctly, or the forward FFT or both, or is this something like a windowing or normalization issue?
Sorry for the long winded question! And thanks in advance.
You're actually seeing two effects.
First the expected one goes. You're talking about "removing wavelength dependence of phase". If you did exactly that - zeroed out the phase completely - you would actually get a slightly compressed peak.
What you actually do is that you add a linear function to the phase. This does not compress anything; it is a well-known transformation that is equivalent to shifting the peaks in time domain. Just a textbook property of the Fourier transform.
Then goes the unintended one. You convert the spectrum obtained with fft with fftshift for better display. Thus before using ifft to convert it back you need to apply ifftshift first. As you don't, the spectrum is effectively shifted in frequency domain. This results in your time domain phase being added a linear function of time, so the difference between the adjacent points which used to be near zero is now about pi.
I have several equations and each have their own individual frequencies and amplitudes. I would like to sum the equations together and adjust the individual phases, phase1,phase2, and phase3 to keep the total amplitude value of eq_total under a specific value like 0.8. I know I can normalize the signal or change the vertical offset, but for my purposes I need to have the amplitude controlled by changing/finding the values for just the phases in phase1,phase2, and phase3 that will limit the maximum amplitude when the equations are summed.
Note: I'm using constructive and destructive phase interference to adjust the maximum amplitude of the summed equations.
Example:
eq1=0.2*cos(2pi*t*3+phase1)+vertical offset1
eq2=0.7*cos(2pi*t*9+phase2)+vertical offset2
eq3=0.8*cos(2pi*t*5+phase3)+vertical offset3
eq_total=eq1+eq2+eq3
Is there a way to solve for phase1,phase2, and phase3 so that the amplitude of the summed signals in eq_total never goes over 0.8 by just adjusting/finding the values of phase1,phase2,and phase3?
Here's a picture of a geogebra applet I tested this idea with.
Here's the geogebra ggb file I used to edit/test idea with. (I used this to see if my idea would work) Java is required if you want to dynamically interact with the applet
http://dl.dropbox.com/u/6576402/questions/ggb/sin_find_phases_example.ggb
I'm using matlab/octave
Thanks
Your example
eq1=0.2*cos(2pi*t*3+phase1)+vertical offset1
eq2=0.7*cos(2pi*t*9+phase2)+vertical offset2
eq3=0.8*cos(2pi*t*5+phase3)+vertical offset3
eq_total=eq1+eq2+eq3
where the maximum amplitude should be less than 0.8, has infinitely many solutions. Unless you have some additional objective you'd like to achieve, I suggest that you modify the problem such that you find the combination of phase angles that has a maximum amplitude of exactly 0.8 (or 0.79, such that you're guaranteed to be below).
Furthermore only two out of three phase angles are independent; if you increase all by, say, pi/3, the solution still holds. Thus, you have only two unknowns in eq_total.
You can solve the nonlinear optimization problem using e.g. FMINSEARCH. You formulate the problem such that max(abs(eq_total(phase1,phase2))) should equal 0.79.
Thus:
%# define the vector t, verticalOffset here
%# objectiveFunction is (eq_total-0.79)^2, so the phase shifts 1 and 2 that
%# satisfy this (approximately) should guarantee that signal never exceeds 0.8
objectiveFunction = #(phase)(max(abs(0.2*cos(2*pi*t+phase(1))+0.7*cos(2*pi*t*9+phase(2))+0.8*cos(2*pi*t*5)+verticalOffset)) - 0.79)^2;
%# search for optimal phase shift, starting at no shift
solution = fminsearch(objectiveFunction,[0;0]);
EDIT
Unfortunately when I Try this code and plot the results the maximum amplitude is not 0.79 it's over 1. Am I doing something wrong? see code below t=linspace(0,1,8000); verticalOffset=0; objectiveFunction = #(phase)(max(abs(0.2*cos(2*pi*t+phase(1))+0.7*cos(2*pi*t*9+phase(2))+0.8*cos(2*pi*t*5)+verticalOffset)) - 0.79)^2; s1 = fminsearch(objectiveFunction,[0;0]) eqt=0.2*cos(2*pi*t+s1(1))+0.7*cos(2*pi*t*9+s1(2))+0.8*cos(2*pi*t*5)+verticalOffset; plot(eqt)
fminsearch will find a minimum of the objective function. Whether this solution satisfies all your conditions is something you have to test. In this case, the solution given by fminsearch with the starting value [0;0] gives a maximum of ~1.3, which is obviously not good enough. However, when you plot the maximum for a range of phase angles from 0 to 2pi, you'll see that `fminsearch didn't get stuck in a bad local minimum. Rather, there is no good solution at all (z-axis is the maximum).
If I understand you correctly, you are trying to find a phase to vary the amplitude of a signal. To my knowledge, this is not possible.
For a signal
s = A * cos (w*t + phi)
only A allows you to change the amplitude. With w you change the frequency of the signal and phi regulates the "horizontal shift".
Furthermore, I think you are missing a "moving variable" like the time t in the equation above.
Maybe this article clarifies things a little.
If you set all the vertical offsets to be equal to -1, then it solves your problem because each eq# will never be > 0, so the sum can never be >0.8.
I know that this isn't that helpful, but I'm hoping that this will help you understand your problem better.