3. 基于频谱分析的电机轴承故障检测
任务说明
本案例针对电机滚动轴承的振动加速度信号,通过快速傅里叶变换(FFT)将时域波形转换至频域,提取轴承故障特征频率(BPFO、BPFI、BSF、FTF)处的幅值,并与健康状态基线对比,从而判断轴承是否存在内圈、外圈或滚动体故障。输入为一段模拟的轴承振动信号(含噪声及故障特征频率成分),输出为频谱图与故障判定结论。
轴承故障特征频率计算
滚动轴承故障特征频率由几何参数与转频决定。设轴转速为 \( f_r \)(Hz),滚动体个数为 \( Z \),节径为 \( D \),滚动体直径为 \( d \),接触角为 \( \alpha \),则各故障特征频率为:
- 外圈故障频率:\( BPFO = \frac{Z f_r}{2} \left(1 - \frac{d}{D} \cos\alpha\right) \)
- 内圈故障频率:\( BPFI = \frac{Z f_r}{2} \left(1 + \frac{d}{D} \cos\alpha\right) \)
- 滚动体故障频率:\( BSF = \frac{D f_r}{2d} \left(1 - \left(\frac{d}{D} \cos\alpha\right)^2\right) \)
- 保持架故障频率:\( FTF = \frac{f_r}{2} \left(1 - \frac{d}{D} \cos\alpha\right) \)
本案例采用典型深沟球轴承6205-2RS的参数:\( Z=9 \),\( d=7.94 \) mm,\( D=39.04 \) mm,\( \alpha=0 \),转频 \( f_r=29.5 \) Hz(约1770 RPM)。代入计算得:BPFO≈106.4 Hz,BPFI≈159.1 Hz,BSF≈69.8 Hz,FTF≈11.8 Hz。
Python实现代码
import numpy as np
import matplotlib.pyplot as plt
# 轴承参数与特征频率
Z = 9
d = 7.94e-3 # 滚动体直径 (m)
D = 39.04e-3 # 节径 (m)
alpha = 0.0 # 接触角 (rad)
fr = 29.5 # 转频 (Hz)
BPFO = Z * fr / 2 * (1 - d / D * np.cos(alpha))
BPFI = Z * fr / 2 * (1 + d / D * np.cos(alpha))
BSF = D * fr / (2 * d) * (1 - (d / D * np.cos(alpha))**2)
FTF = fr / 2 * (1 - d / D * np.cos(alpha))
print(f"BPFO={BPFO:.1f} Hz, BPFI={BPFI:.1f} Hz, BSF={BSF:.1f} Hz, FTF={FTF:.1f} Hz")
# 生成模拟振动信号(含外圈故障特征)
fs = 12000 # 采样率 12 kHz
T = 2.0 # 采样时长 2 秒
N = int(fs * T)
t = np.linspace(0, T, N, endpoint=False)
# 外圈故障:BPFO 及其 2、3 次谐波,叠加转频调制与噪声
signal = (0.8 * np.sin(2 * np.pi * BPFO * t) +
0.5 * np.sin(2 * np.pi * 2 * BPFO * t) +
0.3 * np.sin(2 * np.pi * 3 * BPFO * t) +
0.2 * np.sin(2 * np.pi * fr * t) * (1 + 0.5 * np.sin(2 * np.pi * BPFO * t)))
rng = np.random.default_rng(42)
signal += 0.15 * rng.standard_normal(N)
# FFT 频谱分析
win = np.hanning(N)
S = np.fft.rfft(signal * win, n=N)
freqs = np.fft.rfftfreq(N, 1 / fs)
mag = 2.0 * np.abs(S) / np.sum(win)
# 在特征频率附近搜索峰值幅值(±1.5 Hz 带宽)
def peak_amplitude(freq_target, freqs, mag, bandwidth=1.5):
mask = (freqs >= freq_target - bandwidth) & (freqs <= freq_target + bandwidth)
if np.any(mask):
return np.max(mag[mask])
return 0.0
amp_bpfo = peak_amplitude(BPFO, freqs, mag)
amp_bpfi = peak_amplitude(BPFI, freqs, mag)
amp_bsf = peak_amplitude(BSF, freqs, mag)
amp_ftf = peak_amplitude(FTF, freqs, mag)
print(f"BPFO幅值={amp_bpfo:.3f}, BPFI幅值={amp_bpfi:.3f}, BSF幅值={amp_bsf:.3f}, FTF幅值={amp_ftf:.3f}")
# 故障判定:阈值设为健康基线幅值的 3 倍(基线由纯噪声信号估计)
noise_floor = 0.15 * np.sqrt(2) / np.sqrt(N) * 2 # 噪声底限近似
threshold = 3 * noise_floor
print(f"判定阈值={threshold:.4f}")
faults = []
if amp_bpfo > threshold:
faults.append("外圈故障")
if amp_bpfi > threshold:
faults.append("内圈故障")
if amp_bsf > threshold:
faults.append("滚动体故障")
if amp_ftf > threshold:
faults.append("保持架故障")
if faults:
print("判定结果:检测到 " + "、".join(faults))
else:
print("判定结果:轴承状态正常")
# 绘制频谱图
plt.figure(figsize=(10, 4))
plt.plot(freqs, mag, linewidth=0.8)
for f, name in [(BPFO, "BPFO"), (BPFI, "BPFI"), (BSF, "BSF"), (FTF, "FTF")]:
plt.axvline(f, color="red", linestyle="--", alpha=0.7)
plt.text(f, plt.ylim()[1]*0.9, name, color="red", fontsize=8, ha="center")
plt.xlim(0, 500)
plt.xlabel("频率 (Hz)")
plt.ylabel("幅值")
plt.title("电机轴承振动信号频谱")
plt.grid(alpha=0.3)
plt.tight_layout()
plt.savefig("bearing_spectrum.png", dpi=150)
plt.show()
运行与验证
运行方式:将上述代码保存为 bearing_fault_detection.py,在已安装 numpy 和 matplotlib 的 Python 3.8+ 环境中执行 python bearing_fault_detection.py。
预期输出:控制台打印特征频率计算值(BPFO≈106.4 Hz,BPFI≈159.1 Hz,BSF≈69.8 Hz,FTF≈11.8 Hz),随后打印各特征频率处的频谱幅值。由于模拟信号中注入了 BPFO 基频及谐波成分,BPFO 幅值应显著高于阈值(约0.003),而 BPFI、BSF、FTF 处幅值接近噪声底限,因此判定结果为“检测到外圈故障”。同时生成 bearing_spectrum.png 频谱图,图中在 BPFO 及其 2、3 次谐波处可见明显峰值。
判定标准:若代码运行后控制台输出“检测到外圈故障”,且频谱图中 BPFO 频率处出现明显尖峰(幅值超过图中噪声底限的3倍以上),则验证通过。如需测试内圈或滚动体故障,可将信号生成部分中的 BPFO 替换为 BPFI 或 BSF 后重新运行。