简介:这份资源是一份面向工业自动化、电气控制方向学生与技术人员的PLC电机故障诊断系统设计方案文档,围绕电机运行中相间短路、断相、低电压、单相接地、过负荷、过电流等典型故障,给出基于西门子S7-200、S7-300、S7-400系列PLC的诊断与保护设计思路,适合课程设计、毕业设计及工程入门参考。压缩包内共1个doc文件,约211KB,内容涵盖PLC工作原理与选型依据、I/O接口分配、系统梯形图编写,以及开机检测断路器状态、启动过程循环检测故障、关机跳闸与声光报警复位等完整控制逻辑,并附有摘要、关键词与目录结构,便于按章节查阅。目前已有64人学习,可作为理解PLC在电机故障诊断中应用方式的实用参考资料。
1. 从一份 .doc 方案说起:PLC 电机故障诊断到底在做什么
很多做电气自动化的朋友第一次拿到“PLC电机故障诊断系统设计方案.doc”这类文档时,第一反应是:这不就是给电机加几个传感器、在 PLC 里写几段报警程序吗?真到现场才发现,事情没这么简单。电机故障诊断的核心,不是“报警”,而是“在故障还没把产线停掉之前,把特征量从噪声里抠出来,再让 PLC 做出可复现的判断”。它解决的是非计划停机、误报频繁、维修靠老师傅耳朵听这三件事,适合做设备维护、产线改造、工控集成的从业者。
这份方案文档通常包含系统架构、信号采集、诊断算法、PLC 程序结构和上位机交互几块。但文档是死的,落地是活的。下面我按“先立住原理,再动手复现”的顺序,把这类方案从纸面拆到能跑的程度。中间会给出可抄的代码、参数表和踩坑记录,最后收在一个具体技巧上。
2. 先定架构再写代码:信号链与 PLC 选型怎么定
2.1 电机故障诊断的信号从哪来
电机故障大致分三类:电气类(匝间短路、断相、三相不平衡)、机械类(轴承磨损、偏心、松动)、负载类(过载、堵转)。不同故障对应不同特征量,采集方案也不同。
常见做法是:电流信号用霍尔电流传感器或电流互感器,取三相电流;振动信号用压电式加速度计,装在轴承座或机壳;温度用 PT100 或热电偶,埋在绕组或轴承附近。转速可以用编码器或接近开关。
这里有个选型原则:先确定要诊断哪几类故障,再决定采什么信号。如果只做电气故障,三相电流加电压就够了;如果要做轴承早期故障,振动信号是必须的,而且采样率要够。很多方案文档里写“采集电流、振动、温度”,但没写采样率和带宽,落地时就会发现振动信号混叠,诊断算法根本跑不出结果。
我一般会按这个顺序定信号链:
- 列出目标故障类型;
- 查每类故障的特征频率范围;
- 反推传感器带宽和采样率;
- 确认 PLC 或采集模块能不能接这类信号。
比如轴承故障特征频率通常在几百赫兹到几千赫兹,按奈奎斯特采样定理,采样率至少要到 10 kHz 以上。普通 PLC 的模拟量输入模块扫描周期在毫秒级,根本抓不住。这时候要么加独立振动采集模块,要么用带高速计数/高速采集的 PLC 或专用诊断仪。
2.2 PLC 选型:不是越贵越好,而是看诊断任务放在哪
PLC 在故障诊断系统里通常承担三个角色:数据采集触发、逻辑判断与联锁、与上位机通信。诊断算法可以放在 PLC 里,也可以放在上位机或边缘控制器里。
如果算法简单,比如只做阈值判断、三相不平衡度计算、启动电流超限,那普通中型 PLC 就够了,用梯形图或 SCL 写逻辑。如果要做 FFT、包络解调、特征频率提取,PLC 算力通常不够,常见做法是 PLC 只负责采集和转发,算法在上位机或边缘计算盒子里跑。
选型时重点看这几个参数:
| 项目 | 要求 | 说明 |
|---|---|---|
| 模拟量输入通道 | 至少 3 路电流 + 1 路振动 + 1 路温度 | 按实际故障类型增减 |
| 模拟量刷新周期 | ≤ 1 ms(电流)/ ≤ 0.1 ms(振动) | 振动需高速采集 |
| 通信接口 | 以太网 + RS485 | 上位机与现场仪表 |
| 程序容量 | 留 30% 余量 | 诊断逻辑会越加越多 |
| 支持语言 | SCL / ST 优先 | 比梯形图更适合算法 |
提示:如果方案文档里写“用普通 PLC 采集振动信号做 FFT”,基本可以判断这份方案没有经过现场验证。振动信号要么走专用采集卡,要么走带高速采集功能的模块。
2.3 一个最小可跑的采集与判断流程
下面用 SCL 写一个三相电流不平衡度计算和过载判断的示例。假设 PLC 已经通过模拟量通道读到三相电流值,存放在Current_A、Current_B、Current_C三个 REAL 变量里,单位是安培。
// 三相电流不平衡度与过载判断 // 输入:Current_A, Current_B, Current_C (REAL, 单位 A) // 输出:Unbalance_Percent (REAL), Overload_Flag (BOOL), Fault_Code (INT) FUNCTION_BLOCK MotorDiag VAR_INPUT Current_A : REAL; // A 相电流 Current_B : REAL; // B 相电流 Current_C : REAL; // C 相电流 Rated_Current : REAL; // 电机额定电流 Unbalance_Threshold : REAL := 10.0; // 不平衡度报警阈值 % Overload_Threshold : REAL := 1.15; // 过载倍数阈值 END_VAR VAR_OUTPUT Unbalance_Percent : REAL; // 不平衡度 Overload_Flag : BOOL; // 过载标志 Fault_Code : INT; // 故障码:0 正常,1 不平衡,2 过载,3 断相 END_VAR VAR Avg_Current : REAL; // 平均电流 Max_Deviation : REAL; // 最大偏差 END_VAR // 计算平均电流 Avg_Current := (Current_A + Current_B + Current_C) / 3.0; // 断相判断:任一相电流接近 0 且其他相有电流 IF (Current_A < 0.1 AND Current_B > 0.5) OR (Current_B < 0.1 AND Current_C > 0.5) OR (Current_C < 0.1 AND Current_A > 0.5) THEN Fault_Code := 3; Overload_Flag := FALSE; Unbalance_Percent := 100.0; RETURN; END_IF; // 计算最大偏差 Max_Deviation := 0.0; IF ABS(Current_A - Avg_Current) > Max_Deviation THEN Max_Deviation := ABS(Current_A - Avg_Current); END_IF; IF ABS(Current_B - Avg_Current) > Max_Deviation THEN Max_Deviation := ABS(Current_B - Avg_Current); END_IF; IF ABS(Current_C - Avg_Current) > Max_Deviation THEN Max_Deviation := ABS(Current_C - Avg_Current); END_IF; // 不平衡度 = 最大偏差 / 平均电流 * 100% IF Avg_Current > 0.1 THEN Unbalance_Percent := (Max_Deviation / Avg_Current) * 100.0; ELSE Unbalance_Percent := 0.0; END_IF; // 过载判断 IF Avg_Current > (Rated_Current * Overload_Threshold) THEN Overload_Flag := TRUE; Fault_Code := 2; ELSIF Unbalance_Percent > Unbalance_Threshold THEN Overload_Flag := FALSE; Fault_Code := 1; ELSE Overload_Flag := FALSE; Fault_Code := 0; END_IF; END_FUNCTION_BLOCK这段逻辑说明:先算平均电流,再做断相判断,然后算不平衡度,最后做过载判断。参数说明:Unbalance_Threshold默认 10%,这是常见工业电机的报警线,实际可按电机类型调整;Overload_Threshold默认 1.15 倍额定电流,对应一般电机的短时过载能力。Fault_Code可以直接送 HMI 或上位机做报警显示。
注意:这段代码假设模拟量已经滤波和标定。如果原始信号抖动大,要在前面加一阶低通滤波,否则不平衡度会频繁跳变。
3. 诊断算法怎么落:从阈值到特征频率的实操路径
3.1 阈值判断能解决多少问题
很多现场故障其实用阈值就能覆盖:过载、断相、三相不平衡、启动超时、温度超限。这类判断逻辑简单、响应快、容易在 PLC 里实现,适合做第一层保护。
但阈值判断的边界很明显:它只能告诉你“现在不正常”,不能告诉你“哪里不正常、还能撑多久”。比如轴承早期磨损,电流和温度可能都还在正常范围,但振动信号里已经出现特征频率。这时候就需要第二层诊断。
我一般把诊断分两层:
- 第一层:PLC 内做阈值和逻辑判断,响应时间毫秒级,负责联锁停机;
- 第二层:上位机或边缘控制器做特征提取和模式识别,响应时间秒级,负责预警和维修建议。
3.2 用 Python 做振动信号的包络谱分析
轴承故障的特征频率计算需要知道轴承型号和转速。假设已知内圈故障特征频率 BPFI、外圈故障特征频率 BPFO、滚动体故障特征频率 BSF,可以通过包络谱找这些频率成分。
下面是一个用 Python 做包络谱分析的最小示例。假设已经采集到一段振动信号,采样率fs,数据存在vibration_data数组里。
import numpy as np from scipy.signal import hilbert, butter, filtfilt from scipy.fft import fft, fftfreq def envelope_spectrum(vibration_data, fs, band_low=500, band_high=5000): """ 对振动信号做包络谱分析 :param vibration_data: 一维振动信号数组 :param fs: 采样率 Hz :param band_low: 带通滤波下限 Hz :param band_high: 带通滤波上限 Hz :return: 频率轴, 包络谱幅值 """ # 1. 带通滤波,保留轴承故障激发的频带 nyq = fs / 2.0 low = band_low / nyq high = band_high / nyq b, a = butter(4, [low, high], btype='band') filtered = filtfilt(b, a, vibration_data) # 2. 希尔伯特变换求包络 analytic_signal = hilbert(filtered) envelope = np.abs(analytic_signal) # 3. 对包络做 FFT n = len(envelope) envelope_spectrum = np.abs(fft(envelope - np.mean(envelope))) / n freq = fftfreq(n, 1/fs) # 只取正频率部分 positive_mask = freq > 0 return freq[positive_mask], envelope_spectrum[positive_mask] # 使用示例 # fs = 20000 # 采样率 20 kHz # data = np.loadtxt('vibration.csv') # 假设一列振动数据 # freq, amp = envelope_spectrum(data, fs) # 然后检查 BPFI、BPFO、BSF 附近是否有明显峰值逻辑说明:先带通滤波,把轴承故障激发的频带保留下来;再用希尔伯特变换求包络;最后对包络做 FFT,得到包络谱。参数说明:band_low和band_high要根据轴承故障特征频率所在频带调整,常见范围是 500 Hz 到 5 kHz;butter的阶数 4 是经验值,太高会不稳定,太低滤波效果差。
这段代码跑完后,如果包络谱在 BPFI 或 BPFO 附近出现明显峰值,就可以判断对应轴承部件有早期故障。注意:实际使用时要先做转速归一化,否则特征频率会随转速漂移。
3.3 把诊断结果写回 PLC 的通信方式
上位机算出诊断结果后,需要写回 PLC 做联锁或显示。常见方式有三种:
| 方式 | 适用场景 | 注意点 |
|---|---|---|
| Modbus TCP | 中小型系统,数据量小 | 寄存器地址要规划好 |
| OPC UA | 多品牌设备,需要语义化 | 配置较复杂,但扩展性好 |
| 私有协议 | 特定品牌 PLC | 依赖厂家文档,移植性差 |
我一般优先选 Modbus TCP,因为大部分 PLC 都支持,调试工具也多。下面是一个用 Python 通过 Modbus TCP 写诊断结果的示例。
from pymodbus.client import ModbusTcpClient def write_diagnosis_result(plc_ip, plc_port, fault_code, unbalance_percent): """ 将诊断结果写入 PLC 保持寄存器 :param plc_ip: PLC IP 地址 :param plc_port: Modbus TCP 端口,默认 502 :param fault_code: 故障码 :param unbalance_percent: 不平衡度,放大 10 倍后写入 """ client = ModbusTcpClient(plc_ip, port=plc_port) client.connect() # 假设故障码写入 40001,不平衡度写入 40002 # 注意:不同 PLC 寄存器地址偏移不同,需按实际调整 client.write_register(0, fault_code) client.write_register(1, int(unbalance_percent * 10)) client.close() # 使用示例 # write_diagnosis_result('192.168.1.10', 502, 1, 12.5)逻辑说明:write_register的第一个参数是寄存器偏移地址,不同 PLC 的映射不同,有的从 0 开始,有的从 1 开始,有的需要加 40001 偏移。参数说明:不平衡度放大 10 倍写入是为了保留一位小数,PLC 里再除以 10 还原。注意:写之前要确认 PLC 的 Modbus 从站已经启用,寄存器地址没有和系统占用冲突。
4. 避坑与排查:这类方案落地时最容易翻车的 5 个点
4.1 振动信号混叠:现象是频谱一片模糊,原因是没有抗混叠滤波
现象:采集到的振动信号做 FFT 后,频谱上出现很多不存在的频率成分,特征频率完全找不到。原因:采样率不够,或者没有加抗混叠滤波器,高频成分折叠到低频。解决:采样率至少是目标最高频率的 2.5 倍,最好 5 倍以上;在 ADC 前加硬件抗混叠滤波器,截止频率设为采样率的一半以下。
4.2 电流互感器选型偏大:现象是小电流时不平衡度乱跳
现象:电机轻载时,三相电流不平衡度频繁报警,但实际电流很小。原因:电流互感器量程选得太大,轻载时输出信号很小,信噪比差。解决:按电机额定电流的 1.2 到 1.5 倍选互感器量程,不要按最大短路电流选。如果已经装大了,可以在 PLC 里做零点校准和数字滤波。
4.3 PLC 扫描周期与诊断周期不匹配:现象是报警延迟或漏报
现象:电机已经过载了,但 PLC 过了好几秒才报警。原因:诊断逻辑放在慢速任务里,或者模拟量刷新周期太长。解决:把诊断逻辑放在高速任务或中断里,模拟量模块选刷新周期短的型号。如果做不到,至少要把过载判断放在 10 ms 以内的任务里。
4.4 特征频率算错:现象是包络谱峰值对不上
现象:按公式算出的 BPFI、BPFO 和包络谱峰值总是差一点。原因:转速测量不准,或者轴承型号查错,或者滑差没有考虑。解决:用编码器实测转速,不要用额定转速代替;查轴承手册确认特征频率系数;如果电机有滑差,按实际转速修正。
4.5 通信寄存器地址冲突:现象是写进去的数据读出来不对
现象:上位机写故障码到 PLC,HMI 上显示的值和写入值不一致。原因:Modbus 寄存器地址偏移搞错,或者和系统其他变量重叠。解决:先读一遍 PLC 的寄存器映射表,确认地址范围;写之前先读一次,确认没有其他程序在写同一地址;用调试工具单独测试读写。
5. 一个具体技巧:用趋势数据做早期预警而不是等报警
阈值报警是“已经坏了才报”,趋势预警是“快坏了就提醒”。我一般会在上位机里对每个特征量做滑动平均和斜率计算,当斜率超过设定值时提前预警。
具体做法:对不平衡度、振动包络谱峰值、温度这三个量,各存最近 30 天的日均值。用线性回归算斜率,如果连续 3 天斜率超过阈值,就发预警。这样可以在故障真正触发报警前几周就安排检修。
下面是一个计算趋势斜率的 Python 示例。
import numpy as np def trend_slope(daily_values): """ 计算日均值序列的线性回归斜率 :param daily_values: 最近 N 天的日均值列表 :return: 斜率,正值表示上升趋势 """ n = len(daily_values) if n < 3: return 0.0 x = np.arange(n) y = np.array(daily_values) # 最小二乘拟合 slope = np.polyfit(x, y, 1)[0] return slope # 使用示例 # values = [10.2, 10.5, 10.8, 11.1, 11.6, 12.0, 12.5] # slope = trend_slope(values) # if slope > 0.3: # 每天上升超过 0.3 个单位 # print("预警:不平衡度呈上升趋势")逻辑说明:np.polyfit(x, y, 1)做一次多项式拟合,返回斜率和截距。参数说明:斜率阈值要根据实际数据的波动范围定,一般取历史正常波动标准差的 2 到 3 倍。注意:趋势预警不能替代阈值报警,两者要并行运行。
我自己的习惯是:每次做完一个诊断系统,先跑一个月的历史数据回放,看趋势预警会不会误报。如果误报多,就把斜率阈值调大或者加滤波。这个步骤看起来麻烦,但能省掉后面很多现场投诉。希望帮到你。
本文还有配套的精品资源,点击获取