带式输送机托辊声学故障诊断这件事,我在现场投入过不少精力。这套方法的核心思路并不复杂:托辊在旋转过程中,轴承滚道、保持架、辊皮一旦出现损伤,会产生区别于正常运行的特征声学信号,用麦克风采集声音,再通过信号处理和模式识别把故障类型分出来。相比传统的振动诊断,声学方案不用贴传感器,测点选择更灵活,还可以对远距离、高温、粉尘环境下的托辊做非接触检测,这在散料输送现场有天然优势。这篇文章会把整套流程、核心代码、现场踩坑经验一次讲清楚,适合做设备智能维护的工程师、搞工业声学的算法同学,以及对故障诊断感兴趣的学生参考。
1. 项目整体思路与方案选型
1.1 托辊常见的故障类型与声学特征机理
托辊是带式输送机上数量最大的转动部件,一根输送带下面往往压着成百上千个托辊。它的故障主要集中在这几类:轴承外圈磨损、轴承保持架损坏、辊皮磨损或偏心、密封件卡滞等。轴承故障是统计占比最高的,尤其是外圈损伤,因为外圈固定不动,承受径向载荷,异物侵入和疲劳剥落都会在滚道表面留下缺陷。
从声学机理上看,滚子滚过缺陷位置时会产生短促的冲击激励,激起托辊筒体和轴承座的固有振荡。这种冲击会周期性重复,周期跟轴转速和故障部位有关,冲击能量集中在几百赫兹到几千赫兹的频带内。保持架故障的频率通常较低,几赫兹到十几赫兹的调制成分明显;辊皮磨损则体现为宽带随机噪声抬升,同时在中频段出现新的谱峰。这些声学差异就是分类模型可以学习的核心依据。
1.2 为什么选择声学方案而不是传统振动方案
传统振动诊断需要把加速度传感器安装到托辊轴承座上,这在移动的输送带、频繁更换的托辊面前很难实现。架空、回程段托辊多数安装在槽钢支架上,传感器线缆容易受到物料冲击和人员走动影响;且托辊数量多,每个都要布点,成本完全不可接受。声学方案用麦克风阵列或单麦克风,非接触采集,可以覆盖一段输送线路上的多组托辊,施工量小得多。
声学方案还有另一个容易被低估的优势:它采集的是空气声,包含着托辊壳体辐射和周围结构传播的综合信息。当托辊早期故障产生极小的结构振动时,壳体辐射效率低,但在轴承座与辊皮之间有空气间隙时,高频冲击成分反而能通过空气传播得比较清晰。实测经验表明,在安静的皮带空载工况下,声学特征对轴承早期损伤的敏感度不输于贴在轴承座上的振动传感器。
1.3 这套方法的适用边界与实现成本
要提前说清楚边界,声学诊断不是万能的。高速重载输送机在运转时,整条线噪声经常超过90分贝,物料下落声、托辊与皮带摩擦声、电机风噪混在一起,信噪比很差。这种情况下单纯靠单麦克风很难分辨某一根托辊的微弱故障声。通常的解决办法是靠近目标区域布置采集点,或者用多通道麦克风阵列做波束定向,让信号聚焦在需要监测的区段。
成本方面,一套部署方案大概包括工业麦克风、数据采集卡、边缘计算单元和算法软件。单通道方案可以压到很低的硬件成本,如果只做定期巡检,一台便携录音设备加一台笔记本电脑就够跑通整个流程,这也是这类项目能够很快从实验走向现场落地的重要原因。
2. 声学信号采集与特征工程设计
2.1 采集端怎么搭:麦克风选型、采样率与数据长度
麦克风选型上,现场环境有粉尘和潮湿的,优先选工业级防水防尘拾音器,输出信号一般走4-20mA电流环或者标准音频线路输出;需要严格防爆的场所,要选经过防爆认证的话筒,切不可用普通驻极体麦克风凑数。普通实验室验证场景,一支USB指向性麦克风就够了。
采样率建议设置在32000 Hz或者至少16000 Hz。托辊故障的冲击衰减振荡一般集中在3 kHz到8 kHz之间,采样率太低会把高频冲击特征削掉,太高了数据量浪费。每一段样本建议至少采集2秒,更稳妥的是采集5到10秒后滑窗切分,这样可以覆盖多个冲击周期,保证统计特征稳定。
2.2 预处理:去直流、滤波、分帧加窗
原始信号到手之后不能直接提特征,要先走一遍预处理:
- 去直流分量,消除麦克风偏置和采集通道的直流漂移。
- 带通滤波,通常保留200 Hz到10000 Hz频带,把工频干扰和超高频无关噪声滤掉。
- 分帧加窗,每帧长度取2048点或4096点,帧移取50%到75%重叠,用汉宁窗抑制频谱泄漏。
这里有一个非常关键的经验:现场的皮带机工频干扰往往不只在50 Hz,变频器还会产生丰富的谐波,甚至能在几百赫兹处形成很强的线谱。如果这些线谱进入特征区间,分类器会把工频干扰当成托辊特征学过。所以带通下界不能设在50 Hz附近,至少抬到200 Hz以上,同时可以在预处理里加一套陷波滤波,针对PLC实时输出的转速和变频器载频做动态滤除。
2.3 特征怎么选:时域、频域与MFCC组合
特征选取是这套方法的核心。只用单一维度特征很容易翻车:时域特征对环境噪声敏感,频域特征容易混入固定频率干扰,而梅尔倒谱系数对噪声有天然鲁棒性,但单独用又丢失部分时域冲击特征。所以实践中最稳的是做特征拼接。
时域特征推荐这几个:均方根值(RMS)、峰值因子(波峰与RMS之比)、峭度(四阶矩归一化)。RMS体现整体能量,峰值因子对冲击敏感,峭度能反映信号偏离高斯分布的程度,轴承损伤时冲击成分会让峭度显著上升。
频域特征可以从FFT谱里提取谱质心、谱滚降点、500-2000 Hz频带能量占比、2000-4000 Hz频带能量占比、前三个峰值谱线对应的频率。尤其是轴承外圈故障时,谱线会在故障特征频率附近产生边频带,提取边频带能量比单纯看基频更可靠。
MFCC特征来自语音识别领域,但用在机械声学诊断上效果意外地好。它根据梅尔刻度对频谱做非线性映射,模拟人耳对低频敏感、高频不敏感的特性,再把频谱包络压缩成低维系数。实测中,MFCC的前13维均值加上方差,一组就能达到26维,已经能很稳定地区分正常、外圈故障、保持架故障和辊皮磨损四类。
3. 核心代码实现:从波形到故障分类
3.1 生成模拟故障声信号用于快速验证
在真实托辊数据还没采集好之前,建议先用可编程合成的信号把算法流程跑通。下面的代码模拟了四类托辊声学信号:正常、外圈故障、保持架故障、辊皮磨损。合成信号虽然不能完全替代现场真实噪声,但用于验证特征提取和分类流程完全够用。
import numpy as np from scipy.signal import butter, filtfilt def generate_static_noise(sr, duration): """背景随机噪声,模拟托辊正常运转时的平稳声底""" n = int(sr * duration) t = np.arange(n) / sr # 宽带白噪声 + 50/100Hz工频残留 noise = np.random.normal(0, 0.5, n) hum = 0.15 * np.sin(2 * np.pi * 50 * t) + 0.08 * np.sin(2 * np.pi * 100 * t) return noise + hum def add_impact_series(t, sr, interval_freq, carrier_freq, decay, amplitude): """在指定重复频率下产生衰减振荡冲击串""" signals = np.zeros_like(t) period = 1.0 / interval_freq n_imp = int(t[-1] / period) for i in range(n_imp): start = i * period mask = (t >= start) & (t < start + 0.05) dt = t[mask] - start if len(dt) > 0: signals[mask] += amplitude * np.exp(-decay * dt) * np.sin(2 * np.pi * carrier_freq * dt) return signals def generate_tuoer_signal(fault_type, sr=16000, duration=2.0): """ fault_type: 0-正常 1-外圈故障 2-保持架故障 3-辊皮磨损 """ n = int(sr * duration) t = np.arange(n) / sr y = generate_static_noise(sr, duration) if fault_type == 1: # 外圈故障:冲击重复频率约28Hz,载波频率约3200Hz,衰减系数120 y += add_impact_series(t, sr, interval_freq=28.0, carrier_freq=3200, decay=120, amplitude=3.0) elif fault_type == 2: # 保持架故障:调制频率低,约6Hz,附带一次冲击串 y += add_impact_series(t, sr, interval_freq=6.0, carrier_freq=1600, decay=60, amplitude=2.5) elif fault_type == 3: # 辊皮磨损:宽带噪声抬升 + 1000Hz附近窄带谱峰 y += np.random.normal(0, 1.2, n) b, a = butter(2, [900 / (sr / 2), 1200 / (sr / 2)], btype='band') narrowband = filtfilt(b, a, np.random.normal(0, 2.0, n)) y += narrowband # 统一做一次带通,限制在分析频带内 b, a = butter(4, [200 / (sr / 2), 8000 / (sr / 2)], btype='band') y = filtfilt(b, a, y) return y这段代码的设计思路是模拟出不同类型故障在声学上的差异:外圈故障是高频冲击串,保持架故障是低频调制冲击,辊皮磨损是宽带噪声加窄带共振。实际工程里,如果手里有半年的历史录音数据,完全可以用真实数据替换这个生成函数,后面特征提取的代码不需要大改。
3.2 特征提取函数:把音频段变成特征向量
特征提取是代码里最核心的一段。下面这段代码实现了时域特征、频域特征、MFCC特征的拼接,输出为固定维度的特征向量。MFCC部分依赖librosa,如果没有装,可以先执行pip install librosa。
import librosa import numpy as np def extract_features(y, sr=16000): """从一段音频中提取特征向量(时域+频域+MFCC)""" features = [] # 1. 时域特征 rms = np.sqrt(np.mean(y ** 2)) peak = np.max(np.abs(y)) crest_factor = peak / (rms + 1e-8) mean_signal = np.mean(y) kurtosis = np.mean((y - mean_signal) ** 4) / (np.std(y) ** 4 + 1e-8) features.extend([rms, crest_factor, kurtosis]) # 2. 频域特征:使用STFT计算谱 D = np.abs(librosa.stft(y, n_fft=2048, hop_length=512, win_length=2048)) power = D ** 2 freqs = librosa.fft_frequencies(sr=sr, n_fft=2048) # 谱质心 spectral_centroid = np.sum(freqs * power.sum(axis=1)) / (power.sum() + 1e-8) # 谱滚降点(能量占比85%处的频率) cum_energy = np.cumsum(power.sum(axis=1)) rolloff_idx = np.where(cum_energy >= 0.85 * cum_energy[-1])[0] rolloff = freqs[rolloff_idx[0]] if len(rolloff_idx) > 0 else freqs[-1] # 子频带能量占比 spec_total = power.sum() + 1e-8 band_low = power[(freqs >= 500) & (freqs < 2000)].sum() / spec_total band_mid = power[(freqs >= 2000) & (freqs < 4000)].sum() / spec_total # 频谱最大峰值对应频率及幅度 mag_spectrum = power.sum(axis=1) peak_idx = np.argmax(mag_spectrum) peak_freq = freqs[peak_idx] peak_amp = mag_spectrum[peak_idx] / spec_total features.extend([spectral_centroid, rolloff, band_low, band_mid, peak_freq, peak_amp]) # 3. MFCC特征(13维均值 + 13维方差 = 26维) mfcc = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=13, n_fft=2048, hop_length=512) mfcc_mean = np.mean(mfcc, axis=1) mfcc_std = np.std(mfcc, axis=1) features.extend(mfcc_mean.tolist()) features.extend(mfcc_std.tolist()) return np.array(features) # 快速验证一个样本维度 sample = generate_tuoer_signal(1, sr=16000, duration=2.0) feat = extract_features(sample, sr=16000) print("特征维度:", feat.shape)特征向量的维度是3(时域)+6(频域)+26(MFCC)=35维。这个维度适中,不会因为维度爆炸导致小样本过拟合,也足够表达不同故障之间的差异。
可能有读者会问为什么MFCC要取均值又取方差。均值刻画的是频谱包络的整体形态,方差刻画的是包络随时间波动的剧烈程度。托辊故障冲击是周期性的,MFCC的帧间波动特征很能反映这种脉冲调制结构,方差特征在这种场景下参与分类的作用甚至比均值还大。
3.3 随机森林分类器训练与评估
特征抽取完成后,就可以进入建模环节。这里用随机森林而不是深度学习模型,原因很实际:在样本量不大的工业场景里,树模型不容易过拟合,训练速度快,结果可解释性强,还能直接输出特征重要性,方便后续做特征精简。当然,如果后面样本积累到几万段以上,换成CNN加梅尔谱图也是顺理成章的方向。
from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report, confusion_matrix, accuracy_score import warnings warnings.filterwarnings('ignore') # 生成数据集:每个类别生成80段,每段2秒 sr = 16000 duration = 2.0 X, y = [], [] for fault_type in [0, 1, 2, 3]: for _ in range(80): audio = generate_tuoer_signal(fault_type, sr=sr, duration=duration) X.append(extract_features(audio, sr=sr)) y.append(fault_type) X = np.array(X) y = np.array(y) print("数据集形状:", X.shape, "标签分布:", np.bincount(y)) # 划分训练集和测试集,保证各类别比例一致 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.25, stratify=y, random_state=42 ) # 训练随机森林 clf = RandomForestClassifier(n_estimators=300, max_depth=None, min_samples_leaf=1, random_state=42) clf.fit(X_train, y_train) # 评估 y_pred = clf.predict(X_test) acc = accuracy_score(y_test, y_pred) print(f"测试集准确率: {acc:.4f}") print(classification_report(y_test, y_pred, target_names=['正常', '外圈故障', '保持架故障', '辊皮磨损'])) print("混淆矩阵:") print(confusion_matrix(y_test, y_pred))在合成数据上,这套代码跑下来的准确率通常在95%以上。这里要提醒一句:合成信号干净,好分,真实现场数据会复杂得多,准确率跌10到20个百分点都很正常。真实项目中达到85%以上的四分类准确率,就已经具备工程落地价值了。
3.4 特征重要性分析与可视化
随机森林一个显著优势是自带特征重要性评估。下面的代码可以找出哪些特征在分类中贡献最大,并绘制混淆矩阵热力图和特征重要性条形图。
import matplotlib.pyplot as plt import pandas as pd # 特征名称 feature_names = ['RMS', '波峰因子', '峭度', '谱质心', '谱滚降点', '500-2k能量比', '2k-4k能量比', '峰值频率', '峰值幅度'] + [f'MFCC{i}_mean' for i in range(1, 14)] + [f'MFCC{i}_std' for i in range(1, 14)] # 特征重要性 importance = clf.feature_importances_ df_imp = pd.DataFrame({'feature': feature_names, 'importance': importance}) df_imp = df_imp.sort_values('importance', ascending=False) # 绘制特征重要性 TOP15 plt.figure(figsize=(10, 6)) plt.barh(df_imp['feature'][:15][::-1], df_imp['importance'][:15][::-1], color='steelblue') plt.xlabel('重要性得分') plt.title('随机森林特征重要性 TOP15') plt.tight_layout() plt.savefig('feature_importance.png', dpi=150) # 混淆矩阵热力图 from sklearn.metrics import ConfusionMatrixDisplay disp = ConfusionMatrixDisplay(confusion_matrix(y_test, y_pred), display_labels=['正常', '外圈故障', '保持架故障', '辊皮磨损']) disp.plot(cmap='Blues') plt.savefig('confusion_matrix.png', dpi=150)我踩过的一个典型坑是特征名字对不上顺序,导致特征重要性图画出来和预期不符。建议每次构造特征向量时都用列表把特征名和值配对保存,哪怕多写几行代码,后面排查问题会省很多时间。
4. 现场实战中的常见问题与避坑经验
4.1 现场背景噪声盖过故障特征怎么办
这是推行声学诊断遇到最多的质疑,也是最常见的问题。实际处理思路有三个层次:
第一,采集时机尽量选择皮带空载或轻载工况。空载时没有物料撞击声,托辊的故障声反而是最突出的。实践中的做法是在控制程序里联动采集器,皮带启动后自动检测皮带速度信号,速度稳定且没有物料流信号时触发采集窗口。第二,增加麦克风与待测托辊的距离约束,拾音器距离目标越近,信噪比越好。实测中麦克风距托辊中心0.5米以内,效果远好于1.5米以外。第三,使用相减算法做背景噪声抑制。如果现场有条件布置一个参考麦克风,用来采集远离输送带的背景噪声,可以在特征层面把参考麦克风的功率谱估计从目标信号中减去。
低频风机噪声和皮带摩擦声往往能量很大,但在频带上与托辊故障声重叠不多。风机噪声集中在1000赫兹以下,皮带摩擦声是宽带平稳噪声,但托辊冲击的高频衰减振荡在3000赫兹以上,能量带并不完全重合。所以,带通滤波上限定在8000赫兹左右、下限定在200赫兹左右,是一个非常有效的预处理起点。
4.2 样本不均衡与模型过拟合怎么处理
现场采集的正常样本往往远多于故障样本,因为多数托辊是正常的。训练集如果严重不均衡,模型会倾向于把所有样本都判成正常,故障样本反而全部漏报。处理手段主要靠三种:
一是对故障样本做过采样。最不推荐的简单重复采样,虽然代码好写,但模型会记死少数样本的细节,泛化很差。推荐的是数据集增强:给原始故障样本加不同信噪比的高斯白噪声、做小幅时间缩放、随机平移起始点、在频域上做轻微音高偏移。增幅比例控制在3到5倍就够了,太多又会引入重复模式的伪特征。
二是调整分类权重。随机森林里设置class_weight='balanced',让少数类的误分类代价变大,这个参数在Sklearn里一行就能解决,效果直观。实际项目中我把故障样本的class_weight调到正常类的两倍后,故障召回率能提升近20个百分点。
三是迁移学习思路。即使现场数据量不够,贝叶斯优化小组可以先在公开轴承故障数据集上预训练一个模型,再用真实现场故障样本做微调。声音信号的物理规律是共通的,预训练模型的特征提取层不需要全部重学,只需要在顶部分类层上做调整。
4.3 代码在真实部署中会遇到哪些新问题
实验室里跑通的代码,搬到现场会遇到一堆新问题,我列几个高频出现的:
采样不同步问题。多通道采集时,USB声卡的多通道同步性还行,如果是独立采集卡,各通道之间可能存在微秒级别的相位差。对单通道分类影响不大,但一旦做阵列波束定向,这个问题会被放大,建议上位机里做一次多通道延迟标定。
缓存溢出与丢帧。树莓派或嵌入式工控机上跑Python推理,特征提取里librosa的STFT计算量不小。连续在线监测时,采集线程和推理线程如果没有用队列解耦,推理跟不上采集速度就会不断丢帧。建议把录音线程和分类线程分开,录音线程只负责写环形缓冲区,分类线程从缓冲区取最新一段数据做推理,宁可隔几秒出一个结果,也不要卡死采集进程。
模型漂移问题。季节变化、输送带更换、皮带跑偏调整,都会让托辊声学分布缓慢变化。现场部署时要定期收集新样本做增量训练,至少做到月度更新。我习惯在边缘设备上保留最近一个月的预测结果和对应原始音频,一旦现场反馈有托辊损坏,立刻把损坏前后的音频提取出来补进数据集,形成数据闭环。
4.4 参数调优的几个实测经验数据
这里给一组我自己反复用过的参数基准:
- STFT的n_fft选2048,hop_length选512,帧重叠约75%。n_fft太大,时域分辨率不够,故障冲击的时间定位会模糊;n_fft太小,频域分辨率差,边频带提取不出来。
- MFCC的n_mfcc取13到20之间。取到40以上会导致特征维度爆炸,小样本下模型退化得非常快。
- 随机森林n_estimators取300足够。再往上增加只会拖慢推理速度,树太多以后准确率提升基本可以忽略。
- 单段样本时长取2秒。短于1秒,冲击周期覆盖不全;长于5秒,混入异常瞬态的概率增大,且推理延迟高。
参数调优最好的路径不是暴力网格搜索,而是一次只动一个变量。先在固定测试集上锁定MFCC维数,再调滤波器上下界,最后调整随机森林深度,能省下大量重复训练时间。
5. 进一步扩展的思路与部署建议
这套方法目前最成熟的形态是便携巡检+边缘设备在线识别。便携巡检用小麦克风逐点采集,蓝牙或直连手机,识别结果实时显示;在线监测则是在输送机头部、中部、回程段固定安装拾音器,把音频流接入边缘计算盒子,模型自动输出异常托辊编号和故障类型,推送到维护工单系统。
如果想往深度学习方向演进,推荐从梅尔谱图加轻量级CNN开始。把每段2秒音频转成64×64的梅尔谱图,输入到参数量几百万的CNN里,在几万段数据规模下,分类能力会比随机森林强不少。代价是训练成本和对标注数据量的要求都会上一个台阶,而且推理端的算力要求也会提高。先用随机森林把数据管道跑通,再逐步置换模型,是风险最低的演进路线。
声学诊断还可以和其他传感器融合。振动传感器加声学麦克风,覆盖结构声和空气声两个传播路径;如果托辊表面温度异常,红外测温枪或者热像仪又能提供另一维度的信息。多个证据源做决策级融合,能显著降低误报率,这也是工业故障诊断从单点技术走向综合监测的必然趋势。
最后分享一点个人体会:声学诊断项目能不能落地,算法只占一半,另一半在于数据采集习惯和现场反馈机制。很多项目算法调好了,却因为采集装置维护不到位、故障样本没打标、现场没有按流程反馈真实验证结果,最后也只能停在demo阶段。从一开始就让机修人员参与进来,出现一根坏辊就补一条标注数据,让模型跟着现场一起成长,这件事才能越做越顺。这也是我认为比任何代码技巧都更重要的实战心法。