第四节:数字信号处理基础——DFT、FFT与频谱分析实战

各位同学,今天咱们来聊聊数字信号处理里最核心的几个工具。说实话,我当年刚接触这块时,也被一堆公式搞得头晕。但后来发现,只要你理解了背后的物理意义,这些东西其实挺直观的。

4.1 从连续到离散:为什么要做DFT?

我们传感器采集到的信号,本质上都是连续的时间信号。但单片机、DSP这些数字芯片,只能处理离散的数值点。这就好比你想描述一段旋律,但只能每隔0.1秒记录一个音符——这就是离散化的过程。

离散傅里叶变换(DFT),说白了就是把一段离散的时间信号,拆解成不同频率的正弦波和余弦波的组合。我个人的理解是:它就像一台“频率分光镜”,把混合在一起的光(信号)分解成单色光(频率分量)。

DFT的数学表达式长这样:

X[k] = Σ(n=0 to N-1) x[n] · e^(-j·2π·k·n/N)

别被这个公式吓到。你只需要记住:输入是N个时域点,输出是N个频域点。每个X[k]代表频率为k·fs/N的分量的幅度和相位。

关键点:DFT的计算量是O(N²)。当N=1024时,需要做约100万次复数乘法。这在实时系统中是灾难性的——我早期一个项目就因此吃了大亏。

4.2 FFT:让计算快起来的魔法

快速傅里叶变换(FFT)不是一种新的变换,而是DFT的快速算法。它利用了旋转因子的对称性和周期性,把计算量从O(N²)降到了O(N·log₂N)。

举个例子:N=1024时,DFT需要约100万次运算,而FFT只需要约1万次。快了100倍!

最常用的FFT算法是基2时间抽取法。它的核心思想是“分而治之”:

  1. 把N点序列分成奇偶两个子序列
  2. 分别对子序列做DFT
  3. 用蝶形运算合并结果

下面这张图展示了8点FFT的蝶形运算流程:

8点FFT蝶形运算结构图 x[0] x[4] x[2] x[6] x[1] x[5] x[3] x[7] X[0]~X[7] 第1级 第2级 第3级

你看,每一级都是两两配对做蝶形运算。3级运算后,8个输入就变成了8个频域输出。这就是FFT的精髓——用结构换速度。

4.3 频谱分析实战:从传感器数据到频率信息

好了,理论讲完了,咱们来点实际的。假设你有一个加速度传感器,采样率fs=1000Hz,采集了1024个点。你想看看信号里有哪些频率成分。

这是我在一个振动监测项目中用过的代码片段:

#include <arm_math.h>  // ARM CMSIS-DSP库

#define FFT_SIZE 1024
float32_t input[FFT_SIZE * 2];  // 实部+虚部交错存储
float32_t output[FFT_SIZE];

// 填充数据:假设adc_buffer[]存了传感器数据
for (int i = 0; i < FFT_SIZE; i++) {
    input[2*i] = adc_buffer[i];     // 实部
    input[2*i+1] = 0;               // 虚部置0
}

// 执行FFT
arm_cfft_f32(&arm_cfft_sR_f32_len1024, input, 0, 1);

// 计算幅度谱
arm_cmplx_mag_f32(input, output, FFT_SIZE);

// 输出前10个频率点
for (int i = 0; i < 10; i++) {
    float freq = (float)i * 1000.0f / FFT_SIZE;
    printf("f=%.2f Hz, mag=%.2f\n", freq, output[i]);
}

我的经验:实际项目中,我一般会先做加窗处理。直接对原始数据做FFT,频谱泄漏会让你怀疑人生。汉宁窗(Hanning)是最常用的,能有效抑制旁瓣。

4.4 避坑指南:频谱分析中的常见陷阱

做频谱分析时,有几个坑我当年都踩过,今天一并告诉你:

  • 混叠问题:信号中如果有高于fs/2的频率成分,会被折叠到低频区。我曾经用100Hz采样率去分析一个50Hz的振动信号,结果频谱里出现了30Hz的假峰——后来才发现是工频干扰混叠了。
  • 频率分辨率:Δf = fs / N。要分辨两个相近的频率,需要足够的采样点数。比如fs=1000Hz,N=256时,Δf≈3.9Hz。两个相差2Hz的信号是分不开的。
  • 栅栏效应:FFT只能看到离散频率点上的值。如果信号频率正好在两个bin之间,幅度会被低估。加窗和插值可以缓解这个问题。

我曾经犯过的错:在一个电机故障诊断项目中,我直接用原始数据做FFT,结果频谱里全是噪声。后来发现是传感器电源纹波太大,50Hz的工频干扰淹没了故障特征频率。从那以后,我养成了先做直流分量去除和带通滤波的习惯。

4.5 实用技巧:如何选择FFT参数

在实际工程中,FFT参数的选择直接影响分析效果。我一般按这个思路来:

参数 选择原则 我的建议
采样率fs ≥ 2倍最高信号频率 留20%裕量,比如最高频率100Hz,设fs=250Hz
FFT点数N 2的幂次,越大分辨率越高 一般取1024或2048,兼顾速度和精度
窗函数 根据信号类型选择 宽带信号用汉宁窗,窄带信号用布莱克曼窗
重叠率 做平均时使用 50%~75%重叠,能有效降低方差

嗯,说到重叠率,我记得有一次做声学分析,用了75%的重叠率,结果频谱平滑得跟教科书一样漂亮。但代价是计算量大了4倍——这就是trade-off。

4.6 小结:DFT/FFT在传感器信号处理中的定位

说白了,DFT和FFT就是把时域信号搬到频域去看。在传感器信号处理中,它们主要用于:

  • 特征提取:从振动信号中找出故障频率
  • 噪声分析:识别干扰源的频率成分
  • 系统辨识:通过扫频信号测量传感器频响
  • 数据压缩:只保留主要频率分量,丢掉噪声

我个人觉得,掌握FFT的关键不在于背公式,而在于理解它的物理意义和工程约束。你想想看,一个1024点的FFT,在STM32F4上只需要不到1ms就能跑完——这就是现代嵌入式系统的能力。

好了,这一节的内容就到这里。记住:频谱分析不是万能的,但没有频谱分析是万万不能的。下次当你面对一堆传感器数据时,不妨先做个FFT看看——说不定会有意外发现。


可可精品资料库