识别信号之间的相移

时间:2014-12-18 11:09:58

标签: matlab signal-processing phase

我已经生成了三个相同的波,每个波都有一个相移。例如:

t = 1:10800; % generate time vector
fs = 1; % sampling frequency (seconds)
A = 2; % amplitude
P = 1000; % period (seconds), the time it takes for the signal to repeat itself
f1 = 1/P; % number of cycles per second (i.e. how often the signal repeats itself every second).
y1 = A*sin(2*pi*f1*t); % signal 1
phi = 10; % phase shift
y2 = A*sin(2*pi*f1*t + phi); % signal 2
phi = 15; % phase shift
y3 = A*sin(2*pi*f1*t + phi); % signal 3

YY = [y1',y2',y3'];

plot(t,YY)

enter image description here

我现在想用一种方法来检测波之间的这种相移。这样做的目的是使我最终能够将该方法应用于实际数据并识别信号之间的相移。

到目前为止,我一直在考虑计算每个波与第一波之间的交叉光谱(即没有相移):

for i = 1:3;
    [Pxy,Freq] = cpsd(YY(:,1),YY(:,i));
    coP = real(Pxy);
    quadP = imag(Pxy);
    phase(:,i) = atan2(coP,quadP);
end

但我不确定这是否有意义。

有没有其他人做过类似的事情?对于波2和3,期望的结果应分别在10和15处显示相移。

任何建议都将不胜感激。

6 个答案:

答案 0 :(得分:45)

有几种方法可以测量信号之间的相移。在您的回复,您的回复下方的评论以及其他答案之间,您已经获得了大部分选项。技术的具体选择通常基于以下问题:

  • 嘈杂或干净:信号中是否有噪音?
  • 多分量或单分量:录音中是否有多种类型的信号(多个频率的多个音调向不同的方向移动)?或者,只有一个信号,就像你的正弦波示例一样?
  • 瞬时或平均:您是在寻找整个录制过程中的平均相位滞后,还是想要跟踪整个录制过程中相位的变化?

根据您对这些问题的回答,您可以考虑以下技巧:

  • 互相关:使用类似[c,lag]=xcorr(y1,y2);的a命令获取两个信号之间的互相关。这适用于原始时域信号。您查找c最大值([maxC,I]=max(c);)的索引,然后以样本lag = lag(I);为单位获得滞后值。此方法为您提供整个录制的平均相位滞后。它要求您在录音中感兴趣的信号比录音中的任何其他信号强......换句话说,它对噪音和其他干扰很敏感。

  • 频域:您可以将信号转换为频域(使用fftcpsd或其他)。然后,您将找到与您关注的频率相对应的bin,并获得两个信号之间的角度。因此,例如,如果bin#18对应于您的信号的频率,则您将通过phase_rad = angle(fft_y1(18)/fft_y2(18));获得以弧度为单位的相位滞后。如果您的信号具有恒定频率,这是一种很好的方法,因为它可以自然地抑制其他频率的所有噪声和干扰。您可以在一个频率上产生非常强的干扰,但您仍然可以干净地以另一个频率获取信号。对于在fft分析窗口期间改变频率的信号,这种技术不是最好的。

  • 希尔伯特变换:经常被忽视的第三种技术是通过希尔伯特变换将时域信号转换为分析信号:y1_h = hilbert(y1);。一旦你这样做,你的信号就是一个复数的向量。在时域中持有简单正弦波的矢量现在将是复数的矢量,其大小是恒定的并且其相位与原始正弦波同步变化。这种技术可以让你获得两个信号之间的瞬时相位滞后......它功能强大:phase_rad = angle(y1_h ./ y2_h);phase_rad = wrap(angle(y1_h) - angle(y2_h));。这种方法的主要限制是您的信号需要是单声道的,这意味着您感兴趣的信号必须支配您的录音。因此,您可能必须过滤掉可能存在的任何实质性干扰。

答案 1 :(得分:3)

对于两个正弦信号,复相关系数的相位可以为您提供所需的信号。我只能给你一个python例子(使用scipy),因为我没有matlab来测试它。

x1 = sin( 0.1*arange(1024) )
x2 = sin( 0.1*arange(1024) + 0.456)
x1h = hilbert(x1)
x2h = hilbert(x2)
c = inner( x1h, conj(x2h) ) / sqrt( inner(x1h,conj(x1h)) * inner(x2h,conj(x2h)) )
phase_diff = angle(c)

在matlab中有一个函数corrcoeff,它也应该工作(python一个丢弃虚部)。即c = corrcoeff(x1h,x2h)应该在matlab中工作。

答案 2 :(得分:2)

使用互相关来查找相对相位的Matlab代码:

fr = 20; % input signal freq
timeStep = 1e-4;
t = 0:timeStep:50; % time vector
y1 = sin(2*pi*t); % reference signal
ph = 0.5; % phase difference to be detected in radians
y2 = 0.9 * sin(2*pi*t + ph); % signal, the phase of which, is to be measured relative to the reference signal

[c,lag]=xcorr(y1,y2); % calc. cross-corel-n
[maxC,I]=max(c); % find max
PH = (lag(I) * timeStep) * 2 * pi; % calculated phase in radians

>> PH

PH =

    0.4995

答案 3 :(得分:1)

使用正确的信号:

t = 1:10800; % generate time vector
fs = 1; % sampling frequency (seconds)
A = 2; % amplitude
P = 1000; % period (seconds), the time it takes for the signal to repeat itself
f1 = 1/P; % number of cycles per second (i.e. how often the signal repeats itself every second).
y1 = A*sin(2*pi*f1*t); % signal 1
phi = 10*pi/180; % phase shift in radians
y2 = A*sin(2*pi*f1*t + phi); % signal 2
phi = 15*pi/180; % phase shift in radians
y3 = A*sin(2*pi*f1*t + phi); % signal 3

以下内容应该有效:

>> acos(dot(y1,y2)/(norm(y1)*norm(y2)))
>> ans*180/pi
ans =  9.9332
>> acos(dot(y1,y3)/(norm(y1)*norm(y3)))
ans =  0.25980
>> ans*180/pi
ans =  14.885

这对于你的“真实”信号是否足够好,只有你能说出来。

答案 4 :(得分:1)

以下是对代码的一点修改:phi = 10实际上是度,然后在正弦函数中,阶段信息主要以弧度表示,因此您需要更改deg2rad(phi)如下:

t = 1:10800; % generate time vector
fs = 1; % sampling frequency (seconds)
A = 2; % amplitude
P = 1000; % period (seconds), the time it takes for the signal to repeat itself
f1 = 1/P; % number of cycles per second (i.e. how often the signal repeats itself every second).
y1 = A*sin(2*pi*f1*t); % signal 1
phi = deg2rad(10); % phase shift 
y2 = A*sin(2*pi*f1*t + phi); % signal 2
phi = deg2rad(15); % phase shift
y3 = A*sin(2*pi*f1*t + phi); % signal 3

YY = [y1',y2',y3'];

plot(t,YY)

然后使用频域方法提到chipaudette

fft_y1 = fft(y1);
fft_y2 = fft(y2);
phase_rad = angle(fft_y1(1:end/2)/fft_y2(1:end/2));
phase_deg = rad2deg(angle(fft_y1(1:end/2)/fft_y2(1:end/2)));

现在,这将为您提供error = +-0.2145

的相移估算值

答案 5 :(得分:0)

如果您知道频率并且只想找到相位,而不是使用完整的FFT,则可能需要考虑Goertzel算法,这是一种计算单个频率DFT的更有效方法(FFT将计算所有频率)。

要获得良好的实施效果,请参见:https://www.mathworks.com/matlabcentral/fileexchange/35103-generalized-goertzel-algorithmhttps://asp-eurasipjournals.springeropen.com/track/pdf/10.1186/1687-6180-2012-56.pdf