带式输送机托辊声学故障诊断这件事我在现场投入过不少精力。这套方法的核心思路并不复杂托辊在旋转过程中轴承滚道、保持架、辊皮一旦出现损伤会产生区别于正常运行的特征声学信号用麦克风采集声音再通过信号处理和模式识别把故障类型分出来。相比传统的振动诊断声学方案不用贴传感器测点选择更灵活还可以对远距离、高温、粉尘环境下的托辊做非接触检测这在散料输送现场有天然优势。这篇文章会把整套流程、核心代码、现场踩坑经验一次讲清楚适合做设备智能维护的工程师、搞工业声学的算法同学以及对故障诊断感兴趣的学生参考。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, sr16000, duration2.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_freq28.0, carrier_freq3200, decay120, amplitude3.0) elif fault_type 2: # 保持架故障调制频率低约6Hz附带一次冲击串 y add_impact_series(t, sr, interval_freq6.0, carrier_freq1600, decay60, amplitude2.5) elif fault_type 3: # 辊皮磨损宽带噪声抬升 1000Hz附近窄带谱峰 y np.random.normal(0, 1.2, n) b, a butter(2, [900 / (sr / 2), 1200 / (sr / 2)], btypeband) narrowband filtfilt(b, a, np.random.normal(0, 2.0, n)) y narrowband # 统一做一次带通限制在分析频带内 b, a butter(4, [200 / (sr / 2), 8000 / (sr / 2)], btypeband) 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, sr16000): 从一段音频中提取特征向量时域频域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_fft2048, hop_length512, win_length2048)) power D ** 2 freqs librosa.fft_frequencies(srsr, n_fft2048) # 谱质心 spectral_centroid np.sum(freqs * power.sum(axis1)) / (power.sum() 1e-8) # 谱滚降点能量占比85%处的频率 cum_energy np.cumsum(power.sum(axis1)) 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(axis1) 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(yy, srsr, n_mfcc13, n_fft2048, hop_length512) mfcc_mean np.mean(mfcc, axis1) mfcc_std np.std(mfcc, axis1) features.extend(mfcc_mean.tolist()) features.extend(mfcc_std.tolist()) return np.array(features) # 快速验证一个样本维度 sample generate_tuoer_signal(1, sr16000, duration2.0) feat extract_features(sample, sr16000) print(特征维度:, feat.shape)特征向量的维度是3时域6频域26MFCC35维。这个维度适中不会因为维度爆炸导致小样本过拟合也足够表达不同故障之间的差异。可能有读者会问为什么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, srsr, durationduration) X.append(extract_features(audio, srsr)) 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_size0.25, stratifyy, random_state42 ) # 训练随机森林 clf RandomForestClassifier(n_estimators300, max_depthNone, min_samples_leaf1, random_state42) 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能量比, 峰值频率, 峰值幅度] [fMFCC{i}_mean for i in range(1, 14)] [fMFCC{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, ascendingFalse) # 绘制特征重要性 TOP15 plt.figure(figsize(10, 6)) plt.barh(df_imp[feature][:15][::-1], df_imp[importance][:15][::-1], colorsteelblue) plt.xlabel(重要性得分) plt.title(随机森林特征重要性 TOP15) plt.tight_layout() plt.savefig(feature_importance.png, dpi150) # 混淆矩阵热力图 from sklearn.metrics import ConfusionMatrixDisplay disp ConfusionMatrixDisplay(confusion_matrix(y_test, y_pred), display_labels[正常, 外圈故障, 保持架故障, 辊皮磨损]) disp.plot(cmapBlues) plt.savefig(confusion_matrix.png, dpi150)我踩过的一个典型坑是特征名字对不上顺序导致特征重要性图画出来和预期不符。建议每次构造特征向量时都用列表把特征名和值配对保存哪怕多写几行代码后面排查问题会省很多时间。4. 现场实战中的常见问题与避坑经验4.1 现场背景噪声盖过故障特征怎么办这是推行声学诊断遇到最多的质疑也是最常见的问题。实际处理思路有三个层次第一采集时机尽量选择皮带空载或轻载工况。空载时没有物料撞击声托辊的故障声反而是最突出的。实践中的做法是在控制程序里联动采集器皮带启动后自动检测皮带速度信号速度稳定且没有物料流信号时触发采集窗口。第二增加麦克风与待测托辊的距离约束拾音器距离目标越近信噪比越好。实测中麦克风距托辊中心0.5米以内效果远好于1.5米以外。第三使用相减算法做背景噪声抑制。如果现场有条件布置一个参考麦克风用来采集远离输送带的背景噪声可以在特征层面把参考麦克风的功率谱估计从目标信号中减去。低频风机噪声和皮带摩擦声往往能量很大但在频带上与托辊故障声重叠不多。风机噪声集中在1000赫兹以下皮带摩擦声是宽带平稳噪声但托辊冲击的高频衰减振荡在3000赫兹以上能量带并不完全重合。所以带通滤波上限定在8000赫兹左右、下限定在200赫兹左右是一个非常有效的预处理起点。4.2 样本不均衡与模型过拟合怎么处理现场采集的正常样本往往远多于故障样本因为多数托辊是正常的。训练集如果严重不均衡模型会倾向于把所有样本都判成正常故障样本反而全部漏报。处理手段主要靠三种一是对故障样本做过采样。最不推荐的简单重复采样虽然代码好写但模型会记死少数样本的细节泛化很差。推荐的是数据集增强给原始故障样本加不同信噪比的高斯白噪声、做小幅时间缩放、随机平移起始点、在频域上做轻微音高偏移。增幅比例控制在3到5倍就够了太多又会引入重复模式的伪特征。二是调整分类权重。随机森林里设置class_weightbalanced让少数类的误分类代价变大这个参数在Sklearn里一行就能解决效果直观。实际项目中我把故障样本的class_weight调到正常类的两倍后故障召回率能提升近20个百分点。三是迁移学习思路。即使现场数据量不够贝叶斯优化小组可以先在公开轴承故障数据集上预训练一个模型再用真实现场故障样本做微调。声音信号的物理规律是共通的预训练模型的特征提取层不需要全部重学只需要在顶部分类层上做调整。4.3 代码在真实部署中会遇到哪些新问题实验室里跑通的代码搬到现场会遇到一堆新问题我列几个高频出现的采样不同步问题。多通道采集时USB声卡的多通道同步性还行如果是独立采集卡各通道之间可能存在微秒级别的相位差。对单通道分类影响不大但一旦做阵列波束定向这个问题会被放大建议上位机里做一次多通道延迟标定。缓存溢出与丢帧。树莓派或嵌入式工控机上跑Python推理特征提取里librosa的STFT计算量不小。连续在线监测时采集线程和推理线程如果没有用队列解耦推理跟不上采集速度就会不断丢帧。建议把录音线程和分类线程分开录音线程只负责写环形缓冲区分类线程从缓冲区取最新一段数据做推理宁可隔几秒出一个结果也不要卡死采集进程。模型漂移问题。季节变化、输送带更换、皮带跑偏调整都会让托辊声学分布缓慢变化。现场部署时要定期收集新样本做增量训练至少做到月度更新。我习惯在边缘设备上保留最近一个月的预测结果和对应原始音频一旦现场反馈有托辊损坏立刻把损坏前后的音频提取出来补进数据集形成数据闭环。4.4 参数调优的几个实测经验数据这里给一组我自己反复用过的参数基准STFT的n_fft选2048hop_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阶段。从一开始就让机修人员参与进来出现一根坏辊就补一条标注数据让模型跟着现场一起成长这件事才能越做越顺。这也是我认为比任何代码技巧都更重要的实战心法。