当前位置:   article > 正文

[Matlab科学计算] 频谱分析和FFT算法总结_频谱计算

频谱计算

       频谱分析是一种非常重要的信号处理方法,在机械设备故障诊断、振动系统分析、电力系统、无线电通信、信息图像处理和自动控制等学科中都有重要应用。频谱分析的核心是1965年Cooely-Tukey发表的快速傅里叶变换算法(简称FFT),它是离散傅里叶变换(DFT)的快速算法。FFT算法的各种语言实现包已经相当成熟,不需要自己来重新写源代码,本文使用matlab自带的fft函数来实现频谱分析。实际信号可能是连续无限长时间的,但是计算机在处理的时候只能是有限长度的离散信号,所以需要对信号进行采样。FFT用的时候是对有限长度的信号进行计算的。一段采集的实际信号给你的时候,往往只知道数据和采样频率,根据数据和采样频率就可以进行频谱分析了。当然,如果你有一段10000个点的数据,你也可以只截取其中感兴趣的N个点进行频谱分析,这里就等效为采集了N个点进行分析。

基本名词解释:f_{s} 为信号的采样频率,N为采样点数,也是频谱分析和FFT计算的点数, \Delta t为采样时间间隔,T 为时域截断窗长, \Delta f为频率分辨率,也就是频谱中相邻两条谱线间的频率间隔。这些变量有如下关系:

                                                                       f_{s}=\frac{1}{\Delta t},         \Delta f=\frac{f_{s}}{N}=\frac{f_{s}}{Tf_{s}}=\frac{1}{T}

理论部分请看这篇博客:频谱分析和FFT算法总结—理论基础

FFT的实现过程,这里不做介绍,直接看matlab中的计算结果。

1.首先来看一下常规的FFT计算

指定信号的参数,采样频率为 1 kHz,信号持续时间为 1.5 秒。

matlab代码如下:

  1. clear;close all
  2. Fs = 1000; % 采样频率
  3. T = 1/Fs; % 采样周期
  4. L = 1500; % 截取的信号长度
  5. t = (0:L-1)*T; % 时间矢量
  6. %构造一个信号,其中包含幅值为 0.750 Hz 正弦量和幅值为 1120 Hz 正弦量
  7. X = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
  8. % X = S + 2*randn(size(t));%用均值为零、方差为 4 的白噪声扰乱该信号。
  9. %在时域中绘制原始信号
  10. subplot(2,1,1),plot(1000*t(1:100),X(1:100))
  11. title('部分原始信号X(t)')
  12. xlabel('t (milliseconds)')
  13. ylabel('X(t)')
  14. %计算信号的傅里叶变换
  15. Y = fft(X);
  16. %计算双侧频谱 P2。然后基于 P2 和偶数信号长度 L 计算单侧频谱 P1
  17. P2 = abs(Y/L);
  18. P1 = P2(1:L/2+1);
  19. P1(2:end-1) = 2*P1(2:end-1);
  20. %定义频域 f 并绘制单侧幅值频谱 P1。与预期相符,频率和幅值与理论相同
  21. f = Fs*(0:(L/2))/L;
  22. subplot(2,1,2),plot(f,P1)
  23. title('X(t)的单边幅值谱')
  24. xlabel('f (Hz)')
  25. ylabel('|P1(f)|')

计算结果如图1所示:

图1

 从图1可以看出,计算的频谱(幅值和频率)与理论相同,没有误差。有时候我们也会遇到对数据进行补零以达到数据点数为2的n次幂的情况。

2.如果原始数据插值(重采样)或者补零到2的n次方个再进行频谱分析,结果会如何?

 我们知道FFT分析的时候一般要求数据点数为2的n次幂,所以matlab中提供了Y=fft(x,N)这个函数,如果数据x的长度小于N,则为x补上尾零以达到长度N;如果x的长度大于N,则对x进行截断以达到长度N。或者通过插值使原始信号达到2的n次幂个数据。分别来看这两种情况。

1)补零的matlab程序如下:

  1. clear;close all
  2. Fs = 1000; % 采样频率
  3. T = 1/Fs; % 采样周期
  4. L = 1500; % 截取的信号长度
  5. t = (0:L-1)*T; % 时间矢量
  6. %构造一个信号,其中包含幅值为 0.750 Hz 正弦量和幅值为 1120 Hz 正弦量
  7. X = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
  8. % X = S + 2*randn(size(t));%用均值为零、方差为 4 的白噪声扰乱该信号。
  9. %在时域中绘制原始信号
  10. subplot(2,1,1),plot(1000*t(1:100),X(1:100))
  11. title('部分原始信号X(t)')
  12. xlabel('t (milliseconds)')
  13. ylabel('X(t)')
  14. %计算信号的傅里叶变换
  15. n = length(X); %获取数据点数
  16. N = 2^nextpow2(n); %nextpow2(n)获得大于等于n的最大整数次幂
  17. Y = fft(X,N);
  18. %计算双侧频谱 P2。然后基于 P2 和偶数信号长度 N 计算单侧频谱 P1
  19. P2 = abs(Y/N);
  20. P1 = P2(1:N/2+1);
  21. P1(2:end-1) = 2*P1(2:end-1);
  22. %定义频域 f 并绘制单侧幅值频谱 P1
  23. f = Fs*(0:(N/2))/N;
  24. subplot(2,1,2),plot(f,P1)
  25. title('X(t)的单边幅值谱')
  26. xlabel('f (Hz)')
  27. ylabel('|P1(f)|')

