1. 轴承故障信号仿真概述
在工业设备维护领域,轴承故障诊断一直是关键课题。据统计,约40%的旋转机械故障与轴承相关。传统诊断方法依赖现场采集的真实故障信号,但这种方式存在成本高、周期长且难以获取特定故障样本的局限。通过Python仿真轴承故障信号,我们可以快速生成各类典型故障的模拟数据,为算法验证和诊断方法研究提供高效工具。
这个仿真系统实现了三大核心功能:
- 支持内圈、外圈和滚动体三种典型故障类型的信号生成
- 可调节信噪比模拟不同工况环境
- 自动计算并展示故障特征频率及其谐波
2. 故障机理与频率计算原理
2.1 轴承结构参数定义
典型滚动轴承由内圈、外圈、滚动体和保持架组成。仿真需要以下关键参数:
- 轴转速n(转/秒)
- 滚动体直径d(米)
- 节圆直径D(米)
- 接触角α(弧度)
注意:接触角指滚动体与滚道接触点的法线与轴承径向平面的夹角,常见值为0°(深沟球轴承)或15-25°(角接触轴承)
2.2 故障频率计算公式推导
不同部位的缺陷会产生特定频率的周期性冲击,其计算公式如下:
2.2.1 内圈故障频率(FTF)
[ f_i = \frac{n}{2}\left(1 + \frac{d}{D}\cos\alpha\right) ]
当内圈存在缺陷时,每个滚动体经过缺陷点都会产生冲击。由于内圈随轴旋转,缺陷位置会周期性接近和远离载荷区,导致振幅调制现象。
2.2.2 外圈故障频率(BPF)
[ f_o = \frac{n}{2}\left(1 - \frac{d}{D}\cos\alpha\right) ]
外圈固定时,缺陷产生的冲击频率相对稳定。实际诊断中,外圈故障信号通常包含丰富的谐波成分。
2.2.3 滚动体故障频率(BSF)
[ f_b = \frac{D}{d}\left[1 - \left(\frac{d}{D}\cos\alpha\right)^2\right]\frac{n}{2} ]
滚动体缺陷会产生双重调制效应:既随保持架公转,又存在自转运动。其故障特征频率通常较低。
3. Python仿真实现详解
3.1 核心代码架构
import numpy as np import matplotlib.pyplot as plt from scipy.signal import hilbert3.1.1 参数初始化模块
# 轴承几何参数 n = 10 # 转速 (Hz) d = 0.01 # 滚动体直径 (m) D = 0.1 # 节圆直径 (m) alpha = np.pi/4 # 接触角 (rad) # 信号参数 fs = 10000 # 采样率 (推荐≥10倍最高故障频率) duration = 1 # 信号时长 (s)工程经验:采样率应满足Nyquist定理,通常取故障频率的10倍以上。对于高速轴承,可能需要50kHz以上的采样率。
3.1.2 故障频率计算函数
def calc_fault_freq(fault_type): if fault_type == 'inner': return (n/2) * (1 + (d/D)*np.cos(alpha)) elif fault_type == 'outer': return (n/2) * (1 - (d/D)*np.cos(alpha)) elif fault_type == 'ball': return (D/d) * (1 - ((d/D)*np.cos(alpha))**2) * (n/2) else: raise ValueError("故障类型必须是 'inner', 'outer' 或 'ball'")3.2 信号生成与噪声控制
3.2.1 基带信号生成
def generate_base_signal(fault_freq, fs, duration): t = np.linspace(0, duration, int(fs*duration), endpoint=False) # 冲击信号模型 impact = np.exp(-50*t) * np.sin(2*np.pi*5000*t) impact = impact[:100] # 截取单个冲击 # 周期性冲击序列 period = int(fs/fault_freq) signal = np.zeros_like(t) for i in range(0, len(signal), period): signal[i:i+len(impact)] += impact return t, signal3.2.2 噪声添加与SNR控制
def add_noise(signal, target_snr): # 计算信号功率 sig_power = np.mean(signal**2) # 根据SNR计算噪声功率 noise_power = sig_power / (10**(target_snr/10)) # 生成高斯白噪声 noise = np.random.normal(0, np.sqrt(noise_power), len(signal)) return signal + noise3.3 包络分析实现
def compute_envelope(signal): analytic_signal = hilbert(signal) envelope = np.abs(analytic_signal) return envelope def compute_spectrum(signal, fs): n = len(signal) freq = np.fft.fftfreq(n, 1/fs)[:n//2] spectrum = np.abs(np.fft.fft(signal))[:n//2] * 2/n return freq, spectrum4. 完整仿真流程与可视化
4.1 主程序流程
# 用户输入 fault_type = input("输入故障类型 (inner/outer/ball): ") snr = float(input("输入目标SNR (dB): ")) # 计算故障频率 fault_freq = calc_fault_freq(fault_type) # 生成信号 t, clean_signal = generate_base_signal(fault_freq, fs, duration) noisy_signal = add_noise(clean_signal, snr) # 包络分析 envelope = compute_envelope(noisy_signal) freq_env, spec_env = compute_spectrum(envelope, fs) freq_raw, spec_raw = compute_spectrum(noisy_signal, fs)4.2 结果可视化
plt.figure(figsize=(12, 8)) # 时域信号 plt.subplot(3, 1, 1) plt.plot(t, noisy_signal) plt.title(f'{fault_type} Fault Time Domain (SNR={snr}dB)') plt.xlabel('Time (s)') plt.ylabel('Amplitude') # 频谱 plt.subplot(3, 1, 2) plt.plot(freq_raw, spec_raw) plt.xlim(0, 1000) plt.title('Raw Spectrum') plt.xlabel('Frequency (Hz)') plt.ylabel('Magnitude') # 包络谱 plt.subplot(3, 1, 3) plt.plot(freq_env, spec_env) plt.xlim(0, 500) plt.title('Envelope Spectrum') plt.xlabel('Frequency (Hz)') plt.ylabel('Magnitude') plt.tight_layout() plt.show()5. 工程实践要点与问题排查
5.1 参数选择经验
采样率设置:
- 最低要求:fs > 2×最高感兴趣频率
- 推荐值:fs ≥ 10×fault_freq
- 过高的采样率会导致计算量剧增
SNR选择指南:
- 实验室环境:30-50dB
- 工业现场:10-20dB
- 极端工况:<10dB
信号时长建议:
- 至少包含10个故障周期
- 推荐:duration ≥ 10/fault_freq
5.2 常见问题排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| 包络谱无峰值 | SNR过低 | 提高SNR或增加平均次数 |
| 频谱出现混叠 | 采样率不足 | 提高采样率或加抗混叠滤波器 |
| 频率偏移 | 参数计算错误 | 检查几何参数单位一致性 |
| 谐波不明显 | 冲击模型太简单 | 改用更复杂的冲击响应模型 |
5.3 高级改进方向
- 更真实的冲击模型:
def advanced_impact_model(t): return np.exp(-100*t) * (np.sin(2*np.pi*8000*t) + 0.5*np.sin(2*np.pi*12000*t))- 转速波动模拟:
def add_speed_variation(t, base_freq): freq_mod = base_freq * (1 + 0.1*np.sin(2*np.pi*0.5*t)) return np.sin(2*np.pi*np.cumsum(freq_mod)/fs)- 共振频带选择:
def bandpass_filter(signal, fs, lowcut, highcut): nyq = 0.5 * fs b, a = butter(4, [lowcut/nyq, highcut/nyq], btype='band') return filtfilt(b, a, signal)在实际轴承诊断项目中,我们通常会结合多个频带的分析结果。比如某风电轴承案例中,通过比较1-3kHz和5-8kHz两个共振频带的包络谱,发现外圈故障特征在5-8kHz频带更加明显。这种多频段分析的方法可以有效提高诊断准确率。