使用 Matlab 进行简单的 FFT 和滤波教程






4.27/5 (4投票s)
理解 FFT 从未如此简单!
引言
让我们理解 FFT。它是快速傅里叶变换,是一种快速有效地计算 DFT 或离散傅里叶变换的算法。看到标题出现的第一个问题是,在 2012 年,当该算法已经有大约 50 年历史时,Code Project 的新文章部分中关于 FFT 的教程在做什么。 好问题。 顺便说一下,您可以参考以下链接,以复杂的方式理解相同的内容。
http://en.wikipedia.org/wiki/Discrete_Fourier_transform
http://en.wikipedia.org/wiki/Fast_Fourier_transform
背景
我认为我必须编写本教程的原因之一是,我看到许多工程师发现很难理解什么是频域,什么是滤波。 我们如何以简单的方式过滤信号。 什么是 FFT 的对称特征,更重要的是理解关于 FFT 的核心事实。 因此,如果您是一位编程高手,并且是一位编写了自己的 DSP 逻辑和算法的杀手级程序员,那么本文可能不会给您带来任何新的或有趣的东西。 但是,如果您刚刚开始接触信号处理,您可能会觉得它很有帮助(希望如此)。
Using the Code
首先,让我们构造一个幅度为 5 的 50Hz 简单正弦信号。 我考虑的采样频率是消息频率的 100 倍(它至少应该是奈奎斯特速率的两倍),这意味着我将从实际的模拟正弦信号中收集 1000 个样本。 因此,如果频率为 50,则意味着您将在 1/50 或 0.02 秒处获得一个样本。 如果您想要 10 个样本,则必须收集 0.2 秒的样本。 您将在每 1/5000 秒采样一次信号。
f=50;
A=5;
Fs=f*100;
Ts=1/Fs;
t=0:Ts:10/f;
x=A*sin(2*pi*f*t);
plot(x),grid on
所以这张图显示了 50 Hz 的 10 个正弦波周期。 您可以将绘图更改为 stem 类型以查看样本。
那么让我们进行 FFT。
F=fft(x);
您一定已经学习过 N 点 FFT。 如果您不指定 N,则默认情况下 N 是消息信号的长度。 在本例中,它是 1001。
非常重要的事情:FFT 将您的采样频率划分为 N 个相等的部分,并返回每个频率级别的信号强度。 这意味着您将频率从 0 到 5000 划分为 1001 个相等的部分。 因此,fft 中的第一个点是 5Hz,下一个表示 10 Hz,依此类推。 由于您的消息的实际频率为 50 Hz,因此您必须在该级别获得最高峰值。 那么让我们绘制 FFT。
plot(real(F)),grid on
你看到了什么? 最高值位于第 11 个位置,这不过是第 10 个样本,因为 matlab 从 1 开始。
10*5?=50Hz
这太简单了。 但是等等,为什么我们也会得到虚部? 绝对没有什么叫做虚数值,它们反映了过去的值。
您的信号是正弦信号,所以您也会得到负周期,对吧。 检查这个。
plot(real(imag(F))),grid on
你看到了什么? :)
是的,同样的事情,也有一个负幅度峰值。 我希望你明白了。
现在让我们了解如何使用 FFT 进行一些滤波。 我要做的是将几个具有不同频率和相同样本数的信号与您的信号 x 混合。
x1=A*sin(2*pi*(f+50)*t); x2=A*sin(2*pi*(f+250)*t); x=x+x1+x2;
我们的信号现在包含三个分量:50Hz、100Hz 和 300Hz。
我想恢复我的原始信号。 因此,如果我将样本保留在第 11 个样本处,而将其余样本保留,然后进行 ifft,我必须取回我的信号,对吗? 但是必须保留第 10 个和第 11 个样本的值。 这称为加窗。
请参阅我在混合信号的 FFT 响应上放置的红色窗口。
F2=zeros(length(F),1); F2(10:11)=F(10:11); xr=ifft(F2); plot(real(xr)),grid on
你看到了什么? 这是您的原始信号。 但是幅度较小。 这是因为您选择了矩形窗口,并且损耗是由于负滤波器增益造成的。 您现在可以阅读一些数字滤波器并应用它。
这是完整的代码,可能不需要,但我仍然发布它,以防您决定花一些时间并使用它。
clear all; clc; close all f=50; A=5; Fs=f*100; Ts=1/Fs; t=0:Ts:10/f; x=A*sin(2*pi*f*t); x1=A*sin(2*pi*(f+50)*t); x2=A*sin(2*pi*(f+250)*t); x=x+x1+x2; plot(x) F=fft(x); figure N=Fs/length(F); baxis=(1:N:N*(length(x)/2-1)); plot(baxis,real(F(1:length(F)/2)))
关注点
您可以从此来源学习 Matlab 基础知识 <这里>
要了解有关任何 Matlab 命令的详细信息,您可以简单地单击编辑器中的该命令并按 F1。 Matlab 帮助文件解释了诸如 fft、sin 等命令的用法和其他详细信息。
在所有复杂的数学背后,都有一个简单的逻辑。 我真的很喜欢那个简单的逻辑。