计算结果如图2所示:

图2

从图2可以看出,本来是1500个数据,补零以达到2048个数据点之后,计算的频谱在频率和幅值方面都产生了误差,出现频谱泄露,原因是补零之后,数据相对原始信号发生了改变,已不是初始信号了。

 2)插值的matlab程序如下:

  1. clear;close all
  2. Fs = 1000; % 采样频率
  3. T = 1/Fs; % 采样周期
  4. L = 1500; % 截取的信号长度
  5. t = (0:L-1)*T; % 时间矢量
  6. %构造一个信号,其中包含幅值为 0.750 Hz 正弦量和幅值为 1120 Hz 正弦量
  7. X = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
  8. % X = S + 2*randn(size(t));%用均值为零、方差为 4 的白噪声扰乱该信号。
  9. %在时域中绘制原始信号
  10. subplot(2,1,1),plot(1000*t(1:100),X(1:100))
  11. title('部分原始信号X(t)')
  12. xlabel('t (milliseconds)')
  13. ylabel('X(t)')
  14. %计算信号的傅里叶变换
  15. n = length(X); %获取数据点数
  16. N = 2^nextpow2(n); %nextpow2(n)获得大于等于n的最大整数次幂
  17. X1 = resample(X,N,n);%升采样到2048个数据
  18. Y = fft(X1);
  19. %计算双侧频谱 P2。然后基于 P2 和偶数信号长度 N 计算单侧频谱 P1
  20. P2 = abs(Y/N);
  21. P1 = P2(1:N/2+1);
  22. P1(2:end-1) = 2*P1(2:end-1);
  23. %定义频域 f 并绘制单侧幅值频谱 P1
  24. f = Fs*2048/1500*(0:(N/2))/N;
  25. subplot(2,1,2),plot(f,P1)
  26. title('X(t)的单边幅值谱')
  27. xlabel('f (Hz)')
  28. ylabel('|P1(f)|')

插值前后的信号波形对比如图3所示:

图3

从图3可以看出,插值后信号波形变得光滑了。重采样函数resample用法见matlab文档说明。

计算结果如图4所示:

图4

从图4来看,插值计算的结果频率是正确的,幅值有一点点误差,但要比补零好很多。

综上,在用matlab进行频谱分析的时候,一般情况下不需要进行补零和插值操作,但需要进行对数据进行去趋势项操作。

3.趋势项对频谱分析的影响 

这里考虑最简单的情况,在原始信号上加上直流分量,结果对比如图5所示:

图5

可以看出,如果不去直流分量,频谱分析中会在0Hz出产生很大的一个值,影响结果。 

4.噪声对频谱分析的影响

在原始信号中加入均值为零、方差为 4 的白噪声来扰乱该信号

matlab代码如下:

  1. clear;close all
  2. Fs = 1000; % 采样频率
  3. T = 1/Fs; % 采样周期
  4. L = 1500; % 截取的信号长度
  5. t = (0:L-1)*T; % 时间矢量
  6. %构造一个信号,其中包含幅值为 0.750 Hz 正弦量和幅值为 1120 Hz 正弦量
  7. S = 0.7*sin(2*pi*50*t) + sin(2*pi*120*t);
  8. X = S + 2*randn(size(t));%用均值为零、方差为 4 的白噪声扰乱该信号。
  9. %在时域中绘制原始信号
  10. subplot(2,1,1),plot(1000*t(1:100),X(1:100))
  11. title('部分原始信号X(t)')
  12. xlabel('t (milliseconds)')
  13. ylabel('X(t)')
  14. %计算信号的傅里叶变换
  15. Y = fft(X);
  16. %计算双侧频谱 P2。然后基于 P2 和偶数信号长度 L 计算单侧频谱 P1
  17. P2 = abs(Y/L);
  18. P1 = P2(1:L/2+1);
  19. P1(2:end-1) = 2*P1(2:end-1);
  20. %定义频域 f 并绘制单侧幅值频谱 P1。与预期相符,频率和幅值与理论相同
  21. f = Fs*(0:(L/2))/L;
  22. subplot(2,1,2),plot(f,P1)
  23. title('X(t)的单边幅值谱(去均值)')
  24. xlabel('f (Hz)')
  25. ylabel('|P1(f)|')

结果如图6所示:

图6

从图6中可以看出,加入噪声之后,会对频谱分析的幅值有一定影响,对频率成分基本没有影响。

后面会继续写一写频谱分析误差校正等方面的知识,欢迎大家留言交流!

参考文献: 

matlab官方关于fft函数的教程:https://ww2.mathworks.cn/help/matlab/ref/fft.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/967855
推荐阅读
相关标签
  

闽ICP备14008679号