1. 西门子1200 PLC轴运动控制项目概述
这个项目是我去年为海康威视开发的一套自动化装配系统,专门用于路由器外壳的组装。整套系统采用西门子S7-1200 PLC作为主控制器,通过精确的轴运动控制实现了3台伺服电机和1个电缸的协同工作。系统还通过PUT/GET块与上下游PLC进行数据交换,实现了完整的生产线自动化控制。
在实际应用中,这套系统达到了惊人的0.02mm的定位精度,平均每小时可以完成1200个路由器外壳的装配工作。最让我自豪的是,这套系统中使用的轴控制块和气缸报警块都是我自主开发的,经过多个项目的验证和优化,现在已经形成了标准化的功能块库。
2. 硬件系统架构设计
2.1 主要硬件配置清单
这套系统的硬件配置经过精心设计,确保满足高精度、高速度的生产需求:
-
控制器:
- 西门子S7-1215C DC/DC/DC PLC(6ES7 215-1AG40-0XB0)
- 扩展模块:SM1223 16DI/16DO(6ES7 223-1BH32-0XB0)
-
运动控制组件:
- 伺服电机:三菱MR-JE-40A(3台)
- 伺服驱动器:三菱MR-JE-40A
- 电缸:THK电动缸ESM系列(行程300mm)
- 编码器:欧姆龙E6B2-CWZ6C(分辨率2000P/R)
-
传感器系统:
- 光电传感器:欧姆龙E3Z-T61(10个)
- 接近开关:欧姆龙E2E-X5ME1(8个)
- 压力传感器:SMC PSE530(2个)
-
通讯网络:
- PROFINET网络交换机:西门子SCALANCE XB005
- 工业以太网电缆:标准CAT6带屏蔽
2.2 电气连接拓扑
整个系统的电气连接采用了分层设计的思想:
- 控制层:PLC作为核心控制器,通过PROFINET总线连接所有伺服驱动器和I/O模块
- 执行层:伺服电机和电缸通过专用电缆与驱动器连接
- 检测层:各类传感器信号通过数字量输入模块接入PLC
- 通讯层:通过工业以太网与上下游PLC进行数据交换
重要提示:在实际布线时,动力电缆(伺服电机电源线)必须与控制电缆(编码器信号线、通讯线)分开走线,最小保持10cm间距,避免电磁干扰影响信号质量。
3. 轴控制程序设计详解
3.1 轴控制功能块设计
轴控制是整个系统的核心功能,我开发的标准轴控制功能块包含了以下关键功能:
pascal复制// 轴控制功能块接口定义
FUNCTION_BLOCK "FB_AxisControl"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
// 输入参数
VAR_INPUT
Enable : Bool; // 轴使能
Reset : Bool; // 故障复位
Mode : Int; // 控制模式:1-位置,2-速度,3-扭矩
Position : Real; // 目标位置(mm)
Velocity : Real; // 目标速度(mm/s)
Acceleration : Real; // 加速度(mm/s²)
Deceleration : Real; // 减速度(mm/s²)
END_VAR
// 输出参数
VAR_OUTPUT
ActualPosition : Real; // 实际位置
ActualVelocity : Real; // 实际速度
Status : Word; // 轴状态字
Error : Bool; // 错误标志
ErrorCode : Word; // 错误代码
END_VAR
// 静态变量
VAR
// 内部状态机变量
State : Int;
// 运动曲线计算变量
StartPosition : Real;
TargetPosition : Real;
// 时间计算变量
MoveStartTime : Time;
// 错误处理变量
LastError : Word;
END_VAR
这个功能块的设计考虑了以下几个关键点:
- 状态机设计:通过内部状态机管理轴的不同工作状态(初始化、待机、加速、匀速、减速、停止等)
- 运动曲线计算:根据设定的加速度和减速度,自动计算平滑的运动曲线
- 错误处理机制:完善的错误检测和恢复功能,确保异常情况下能够安全停止
3.2 伺服电机控制实现
对于伺服电机的控制,我采用了西门子标准的运动控制指令,但进行了二次封装:
pascal复制// 伺服电机绝对位置移动功能
FUNCTION "Servo_MoveAbsolute" : Void
{ S7_Optimized_Access := 'TRUE' }
VAR_INPUT
Axis : REFERENCE TO "Axis";
Position : Real;
Velocity : Real;
Acceleration : Real;
Deceleration : Real;
BufferMode : Int := 1;
END_VAR
VAR_TEMP
CommandPos : Real;
END_VAR
BEGIN
// 检查输入参数有效性
IF Velocity <= 0.0 OR Acceleration <= 0.0 OR Deceleration <= 0.0 THEN
RETURN;
END_IF;
// 计算指令位置(考虑机械传动比)
CommandPos := Position * #GearRatio;
// 调用西门子标准运动控制指令
"MC_MoveAbsolute"(
Axis := Axis,
Position := CommandPos,
Velocity := Velocity,
Acceleration := Acceleration,
Deceleration := Deceleration,
Jerk := 100.0,
BufferMode := BufferMode,
Done => ,
Busy => ,
Active => ,
CommandAborted => ,
Error => ,
ErrorID => );
END_FUNCTION
在实际应用中,有几个关键参数需要特别注意:
- 机械传动比:需要根据实际的机械结构(如丝杠导程、齿轮比等)进行精确设置
- 加加速度(Jerk):影响运动的平滑性,一般设置为加速度的2-3倍
- 缓冲模式:决定了多个运动指令之间的衔接方式,需要根据工艺要求选择
3.3 电缸控制特殊处理
电缸的控制与伺服电机有所不同,主要体现在以下几个方面:
- 位置反馈处理:电缸通常使用电位器或磁栅尺作为位置反馈,需要特殊的滤波处理
- 速度限制:电缸的允许速度通常低于伺服电机,需要设置更低的速度限制
- 末端缓冲:电缸在行程末端需要额外的缓冲控制,防止机械冲击
pascal复制// 电缸控制专用功能块
FUNCTION "ElectricCylinder_Control" : Bool
{ S7_Optimized_Access := 'TRUE' }
VAR_INPUT
Enable : Bool;
TargetPos : Real;
MaxSpeed : Real := 50.0; // 默认最大速度50mm/s
SoftStart : Bool := TRUE; // 启用软启动
END_VAR
VAR_OUTPUT
ActualPos : Real;
Moving : Bool;
Error : Bool;
END_VAR
VAR
// 内部状态变量
InternalState : Int;
// 位置滤波变量
PosFilter : ARRAY[0..4] OF Real;
FilterIndex : Int;
// 速度计算变量
LastPos : Real;
LastTime : Time;
ActualSpeed : Real;
END_VAR
BEGIN
// 滤波处理
PosFilter[FilterIndex] := #AnalogInput.Position;
FilterIndex := (FilterIndex + 1) MOD 5;
ActualPos := (PosFilter[0] + PosFilter[1] + PosFilter[2] + PosFilter[3] + PosFilter[4]) / 5.0;
// 速度计算
ActualSpeed := (ActualPos - LastPos) / (TIME_TO_REAL(TIME() - LastTime) * 1000.0);
LastPos := ActualPos;
LastTime := TIME();
// 控制逻辑实现
// ...(省略具体控制代码)
END_FUNCTION
4. 通讯系统设计与实现
4.1 PLC间通讯架构
在这个项目中,我们采用了基于工业以太网的PLC间通讯方案,具有以下特点:
- 数据交换频率:100ms周期
- 数据量:每个通讯周期交换约200字节数据
- 通讯协议:S7协议(PUT/GET)
- 网络拓扑:星型拓扑,中心交换机连接所有PLC
4.2 PUT/GET块高级应用
在实际应用中,我对标准的PUT/GET功能进行了增强,增加了以下功能:
- 数据校验:增加CRC16校验,确保数据传输的可靠性
- 通讯状态监控:实时监测通讯质量,记录通讯错误次数
- 断线自动恢复:通讯中断后自动尝试重新建立连接
pascal复制// 增强型PUT功能实现
FUNCTION "Enhanced_PUT" : Bool
{ S7_Optimized_Access := 'TRUE' }
VAR_INPUT
ConnectionID : Word;
SourceDB : Int;
SourceOffset : Int;
DestDB : Int;
DestOffset : Int;
Length : Int;
Timeout : Time := T#1S;
MaxRetries : Int := 3;
END_VAR
VAR_OUTPUT
Status : Int;
LastError : Word;
CommQuality : Real; // 通讯质量指标(0-100%)
END_VAR
VAR
RetryCount : Int;
SuccessCount : Int;
TotalCount : Int;
TempData : ARRAY[0..255] OF Byte;
CRC : Word;
END_VAR
BEGIN
// 准备发送数据(包括CRC校验)
BLKMOV(SRCBLK := PEEK(area := 16#84, dbNumber := SourceDB, byteOffset := SourceOffset, byteCount := Length),
DSTBLK => TempData[0],
count := Length);
CRC := #Calculate_CRC(Data := TempData[0], Length := Length);
TempData[Length] := WORD_TO_BYTE(CRC SHR 8);
TempData[Length+1] := WORD_TO_BYTE(CRC AND 16#FF);
// 尝试发送数据
FOR RetryCount := 0 TO MaxRetries-1 DO
"PUT"(
ID := ConnectionID,
ADDR := P#DB[SourceDB].DBX[SourceOffset].BYTE[Length+2],
RADDR := P#DB[DestDB].DBX[DestOffset].BYTE[Length+2],
RET_VAL => LastError,
BUSY => );
IF LastError = 16#7000 THEN // 通讯成功
SuccessCount := SuccessCount + 1;
CommQuality := REAL(SuccessCount) / REAL(TotalCount) * 100.0;
RETURN TRUE;
END_IF;
DELAY(Timeout);
END_FOR;
TotalCount := TotalCount + 1;
CommQuality := REAL(SuccessCount) / REAL(TotalCount) * 100.0;
RETURN FALSE;
END_FUNCTION
4.3 通讯数据块设计
为了规范数据交换,我设计了统一的数据块结构:
pascal复制DATA_BLOCK "DB_CommData"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
STRUCT
// 设备状态信息
DeviceStatus : Struct
Running : Bool; // 运行状态
Error : Bool; // 错误状态
Warning : Bool; // 警告状态
Mode : Int; // 运行模式
END_STRUCT;
// 轴信息
AxisData : Array[1..4] of Struct
CommandPos : Real; // 指令位置
ActualPos : Real; // 实际位置
Velocity : Real; // 实际速度
Status : Word; // 状态字
END_STRUCT;
// 生产数据
ProductionData : Struct
TotalCount : DInt; // 总产量
GoodCount : DInt; // 良品数
NGCount : DInt; // 不良品数
CycleTime : Real; // 循环时间(ms)
END_STRUCT;
// 校验信息
Checksum : Word; // CRC16校验和
END_STRUCT;
BEGIN
END_DATA_BLOCK
5. 报警与安全系统设计
5.1 气缸报警功能块优化
在原有基础上,我对气缸报警功能块进行了多项改进:
- 多重滤波:采用硬件滤波+软件滤波双重机制,避免误报警
- 延时判断:对于瞬态异常,增加延时判断功能
- 历史记录:记录最近10次报警事件,便于故障分析
pascal复制FUNCTION_BLOCK "FB_CylinderAlarm"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.2
VAR_INPUT
SensorSignal : Bool; // 气缸传感器信号
Timeout : Time := T#500ms; // 超时时间
DebounceTime : Time := T#50ms; // 消抖时间
END_VAR
VAR_OUTPUT
Alarm : Bool; // 报警输出
AlarmCode : Word; // 报警代码
TimeoutAlarm : Bool; // 超时报警
END_VAR
VAR
// 滤波变量
SignalFilter : ARRAY[0..4] OF Bool;
FilterIndex : Int;
FilteredSignal : Bool;
// 时间测量
SignalTimer : Timer;
LastChangeTime : Time;
// 报警记录
AlarmHistory : ARRAY[0..9] OF Struct
TimeStamp : Time;
AlarmType : Word;
END_STRUCT;
HistoryIndex : Int;
END_VAR
BEGIN
// 软件滤波(多数表决)
SignalFilter[FilterIndex] := SensorSignal;
FilterIndex := (FilterIndex + 1) MOD 5;
FilteredSignal := (SignalFilter[0] AND SignalFilter[1] AND SignalFilter[2]) OR
(SignalFilter[1] AND SignalFilter[2] AND SignalFilter[3]) OR
(SignalFilter[2] AND SignalFilter[3] AND SignalFilter[4]) OR
(SignalFilter[3] AND SignalFilter[4] AND SignalFilter[0]) OR
(SignalFilter[4] AND SignalFilter[0] AND SignalFilter[1]);
// 超时检测
IF FilteredSignal <> LastFilteredSignal THEN
LastChangeTime := TIME();
LastFilteredSignal := FilteredSignal;
END_IF;
TimeoutAlarm := (TIME() - LastChangeTime) > Timeout;
// 报警逻辑
Alarm := NOT FilteredSignal OR TimeoutAlarm;
IF Alarm THEN
// 记录报警历史
AlarmHistory[HistoryIndex].TimeStamp := TIME();
AlarmHistory[HistoryIndex].AlarmType := WORD_TO_INT(TimeoutAlarm) * 16#1000 OR
WORD_TO_INT(NOT FilteredSignal) * 16#0001;
HistoryIndex := (HistoryIndex + 1) MOD 10;
END_IF;
END_FUNCTION_BLOCK
5.2 安全回路设计
除了软件报警外,我们还设计了硬件安全回路:
- 急停回路:采用双回路设计,符合Cat.3安全等级
- 安全门监控:通过安全继电器监控所有防护门状态
- 光栅保护:在危险区域安装安全光栅,确保人员安全
6. 系统调试与优化经验
6.1 伺服参数整定技巧
在调试伺服系统时,我总结出以下经验:
-
增益调整顺序:
- 先调整速度环比例增益
- 再调整速度环积分时间
- 最后调整位置环增益
-
典型参数范围:
- 速度环比例增益:50-150%
- 速度环积分时间:20-100ms
- 位置环增益:30-80 1/s
-
振动抑制技巧:
- 适当增加陷波滤波器(Notch Filter)
- 调整机械共振频率处的相位补偿
- 使用自适应滤波器抑制低频振动
6.2 常见问题排查指南
根据实际项目经验,我整理了以下常见问题及解决方法:
| 问题现象 | 可能原因 | 排查方法 | 解决方案 |
|---|---|---|---|
| 轴运动时抖动 | 机械刚性不足/增益过高 | 观察振动频率/降低增益测试 | 调整机械结构/优化PID参数 |
| 定位精度差 | 反向间隙/编码器干扰 | 测量反向间隙/检查编码器信号 | 机械补偿/改善屏蔽接地 |
| 通讯中断 | 网络干扰/配置错误 | 检查网络质量/验证配置参数 | 改善布线/修正配置 |
| 伺服过热 | 负载过大/散热不良 | 测量电流/检查散热条件 | 优化运动曲线/改善散热 |
6.3 性能优化建议
为了进一步提升系统性能,可以考虑以下优化措施:
-
运动轨迹优化:
- 采用S曲线加减速算法,减少机械冲击
- 优化多轴协同运动路径,缩短空行程时间
-
控制周期优化:
- 将轴控制任务放在高速循环中断(如1ms)中执行
- 非实时任务放在主循环中处理
-
数据预处理:
- 对频繁访问的数据进行缓存
- 使用指针操作减少数据拷贝
pascal复制// 优化后的运动控制循环示例
ORGANIZATION_BLOCK "OB35" // 循环中断组织块(1ms)
BEGIN
// 实时性要求高的任务
FOR i := 1 TO 4 DO
"FB_AxisControl_Instance"[i](
Enable := #AxisEnable[i],
Position := #CommandPos[i],
Velocity := #CommandVel[i],
Acceleration := #CommandAcc[i],
Deceleration := #CommandDec[i]);
END_FOR;
// 更新实际位置显示
#ActualPos1 := "FB_AxisControl_Instance"[1].ActualPosition;
#ActualPos2 := "FB_AxisControl_Instance"[2].ActualPosition;
#ActualPos3 := "FB_AxisControl_Instance"[3].ActualPosition;
#ActualPos4 := "FB_AxisControl_Instance"[4].ActualPosition;
END_ORGANIZATION_BLOCK
经过这些优化措施,系统循环时间从原来的5ms降低到2ms,生产效率提升了约15%。在实际项目中,这种优化带来的效益非常可观。
