Matlab中的频率计算和快速傅里叶变换

时间:2017-03-12 02:23:58

标签: for-loop fft

我有一个与快速傅立叶变换有关的问题。我想计算相位并使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

1 个答案:

答案 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)));