Matlab的信号频谱分析——FFT变换
Matlab的信号频谱分析
FFT是离散傅立叶变换的快速算法,可以将一个时域信号变换到频域。
有些信号在时域上是很难看出什么特征的。但是如果变换到频域之后,就很容易看出特征了。
这就是很多信号分析采用FFT变换的原因。
另外,FFT可以将一个信号的频谱提取出来,这在频谱分析方面也是经常用的。
通俗点说FFT就是将一个信号解析成是由不同频率、幅值,相位的正弦波叠加而成的。
FFT变换的步骤:
1、对模拟信号离散化
一个模拟信号,经过ADC采样之后,就变成了离散的数字信号。
2、采样频率(Fs)的选取
根据采样定理,采样频率需大于信号频率的两倍。
3、采样点数( N )的选取
在FFT变换中,输入N个采样点,就有N个变换结果,每个结果都是一个复数。
每个结果都和上面所说的一个正弦信号的频率、幅值,相位对应。
复数的幅值和正弦信号的幅值对应,相位和相位对应。
而其频率的对应关系为:假设第n个结果,则其对应的频率为 Fn = (n-1)*Fs/N 。
Fs/N为分辨率,例如采样频率Fs为1024Hz,采样点数为1024点,
则每个结果以1HZ的频率步长递增。如果采样频率Fs为1024Hz,采样点数为2048点,
则每个结果以0.5HZ的频率步长递增。我们讲其分辨率为0.5HZ。
如果要提高频率分辨力,则必须增加采样点数,也即采样时间。
频率分辨率和采样时间是倒数关系。
注意:为了方便进行FFT运算,通常N取2的整数次方。
例:假设我们有一个信号,它含有一个2V的直流分量,一个频率为50Hz、相位为-30度、幅度为3V的交流信号,以及一个频率为75Hz、相位为90度、幅度为1.5V的交流信号。
用数学表达式就是如下:S=2+3cos(2pi50t-pi30/180)+1.5cos(2pi75t+pi90/180)。
我们以256Hz的采样率对这个信号进行采样,总共采样256点。
按照我们上面的分析,Fn=(n-1)*Fs/N,我们可以知道,每两个点之间的间距就是1Hz,第n个点的频率就是n-1。我们的信号有3个频率:0Hz、50Hz、75Hz,应该分别在第1个点、第51个点、第76个点上出现峰值,其它各点应该接近0。
实际情况如何呢?我们来看看FFT的结果:
% 假设我们有一个信号,它含有一个2V的直流分量,一个频率为50Hz、相位为-30度、幅度为3V的交流信号,
% 以及一个频率为75Hz、相位为90度、幅度为1.5V的交流信号。
% 用数学表达式就是如下:S=2+3cos(2pi50t-pi30/180)+1.5cos(2pi75t+pi90/180)。
% 我们以256Hz的采样率对这个信号进行采样,总共采样256点。
% 按照我们上面的分析,Fn=(n-1)*Fs/N,我们可以知道,每两个点之间的间距就是1Hz,
% 第n个点的频率就是n-1。
% 我们的信号有3个频率:0Hz、50Hz、75Hz,应该分别在第1个点、第51个点、第76个点上出现峰值,
% 其它各点应该接近0。
% 实际情况如何呢?我们来看看FFT的结果:clc; clear; close all;t = 0:1/255:1; %采样步长
% s1 = 2; % 一个2V的直流
% s2 = 3*cos(2*pi*50*t-pi*30/180); % 一个频率为50Hz、相位为-30度、幅度为3V的交流信号
% s3 = 1.5*cos(2*pi*75*t+pi*90/180); % 一个频率为75Hz、相位为90度、幅度为1.5V的交流信号
y = 2 + 3*cos(2*pi*50*t-pi*30/180) + 1.5*cos(2*pi*75*t+pi*90/180); % 信号叠加
N = length(t); %样点个数
plot(t,y);
xlabel('时间/s'); ylabel('幅值');
title('时域信号time domain signal');
% 采样
fs = 255; %采样频率
df = fs/(N-1); %分辨率
Y = fft(y(1:N)); %真实的幅值
figure(2)
plot((1:N/2),abs(Y(1:N/2))); %由于傅里叶算法转换得到的是对称图,而常用的只需要一半就可以了。
xlabel('Hz'); ylabel('幅值');
title('幅频响应');
%
% FFT结果的幅值和信号真实幅值对应的关系:除第一个点外,
% FFT结果的其他点的幅值是真实信号幅值N/2倍,而第一个点是真实值的N倍。
%
% FFT结果的相位和真实信号相位对比:由于是第51个点对应的是50Hz,有个错位关系,
% 还有就是FFT的幅值和真实值也有个转换关系,下面我们通过算法让其完全对应起来。
% f = (0:N-1)*df; %其中每点的频率,第一个点对应的频率为0
Y1 = fft(y(1:N))/(N/2); %真实的幅值
figure(3)
plot(f(1:N/2),abs(Y1(1:N/2))); %由于傅里叶算法转换得到的是对称图,而常用的只需要一半就可以了.
xlabel('Hz'); ylabel('幅值');
title('幅频响应');