我有一个与快速傅立叶变换有关的问题。我想计算相位并使FFT绘制功率谱密度。但是,当我计算频率f
时,会出现一些错误。这是我的程序代码:
n = 1:32768;
T = 0.2*10^-9; % Sampling period
Fs = 1/T; % Sampling frequency
Fn = Fs/2; % Nyquist frequency
omega = 2*pi*200*10^6; % Carrier frequency
L = 32768; % % Length of signal
t = (0:L-1)*T; % Time vector
x_signal(n) = cos(omega*T*n + 0.1*randn(size(n))); % Additive phase noise (random)
y_signal(n) = sin(omega*T*n + 0.1*randn(size(n))); % Additive phase noise (random)
theta(n) = atan(y_signal(n)/x_signal(n));
f = (theta(n)-theta(n-1))/(2*pi)
Y = fft(f,t);
PSD = Y.*conj(Y); % Power Spectral Density
%Fv = linspace(0, 1, fix(L/2)+1)*Fn; % Frequency Vector
答案 0 :(得分:0)
发布时,您会收到错误
error: subscript indices must be either positive integers less than 2^31 or logicals
,当theta(n-1)
导致索引为0(由于Matlab使用基于1的索引时超出界限)时,引用操作n=1
。为避免这种情况,可以使用n
中的索引子集:
f = (theta(n(2:end))-theta(n(1:end-1)))/(2*pi);
那就是说,如果你这样做是为了试图获得频率的瞬时测量,那么你还需要处理一些问题。最微不足道的是你也应该除以T
。事实并非如此明显,theta
由于使用了/
运算符(请参阅Matlab's mrdivide
)而不是执行元素的./
operator,因此theta(n) = atan(y_signal(n)./x_signal(n));
是一个标量明智的分裂。所以更好的表达方式是:
atan
现在,您可能会注意到的下一个问题是,您实际上正在丢失一些阶段信息,因为[-pi/2,pi/2]
的结果是[-pi,pi]
而不是完整的theta(n) = atan2(y_signal(n), x_signal(n));
范围。为避免这种情况,您应该使用atan2
:
-pi
即便如此,您可能会注意到,当相位在pi
附近和2*pi
附近跳跃时,估计的频率会经常出现峰值。通过计算模{@ 1}}的相位差可以避免这种情况:
f = mod(theta(n(2:end))-theta(n(1:end-1)),2*pi)/(2*pi*T);
最后要注意的是:在调用fft
时,不应该传入时间变量(隐式假设输入是以固定的时间间隔进行采样)。但是,您可以指定所需的FFT长度。因此,您将按照以下方式计算Y
:
Y = fft(f, L);
然后你可以使用:
绘制结果PSD
Fv = linspace(0, 1, fix(L/2)+1)*Fn; % Frequency Vector
plot(Fv, abs(PSD(1:L/2+1)));