2024年3月,山东东营一家地方炼化厂的设备科长给我打了一个电话。电话那头声音很急:"我们一台加氢进料泵上周抱轴了,停了两天,直接损失小两百万。你们那个预测性维护到底靠不靠谱?"
两周后我站在这家炼化厂的催化裂化装置区,看着密密麻麻的管道和轰鸣的机组,说实话心里有点发怵。石化行业搞预测性维护和普通工厂完全不是一个难度级别------防爆要求、介质腐蚀、高温高压、连续生产不允许停机。但反过来想,正因为后果严重,预测的价值才大。
这个项目最终落地了我们团队前后花了八个月。今天把核心内容拆开讲讲------泵和压缩机这两类最核心的转动设备到底怎么搞状态监测。
先搞清楚:石化厂里什么设备最值得监测
不是所有设备都值得上状态监测系统。我们做的第一件事就是拿着工厂近三年的维修记录做了一轮"设备关键度评估"。
说个很有意思的数据:这家厂三年内记录了147次非计划停机,其中离心泵占了68次(46%),往复式压缩机占了41次(28%),两项加起来就占到了将近四分之三。而泵里面又数高温油泵(加氢进料泵、常压塔底泵)和锅炉给水泵故障率最高。
于是我们定了范围:先做12台关键离心泵 + 4台往复式压缩机的状态监测。不是不想全覆盖,是预算和人力都有限,精准打击比广撒网靠谱得多。
传感器部署:在防爆区干活处处是坑
石化厂的传感器选型和部署,和普通工厂有几个根本性区别。
首先,所有在线传感器必须带本安防爆认证(Ex ia 或 Ex d)。我们选了 PCB 的 EX600 系列加速度传感器,量程±50g,频响0.5Hz-10kHz,一根传感器不含电缆就得三千多块。12台泵每台装4个测点(驱动端径向、驱动端轴向、非驱动端径向、泵体轴向),再加上4台压缩机每台6个测点(多了十字头振动和缸体冲击),一共72个测点------光传感器就花了二十多万。
其次,布线是个噩梦。炼化装置区到处都是高温管线,电缆不能贴着管壁走,得穿镀锌钢管从桥架绕。我们一个施工队干了整整两周才把72路信号全部接到现场采集箱。
采集箱我们用了 NI 的 cDAQ-9189 以太网机箱 + NI-9234 动态信号采集模块,每通道同步采样,采样率设的 2560Hz。为什么是2560?因为我们关注的轴承故障特征频率最高在 1000Hz 左右,按奈奎斯特定理至少 2000Hz,留点余量取 2560------这是踩了坑才确定的。之前一个项目设了 800Hz,结果轴承滚动体故障频率刚好在 400Hz 附近,连二倍频都采不全。
# 验证采样率是否够用的一段检查脚本
import numpy as np
# 轴承参数:SKF 6314 深沟球轴承
bearing_params = {
'ball_diameter': 20.64, # mm
'pitch_diameter': 97.5, # mm
'n_balls': 8,
'contact_angle': 0 # 度
}
def calc_fault_frequencies(rpm, params):
"""
计算轴承四种故障特征频率
返回:BPFO, BPFI, BSF, FTF
"""
fr = rpm / 60 # 转频
d = params['ball_diameter']
D = params['pitch_diameter']
n = params['n_balls']
theta = np.radians(params['contact_angle'])
BPFO = (n * fr / 2) * (1 - (d / D) * np.cos(theta))
BPFI = (n * fr / 2) * (1 + (d / D) * np.cos(theta))
BSF = (D * fr / (2 * d)) * (1 - (d / D * np.cos(theta))**2)
FTF = (fr / 2) * (1 - (d / D) * np.cos(theta))
return BPFO, BPFI, BSF, FTF
# 泵额定转速 2980 RPM
bpfo, bpfi, bsf, ftf = calc_fault_frequencies(2980, bearing_params)
max_freq = max(bpfo, bpfi, bsf)
print(f"最高故障频率: {max_freq:.1f} Hz")
print(f"所需最低采样率: {max_freq * 2.56:.0f} Hz (按2.56倍)")
# 输出:最高故障频率 ≈ 345 Hz,最低采样率 884 Hz
# 2560 Hz 足够,且有冗余做包络分析
离心泵的状态监测:振动+温度就够了,但特征要算对
离心泵的失效模式非常集中:轴承损坏、密封泄漏、叶轮磨损/气蚀、不对中。这四种占了我们统计的87%的故障。
有意思的是,不同故障在振动信号里的"特征指纹"完全不一样: - 轴承损伤 → 高频冲击,在包络谱里出现特征频率及其谐波 - 不对中 → 1倍频和2倍频的振动幅值明显升高,轴向振动尤其突出 - 叶轮磨损/气蚀 → 宽频带噪声底抬升,0.5倍频附近出现亚谐波 - 密封泄漏 → 温度趋势缓慢上升(缓慢很重要,突然升高一般是轴承要挂了)
所以我们设计的特征提取pipeline是这样的:
import scipy.signal as signal
from scipy.fft import fft
import numpy as np
def extract_pump_features(raw_signal, fs=2560):
"""
从2秒振动数据窗口提取离心泵监测特征
raw_signal: 1D numpy array, 5120个点(2秒@2560Hz)
"""
features = {}
# ---- 时域特征 ----
features['rms'] = np.sqrt(np.mean(raw_signal**2))
features['peak'] = np.max(np.abs(raw_signal))
features['crest_factor'] = features['peak'] / (features['rms'] + 1e-8)
features['kurtosis'] = np.mean((raw_signal - np.mean(raw_signal))**4) / \
(np.std(raw_signal)**4 + 1e-8)
# ---- 频域特征 ----
n = len(raw_signal)
fft_vals = np.abs(fft(raw_signal))[:n//2]
freqs = np.fft.fftfreq(n, 1/fs)[:n//2]
# 1倍频能量(泵转频≈49.7Hz)
rpm_freq = 49.7
idx_1x = np.argmin(np.abs(freqs - rpm_freq))
idx_2x = np.argmin(np.abs(freqs - 2*rpm_freq))
features['energy_1x'] = fft_vals[idx_1x]
features['energy_2x'] = fft_vals[idx_2x]
# 高频带能量(2kHz-5kHz,捕捉轴承早期损伤)
hf_mask = (freqs > 2000) & (freqs < 5000)
features['hf_energy'] = np.sum(fft_vals[hf_mask])
# ---- 包络谱特征(用于轴承诊断) ----
analytic = signal.hilbert(raw_signal)
envelope = np.abs(analytic)
env_fft = np.abs(fft(envelope))[:n//2]
# BPFO ≈ 155Hz 附近的能量
bpfo_mask = (freqs > 140) & (freqs < 170)
features['bpfo_energy'] = np.sum(env_fft[bpfo_mask])
return features
这个pipeline上线后第二周就抓到一个有意思的案例:一台常压塔底泵的峭度值突然从3.2跳到了6.8,但RMS值几乎没变。我们马上安排内窥镜检查,发现轴承内圈已经出现了一个1.5mm左右的剥落坑。峭度对冲击敏感、RMS对冲击不敏感------这个特性救了这台泵一命。
往复式压缩机:和离心泵完全不同的打法
说完了泵,聊压缩机。往复式压缩机的监测逻辑和离心泵完全不同------泵是旋转机械,看频谱就行;压缩机是往复机械,冲击信号和循环载荷混在一起,频谱图上一团乱麻。
我们监测的4台压缩机是沈阳远大做的,型式为 4M 型四列对称平衡式,处理量 12000 Nm³/h,排气压力 3.5MPa。这类压缩机的核心风险点是:十字头磨损、气阀泄漏、活塞杆断裂(这个最吓人)。
十字头磨损的监测,我们没有用传统的振动方法------振动在这个位置噪声太大了。取而代之的是在十字头滑道处装了一个电涡流位移传感器,直接测十字头的下沉量。正常工况下沉量在0.05mm以内波动,一旦超过0.12mm,基本可以确定滑道巴氏合金层已经磨穿。
气阀泄漏的监测更有意思。气阀泄漏时,阀盖温度会出现异常分布------泄漏阀的温度会比正常阀高8-15°C。我们在每个气阀盖上贴了磁吸式热电偶,12个气阀 × 4台机 = 48个温度点,每5秒采集一次。然后用了一个很土但很管用的算法:
def detect_valve_leak(temps_12valves, baseline, threshold=8.0):
"""
temps_12valves: 12个气阀的当前温度
baseline: 12个气阀的历史正常温度均值
判断逻辑:如果某个阀的温度偏离集体中位数超过阈值→可疑
"""
median_temp = np.median(temps_12valves)
deviations = temps_12valves - baseline
suspect = []
for i, dev in enumerate(deviations):
if dev > threshold and temps_12valves[i] - median_temp > 5:
suspect.append(i + 1) # 阀号从1开始
return suspect
# 实际运行时,连续3次报警才触发工单,避免短时波动误报
你可能会问,为什么不用更高级的方法?说实话,这个场景下温度偏差模式太明显了,不需要上机器学习。好的工程师不是会用多复杂的算法,而是知道什么场景用什么方法最合适。
整个系统的数据流和报警逻辑
说了这么多传感器和算法,得串起来看看整个系统的数据流。
现场72路振动信号进 NI cDAQ 采集箱 → 千兆以太网进边缘计算网关(我们用的研华 MIC-770,i7-10700,32G内存)→ 网关本地做特征提取(每2秒一个窗口)→ 特征数据通过 MQTT 5.0 协议发到中控室的 InfluxDB 2.7 时序库 → Grafana 10.2 做可视化仪表盘。
为什么不在云端做计算?两个原因:一是石化厂内网对数据外传管控极严,能不出厂就不出厂;二是2560Hz × 72通道的原始数据量太大,全传云端带宽不够。
报警逻辑上我们做了三层------绿色是"特征异常但未确认",触发后自动加密采样到5120Hz持续一分钟;黄色是"连续三次确认异常",自动生成巡检工单推送到企业微信;红色是"趋势快速恶化",直接打电话给值班长。这套逻辑上线后误报率控制在了每台设备每周不到1次,在石化行业已经算很不错的了。
写在最后
石化行业的预测性维护确实难做------环境恶劣、防爆要求高、设备种类多、不允许随便停机试验。但这个行业不缺预算和需求,缺的是能真正理解现场、把方案落地的团队。
如果你也在做类似的项目,我建议你记住三点:第一,做好设备分级 ,不值得监测的设备别硬上;第二,传感器位置比传感器数量更重要,一个装错位置的传感器不如不装;第三,不要把简单问题复杂化------该用阈值的地方就别上AI。
这个项目跑了一年多,12台泵和4台压缩机的非计划停机降了大约65%,维修费用省了80多万。下次有机会再聊聊石化行业的旋转机械------汽轮机和离心压缩机,那是另一个难度级别了。