先说明一个很直接的现实:航空发动机齿轮振动信号处理,绝大多数时候不是“看频谱全貌”,而是“盯着某一个频段往死里看”。测试台架上辛辛苦苦采回的数据,普通FFT一画,啮合频率倒是清清楚楚,可旁边那几根边频带被噪声埋得严严实实,频率间隔根本数不出来。这时候,细化谱分析是最实用的工具之一。这篇文章就围绕航空发动机齿轮振动信号的细化谱分析展开,附上一套可以直接跑的Matlab代码,适合做齿轮箱故障诊断、传动系统状态监测或者研究生阶段做信号处理课题的朋友参考。我尽量把原理、代码和实操中的坑一次讲透。
1. 先说清楚:齿轮振动信号为什么要做细化谱分析
1.1 普通FFT在齿轮诊断里的“迷糊”时刻
齿轮振动信号跟一般的旋转机械振动不太一样。齿轮在啮合过程中,啮合刚度周期性变化,产生以啮合频率 ( f_m = f_r \times z ) 为载波的振动,这是最主要的成分。当某个齿轮出现局部故障(比如齿面点蚀、断齿、裂纹),振动信号就会出现以故障齿轮转频为间隔的边频带,也就是 ( f_m \pm k f_r )。理论上,只要FFT分辨率足够,这些边频带就能被清楚分辨。
但问题恰恰出在“分辨率足够”这五个字上。
普通FFT的频率分辨率是 ( \Delta f = f_s / N ),要提高分辨率,只能增加采样点数 ( N )——也就是延长采样时间。可实际上,航空发动机试车时间受多工况约束,单工况稳态段可能只有几秒钟;即便采够时间,FFT点数动辄几十万点,算起来没问题,但你想仔细看某一根谱线周围的细节时,整段频谱上密密麻麻全是谱线,反而把关键特征淹没了。
我调试过很多次这种场景:普通FFT画出来,啮合频率处的谱峰很高,但两侧的边频带跟噪声底部混在一起,看不清到底有几根边带,间隔到底是多少。做故障诊断的同事问能不能把这段放大看看,实际上用普通FFT强行截取一段放大,分辨率并没有变,只是把图片拉伸了,原来看不出细节的地方照样看不出细节。
1.2 细化谱分析要解决的核心问题
细化谱分析(Zoom-FFT)解决的就是“局部放大还要保持高分辨率”这个问题。它的核心逻辑可以类比成拿放大镜看图:普通FFT是把整张图纸摊开看,每个局部都那么大,细节有限;细化谱则是把相机镜头直接对准图纸上一个很小的区域,让这个区域在传感器上占满整个画幅,细节自然多得多。
在航空发动机齿轮诊断里,细化谱最典型的应用场景有两个。
一个是啮合频率附近的边频带结构分析。齿轮故障的边频带不是随便长的,它的间隔等于故障齿轮的转频,边带数量、对称性、幅值规律都能反映故障类型。比如均匀磨损会带来较宽的高次边带,断齿会在啮合频率附近产生丰富的分数谐波,用普通FFT看不清这些规律,细化谱一上马上见分晓。
另一个是多个啮合频率相互靠近时的频率分离。航空发动机传动链里常有多个齿轮副,两级啮合频率可能只差十几赫兹,普通FFT分辨率不够时两根谱峰重叠成一根,很难区分是哪一级齿轮出了问题,细化谱能把两根峰稳稳分开。
2. 细化谱分析的原理:Zoom-FFT是如何“放大”频谱的
2.1 三步核心操作:频移、滤波、重采样
细化谱分析最常见的是复调制细化法,也叫Zoom-FFT。原理说穿了就是三步。
第一步是复调制频移。我们想把中心频率 ( f_0 ) 附近的频谱搬过来看,就让原始信号乘以一个复指数 ( e^{-j2\pi f_0 n / f_s} )。这一步的本质是频谱搬移,把关注频段的中心从 ( f_0 ) 搬到零频附近。这样做的好处是,原本分布在 ( f_0 ) 两侧的窄带成分,现在都围绕零频分布了。
第二步是低通滤波。频移之后,原本远离 ( f_0 ) 的成分也都被搬到了相应位置,如果不做处理,后面重采样时就会发生混叠。所以要用一个截止频率为 ( f_s / (2M) ) 的低通滤波器,只保留零频附近宽度为 ( f_s / M ) 的频带。这个 ( M ) 就是细化倍数。
第三步是抽取重采样。滤波后的信号数据量还是原来的 ( N ),但有效带宽只有 ( f_s / M ),按照带限信号的采样定理,这时可以每 ( M ) 个点抽一个,等效采样率从 ( f_s ) 降为 ( f_s / M ),数据量也压缩为原来的 ( 1/M )。最后再对这个重采样序列做FFT,得到的就是中心频率 ( f_0 ) 附近的高分辨率细化谱。
2.2 为什么细化后分辨率确实变好了
很多人会把细化谱里的补零FFT和真实分辨率提升混为一谈。实际上细化后的频率分辨率是
[ \Delta f_{zoom} = \frac{f_s / M}{N_{fft}} ]
其中 ( N_{fft} ) 是细化后实际做FFT的有效数据点数。如果这段数据本身的时长不够,信息量就是不够的,补零只能让谱线看起来更平滑,不会真的把间隔很小的两个频率分开。
那为什么工程上还是说“分辨率提高了M倍”?因为同等FFT点数下,细化谱的观察带宽压缩到了原来的 ( 1/M )。举个例子:做2048点FFT,普通FFT观察范围是0到 ( f_s/2 ),频率分辨率是 ( f_s / 2048 );细化10倍后,观察范围变成 ( f_0 ) 附近宽度 ( f_s/10 ) 的窄带,同样是2048点FFT,分辨率变成了 ( f_s / (10 \times 2048) )。也就是说,不用把FFT点数拉到几百万点,就能拿到和超长FFT相当的局部分辨率。
2.3 细化倍数与中心频率的选取逻辑
细化倍数 ( M ) 并不是越大越好,这一点我踩过坑。( M ) 越大,目标频带越窄,表面上看分辨率越高,但带内能量越少,信噪比随之下降,而且抽取后的有效数据点数 ( N/M ) 急剧减少,这时如果FFT点数不变,相当于补零比例越来越大,真实分辨率其实没有提升。经验上,( M ) 一般取4到20,具体根据待分析的边频带宽度来定。比如啮合频率附近的边带分布在 ( f_m \pm 3f_r ) 范围内,那目标带宽至少取 ( 6f_r ) 再留点裕量,按 ( BW = f_s / M ) 反算 ( M ) 就行。
中心频率 ( f_0 ) 则尽量对准啮合频率或者待分析谱峰的中心,不要偏太多。因为低通滤波器有过渡带,如果 ( f_0 ) 选在边带边缘,滤波时容易被削掉一部分幅值,边带结构就失真了。
3. Matlab完整实现:从仿真信号到细化谱
3.1 仿真齿轮振动信号的构造
写细化谱代码之前,先要有一份能验证算法正确性的信号。我习惯用仿真信号验证算法,因为结果已知,代码有没有写对一眼就能看出来。
构造一个典型的齿轮局部故障振动信号,包含啮合频率载波、一阶和二阶边频带以及噪声:
clear; clc; close all; %% 1. 基础参数 fs = 20480; % 采样频率 20480 Hz T = 2; % 时长 2 秒 N = round(fs * T); % 总采样点数 t = (0:N-1) / fs; %% 2. 齿轮参数 fr1 = 24.4; % 主动轴转频 Hz z1 = 28; % 主动齿轮齿数 fm = fr1 * z1; % 啮合频率 = 683.2 Hz fr2 = 683.2 / 31; % 从动轴转频,假设从动齿数 z2 = 31 %% 3. 构造振动信号 % 啮合频率载波 + 1阶边带 + 2阶边带的典型调制结构 x = 1.2 * cos(2*pi*fm*t) ... % 载波 + 0.35 * cos(2*pi*(fm - fr1)*t) ... % -1阶边带 + 0.35 * cos(2*pi*(fm + fr1)*t) ... % +1阶边带 + 0.12 * cos(2*pi*(fm - 2*fr1)*t) ... % -2阶边带 + 0.12 * cos(2*pi*(fm + 2*fr1)*t) ... % +2阶边带 + 2.2 * randn(1, N); % 高斯噪声这段信号里边频带间隔是24.4 Hz,如果采样时长不够或者FFT点数不足,这五根谱线很容易被噪声淹没。
3.2 Zoom-FFT核心函数代码
下面是细化谱分析的Matlab函数,按频移、滤波、抽取、FFT四步实现。
function [f_abs, amp] = zoomfft(x, fs, f0, M, Nfft) % ZOOMFFT 复调制细化谱分析 % 输入: % x - 待分析信号(行向量或列向量) % fs - 采样频率 (Hz) % f0 - 细化中心频率 (Hz) % M - 细化倍数(正整数,建议 4~20) % Nfft - 细化FFT点数(建议取 2 的整数次幂) % 输出: % f_abs - 绝对频率轴(单边谱) % amp - 幅值谱 x = x(:).'; N = length(x); %% 1. 复调制频移 n = 0:N-1; y = x .* exp(-1j * 2 * pi * f0 * n / fs); %% 2. 数字低通滤波 fc = fs / (2 * M); % 低通截止频率 % 设计等纹波FIR滤波器,阶数128,过渡带取截止频率的20% filt_order = 128; Wn = fc / (fs/2); % 归一化截止频率 fcuts = [0, Wn, Wn*1.2, 1]; % 截止带与过渡带位置 amps = [1, 1, 0, 0]; % 通带幅值1,阻带幅值0 b = firpm(filt_order, fcuts, amps); % Parks-McClellan最优等纹波设计 y_filt = filter(b, 1, y); %% 3. 抽取重采样,等效采样率 fs/M y_dec = y_filt(1:M:end); %% 4. 对重采样信号加窗并FFT Ndec = length(y_dec); win = hanning(Ndec)'; y_win = y_dec .* win; X = fft(y_win, Nfft); % 不足Nfft时自动补零 X_one = X(1:Nfft/2); amp = abs(X_one) * 2 / sum(win); % 幅值修正 %% 5. 频率轴映射 % 重采样后采样率为fs/M,因此FFT单边谱对应0 ~ fs/(2M) f_zoom = (0:Nfft/2-1) * (fs/M) / Nfft; % 将零频映射回中心频率f0,得到绝对频率 f_abs = f0 - fs/(2*M) + f_zoom; end这里说几个代码里的关键细节。
第一,滤波器用FIR等纹波设计而不是IIR。IIR滤波器幅频特性可以做得很陡,但相位非线性会扭曲边频带之间的相对相位关系,对故障诊断里的调制特征分析有影响。FIR滤波器线性相位,虽然阶数高一些,但相位不失真,分析结果更可信。
第二,抽取只取 ( 1:M:end ),没有用抗混叠的抽取函数。因为我们在抽取之前已经做了低通滤波,满足抗混叠条件,直接抽取就行。如果省略了滤波直接抽取,高频成分会折叠进目标频带,细化谱上会出现一堆“伪边带”,这是新手最容易犯的错误。
第三,窗函数用Hanning。细化FFT的窄带内谱线数量不多,加窗主要为了抑制频谱泄漏造成的边带变形。如果是纯稳态信号也可以用Flattop窗,幅值精度更高,但主瓣宽,对邻近谱线的分辨能力稍差。
3.3 细化前后的对比与结果判读
写好主程序,调用一下:
%% 4. 普通FFT对照 figure(1); X_all = fft(x); N_half = floor(N/2); f_all = (0:N_half-1) * fs / N; A_all = abs(X_all(1:N_half)) * 2 / N; plot(f_all, A_all); xlim([600, 780]); xlabel('频率 (Hz)'); ylabel('幅值'); title('普通FFT(直接截取600~780Hz区间)'); grid on; %% 5. 细化谱分析 f0 = 683.2; % 中心频率取啮合频率 M = 10; % 细化倍数 Nfft = 8192; [f_zoom, A_zoom] = zoomfft(x, fs, f0, M, Nfft); figure(2); plot(f_zoom, A_zoom); xlim([f0 - 80, f0 + 80]); xlabel('频率 (Hz)'); ylabel('幅值'); title('细化谱分析(Zoom-FFT, M=10)'); grid on;普通FFT的横轴如果直接限到600到780 Hz,看到的仍是原始分辨率1 Hz(( f_s/N = 20480/40960 = 0.5 ) Hz),在这个范围内,( fm \pm 24.4 ) Hz的边带勉强可见,但2阶边带与噪声底部差别很小,肉眼几乎分不出来。细化谱M=10配合8192点FFT,局部分辨率 ( 20480/(10 \times 8192) = 0.25 ) Hz左右,各阶边带清晰分离,幅值比例也基本对应仿真设定值。
注意一个细节:由于加了Hanning窗,幅值谱不再像矩形窗那样精确等于原始幅值,会有一个窗函数带来的幅值修正系数,代码里用sum(win)做归一化已经处理了这个问题。实测时如果要用幅值做定量判断,建议用Flattop窗再做一次对比。
4. 实测中的几个问题与排查技巧
4.1 频率轴换算错乱是最常见的错误
细化谱写出来第一件事就是检查频率轴。很多人把细化后的频率轴直接当作 ( 0 \sim fs/M ),忘了映射回绝对频率,画出来的图中心频率变成了0 Hz。更隐蔽的一个错误是中心频率映射反了方向,把 ( f0 - fs/(2M) ) 写成了 ( f0 + fs/(2M) ),导致整条谱线左右镜像翻转。
我常用的验证方法很笨但很可靠:用仿真信号测一根已知频率的谱线,比如683.2 Hz,细化后这根谱线必须精确出现在683.2 Hz处,偏了就是频率轴问题。跑通算法后再上实测数据,不要一上来就拿真信号调试,否则错了都不知道错在哪。
4.2 滤波器引起的吉布斯现象与边界失真
FIR滤波器阶数再高,通带边缘都会有过渡带和轻微的振铃现象。细化观察频带的两端(也就是 ( f0 \pm fs/(2M) ) 附近)大约各 ( 10% ) 左右的频带是有一定失真的,谱线幅值可能偏低,甚至出现虚假的小波动。
解决办法有两个。一个是中心频率留裕量,不要正好把关注的特征频率放在细化频带边缘,让目标谱线处于细化带宽中间区域。另一个是适当提高滤波器阶数,同时把过渡带设计得窄一些,但代价是滤波计算量变大,相位畸变也会略有增加。实测中,我一般把目标边带范围控制在细化带宽的70%以内,给滤波器过渡带和振铃留出缓冲。
4.3 数据长度不足:细化谱不是“无中生有”
再强调一次基本概念:频率分辨率的上限由实际信号的观测时长决定。一段1秒的数据,真实频率分辨率就是1 Hz,不管细化倍数取多大,都变不出0.1 Hz的分辨本领。细化谱的价值在于用更少的FFT计算量把局部频段看细,而不是从无到有地创造信息。
所以实测前先算清楚:你需要分辨的最小频率间隔 ( \delta f ) 是多少?对应需要至少 ( 1/\delta f ) 秒的平稳数据?数据不够,宁可先跟试验方沟通延长稳态段时长,也不要硬上细化谱,否则做出来的图“好看”,实际诊断结论是靠不住的。
4.4 细化倍数与FFT点数的匹配原则
细化倍数 ( M ) 和FFT点数 ( Nfft ) 需要一起定,常见错误是 ( M ) 取很大但 ( Nfft ) 没跟上。抽取后有效数据长度是 ( N/M ),如果 ( Nfft ) 远大于 ( N/M ),大部分是补零,谱线虽然平滑但真实分辨率没有提高。
我给出的参考组合是:数据长度2秒以上,( M ) 取8到16,( Nfft ) 取4096到8192。如果数据只有0.5秒,( M ) 取4以下,( Nfft ) 取1024到2048,重点看主要边带结构,不要去抠高次边带细节。细化倍数和FFT点数的合理匹配,可以参考下表。
| 数据时长 | 细化倍数 M | FFT点数 Nfft | 实际有效分辨率 |
|---|---|---|---|
| 0.5 s | 4 | 1024 | ~10 Hz |
| 1 s | 8 | 2048 | ~2.5 Hz |
| 2 s | 10 | 4096 | ~0.5 Hz |
| 5 s | 16 | 8192 | ~0.25 Hz |
这个表是按 ( fs = 20480 ) Hz算的工程经验值,实际使用时用 ( fs/(M \times Nfft) ) 核算一下,保证分辨率低于你关注的最小边带间隔的 ( 1/3 ) 就行。
5. 工程应用中的几个补充建议
5.1 细化谱不是越宽越好,定位好再看
航空发动机齿轮振动信号里的特征频率,除了啮合频率,还有各级齿轮的转频、轴承故障特征频率、叶片通过频率等。细化谱一次只看一个窄带,所以先要明确诊断目标。我个人的操作顺序是:先用普通FFT扫全频段,锁定啮合频率及其大致边带分布范围;再用细化谱细看确认边带间隔与幅值规律;最后结合包络谱验证。三条手段互为印证,单独拎细化谱出来是没有意义的。
5.2 实测数据预处理不能跳过
实测振动信号进细化谱之前,必须先做预处理。首先是去均值,否则直流分量在频移之后会跑到中心频率上,形成虚假谱峰;其次是抗混叠滤波,确保ADC前已经有模拟低通滤波处理;第三是检查是否存在明显的脉冲干扰,比如安装松动引起的瞬态冲击,这种冲击会在细化谱上产生平坦的宽带底噪,严重时掩盖所有边频带。
有一次我处理试车数据,细化谱上出现了两根奇怪的谱线,间隔恰好是50 Hz的整数倍,排查半天发现是测试间里某个电气设备干扰,不是齿轮故障。所以实测数据一定要同步记录环境信息和测点位置,排故的时候才能快速排除外部干扰。
5.3 多段数据平均的问题
有的分析流程喜欢对多段细化谱做平均来压低噪声,这个方法在齿轮故障诊断里要慎用。齿轮故障的边频带幅值会随着转速波动而波动,多段平均之后边带细节可能被抹平。如果确实需要平均,一定要选择同一稳态工况下的数据段,把转频波动控制在 ( \pm 0.5% ) 以内,否则细化谱边带会模糊不清。
我个人现在在做的一个方向是,把细化谱结果跟深度神经网络结合,先用Zoom-FFT把关键频段的高分辨率特征提取出来,再做分类诊断,效果比直接用原始波形喂网络好不少。这个思路在Matlab里搭原型也很顺手,前面给的函数稍加改造,就能批量生成训练用的细化谱特征图。
说到底,细化谱分析不是什么新东西,它在经典的信号处理教材里是被反复讨论的成熟方法,但在航空发动机齿轮故障诊断这个场景里,依然是现场最有实用价值的分析手段之一。只要频率轴换算正确、滤波器选型合理、数据时长够用,这套方法用起来会非常顺手。上面给的代码和参数组合,可以直接拿去做仿真验证,也可以移植到实测数据上试跑,有问题欢迎一起交流。