在工业自动化领域,模切机作为包装、印刷行业的核心设备,其控制系统的复杂程度直接决定了生产效率和产品质量。欧姆龙NJ系列PLC凭借强大的EtherCAT总线控制能力和结构化编程特性,成为实现高端模切机控制的理想选择。这个项目实现了12轴伺服同步运动、张力PID控制、自动纠偏等核心功能,是工业自动化领域典型的复杂运动控制案例。
我曾在某包装设备制造企业参与过类似项目,当时面对的最大挑战是如何在300mm/s的线速度下保持±0.1mm的裁切精度。通过这个欧姆龙NJ项目,我们可以学习到如何用结构化文本(ST)语言实现工业级的精密控制方案。下面我将从六个核心模块详细解析这个系统的技术实现。
现代工业设备越来越多地采用EtherCAT总线替代传统的脉冲控制,主要原因有三点:
在本项目中,12个伺服驱动器通过菊花链方式连接,主站使用NJ501-1300控制器。实际布线时要注意:
重要提示:EtherCAT网络配置完成后,务必使用ESI文件导入设备描述,避免手动参数配置错误。
原始代码展示了基本的回零操作,但在实际项目中我们需要考虑更多细节:
st复制// 增强型回零功能块
FUNCTION_BLOCK FB_EnhancedHoming
VAR_INPUT
Axis: AXIS_REF;
HomeMode: INT; // 0=限位开关,1=Z相,2=外部传感器
HomeSpeedFast: REAL := 50.0;
HomeSpeedSlow: REAL := 10.0;
Acceleration: REAL := 100.0;
RetryTimes: INT := 3;
END_VAR
VAR_OUTPUT
Status: INT; // 0=成功,1=超时,2=错误
ActualPos: REAL;
END_VAR
VAR
tTimeout: TON;
nRetry: INT := 0;
END_VAR
// 根据模式配置回零参数
CASE HomeMode OF
0:
Axis.REF_MODE := REF_HOME_LIMIT;
Axis.REF_SPEED_FAST := HomeSpeedFast;
1:
Axis.REF_MODE := REF_HOME_INDEX;
ELSE
Axis.REF_MODE := REF_HOME_EXTERNAL;
END_CASE
// 重试机制
WHILE nRetry < RetryTimes DO
Axis.ENABLE := TRUE;
tTimeout(IN:=TRUE, PT:=T#10S);
IF Axis.STATUS = AXIS_STATE_READY THEN
Status := 0;
ActualPos := Axis.ACTUAL_POSITION;
RETURN;
ELSIF tTimeout.Q THEN
nRetry := nRetry + 1;
Axis.ENABLE := FALSE;
tTimeout(IN:=FALSE);
END_IF
END_WHILE
Status := (nRetry >= RetryTimes) ? 2 : 1;
这个增强版本增加了:
原始点动示例缺少安全保护,实际项目必须加入以下要素:
st复制// 安全型点动控制
IF EmergencyStop THEN
Axis1.ENABLE := FALSE;
ELSIF NOT Axis1Status.HOME_DONE THEN
// 未回零禁止点动
Axis1.ENABLE := FALSE;
ELSIF Button1Pressed AND NOT LimitSwitchFwd THEN
Axis1.VELOCITY := 100;
Axis1.MOVE_MODE := MOVE_JOG;
Axis1.DIRECTION := DIR_POSITIVE;
Axis1.ENABLE := TRUE;
Axis1.ACCELERATION := 500; // 加入加速度控制
END_IF
关键改进点:
原始PID示例是基础公式,实际工业应用需要考虑更多因素:
st复制FUNCTION_BLOCK FB_IndustrialPID
VAR_INPUT
PV: REAL; // 过程量
SP: REAL; // 设定值
Kp: REAL := 1.0;
Ki: REAL := 0.1;
Kd: REAL := 0.01;
Ts: TIME := T#10MS; // 采样周期
OutMin: REAL := 0.0;
OutMax: REAL := 100.0;
ManualMode: BOOL := FALSE;
ManualValue: REAL := 0.0;
END_VAR
VAR_OUTPUT
OUT: REAL;
Error: REAL;
END_VAR
VAR
LastPV: REAL;
Integral: REAL := 0.0;
Derivative: REAL;
tSample: TON;
END_VAR
// 采样周期控制
tSample(IN:=TRUE, PT:=Ts);
IF tSample.Q THEN
tSample(IN:=FALSE);
Error := SP - PV;
// 抗积分饱和
IF NOT (OUT >= OutMax AND Error > 0) AND
NOT (OUT <= OutMin AND Error < 0) THEN
Integral := Integral + Ki * Error * TIME_TO_REAL(Ts)/1000;
END_IF
// 微分项滤波
Derivative := 0.2*Derivative + 0.8*(Kd * (PV - LastPV)/(TIME_TO_REAL(Ts)/1000));
OUT := Kp * Error + Integral - Derivative;
OUT := LIMIT(OutMin, OUT, OutMax);
LastPV := PV;
END_IF
// 手动模式处理
IF ManualMode THEN
OUT := ManualValue;
END_IF
工业级PID的特点:
卷径计算需要考虑材料厚度变化和机械损耗:
st复制// 精确卷径计算
FUNCTION_BLOCK FB_DiameterCalc
VAR_INPUT
MaterialThickness: REAL := 0.1; // 材料厚度(mm)
InitialDiameter: REAL := 100.0; // 初始卷径(mm)
EncoderResolution: REAL := 1000.0; // 编码器线数/转
RollerDiameter: REAL := 50.0; // 导辊直径(mm)
END_VAR
VAR_OUTPUT
CurrentDiameter: REAL;
LengthRemaining: REAL; // 剩余材料长度
END_VAR
VAR
nPulseCount: UDINT;
Circumference: REAL;
END_VAR
// 每转脉冲数计算
Circumference := 3.1415926 * RollerDiameter;
nPulsePerRev := EncoderResolution * Circumference;
// 实时计算
CurrentDiameter := SQRT(InitialDiameter**2 - 4*MaterialThickness*nPulseCount/nPulsePerRev/3.1415926);
LengthRemaining := (InitialDiameter**2 - CurrentDiameter**2)*3.1415926/(4*MaterialThickness);
这个算法通过编码器脉冲计数实现高精度计算,比单纯依靠理论公式更准确。
自动纠偏系统通常采用光电传感器+气动阀的控制方案:
st复制// 纠偏控制逻辑
FUNCTION_BLOCK FB_EdgeGuide
VAR_INPUT
SensorLeft: BOOL;
SensorRight: BOOL;
DeadBand: REAL := 0.5; // 死区(mm)
MaxAdjust: REAL := 10.0; // 最大调整量(mm)
END_VAR
VAR_OUTPUT
ValveLeft: BOOL;
ValveRight: BOOL;
AdjustAmount: REAL;
END_VAR
VAR
ErrorCount: INT;
END_VAR
// 纠偏逻辑
CASE TRUE OF
SensorLeft AND NOT SensorRight:
ValveLeft := TRUE;
ValveRight := FALSE;
AdjustAmount := -MaxAdjust;
ErrorCount := ErrorCount + 1;
SensorRight AND NOT SensorLeft:
ValveLeft := FALSE;
ValveRight := TRUE;
AdjustAmount := MaxAdjust;
ErrorCount := ErrorCount + 1;
ELSE
ValveLeft := FALSE;
ValveRight := FALSE;
AdjustAmount := 0.0;
END_CASE
// 连续错误报警
IF ErrorCount > 100 THEN
// 触发报警处理
AlarmHandler(AlarmID:=101);
END_IF
实际应用中还需要考虑:
原始凸轮表示例较为简单,实际需要动态生成凸轮数据:
st复制// 动态凸轮表生成
FUNCTION_BLOCK FB_DynamicCam
VAR_INPUT
MasterAxis: AXIS_REF;
SlaveAxis: AXIS_REF;
CutLength: REAL := 100.0; // 裁切长度(mm)
PhaseOffset: REAL := 0.0; // 相位偏移
SmoothFactor: REAL := 0.5; // 平滑系数
END_VAR
VAR
nPoints: INT := 100;
CamData: ARRAY[0..99] OF POINT;
LastPos: REAL := 0.0;
END_VAR
// 生成正弦加速度曲线
FOR i := 0 TO nPoints-1 DO
x := i * CutLength / nPoints;
y := CutLength/2 * (1 - COS(2*3.1415926*x/CutLength));
// 应用平滑处理
y := SmoothFactor*y + (1-SmoothFactor)*LastPos;
LastPos := y;
CamData[i].X := x;
CamData[i].Y := y + PhaseOffset;
END_FOR
// 应用凸轮表
AXIS_SET_CAM(SlaveAxis,
POINTS:=CamData,
CYCLE_TIME:=CutLength/MasterAxis.VELOCITY);
这种动态生成方式可以根据不同产品规格实时调整凸轮曲线,比固定凸轮表更灵活。
良好的功能块设计应遵循以下原则:
示例轴控制功能块改进版:
st复制FUNCTION_BLOCK FB_AxisControl EXTENDS FB_BaseControl
VAR_INPUT
// 运动参数
Position: REAL;
Velocity: REAL;
Acceleration: REAL;
Deceleration: REAL;
// 控制命令
CmdMoveAbsolute: BOOL;
CmdMoveRelative: BOOL;
CmdStop: BOOL;
// 配置参数
SoftLimitPos: REAL := 1000.0;
SoftLimitNeg: REAL := -1000.0;
END_VAR
VAR_OUTPUT
ActualPosition: REAL;
ActualVelocity: REAL;
Status: INT; // 状态字
ErrorCode: INT; // 错误代码
END_VAR
VAR
// 内部状态机
State: (IDLE, MOVING, STOPPING, ERROR);
Axis: AXIS_REF;
END_VAR
// 状态机实现
CASE State OF
IDLE:
IF CmdMoveAbsolute THEN
// 检查软限位
IF Position > SoftLimitPos OR Position < SoftLimitNeg THEN
State := ERROR;
ErrorCode := 1001;
ELSE
AXIS_MOVE_ABSOLUTE(Axis, Position, Velocity, Acceleration, Deceleration);
State := MOVING;
END_IF
END_IF
MOVING:
ActualPosition := Axis.ACTUAL_POSITION;
ActualVelocity := Axis.ACTUAL_VELOCITY;
IF CmdStop OR Axis.STATUS = AXIS_STATE_ERROR THEN
AXIS_STOP(Axis, Deceleration);
State := STOPPING;
ELSIF Axis.STATUS = AXIS_STATE_READY THEN
State := IDLE;
END_IF
STOPPING:
IF Axis.STATUS = AXIS_STATE_READY THEN
State := IDLE;
END_IF
ERROR:
// 错误处理逻辑
IF Reset THEN
State := IDLE;
ErrorCode := 0;
END_IF
END_CASE
优秀的大型PLC项目应遵循以下架构原则:
code复制ProjectRoot/
├── Libraries/ // 通用功能库
│ ├── Motion/ // 运动控制相关
│ ├── PID/ // 控制算法
│ └── Safety/ // 安全功能
├── MachineModules/ // 设备模块
│ ├── Feeder/ // 送料模块
│ ├── Cutter/ // 裁切模块
│ └── Winder/ // 收卷模块
├── DataTypes/ // 全局数据类型定义
├── GlobalVariables/ // 全局变量
└── MainProgram/ // 主程序
├── INIT/ // 初始化
├── CYCLIC/ // 循环逻辑
└── EXCEPTION/ // 异常处理
网络诊断工具使用:
常见问题排查:
st复制// 检查从站状态
IF NOT ECAT_SLAVE[1].Operational THEN
// 检查从站供电是否正常
// 检查网线连接是否可靠
// 检查从站配置是否正确
END_IF
// 检查同步误差
IF ECAT_MASTER.DCSyncError > 100 THEN
// 检查网络拓扑是否合理
// 调整分布式时钟参数
END_IF
伺服参数整定步骤:
振动抑制方法:
st复制// 在伺服驱动器中设置
SERVO_PARAM.Filter1.Frequency := 50.0; // 陷波滤波器频率
SERVO_PARAM.Filter1.Bandwidth := 5.0; // 带宽
SERVO_PARAM.Filter1.Gain := 0.8; // 增益
采用Ziegler-Nichols方法进行参数整定:
| 控制类型 | Kp | Ti | Td |
|---|---|---|---|
| P | 0.5Ku | - | - |
| PI | 0.45Ku | 0.83Tu | - |
| PID | 0.6Ku | 0.5Tu | 0.125Tu |
实际项目中,我发现在薄膜张力控制中,采用PI控制加上前馈补偿效果更好:
st复制// 前馈补偿公式
Output := PID_Output + FeedForward * LineSpeed;
安全设计要点:
抗干扰措施:
维护性设计:
实际项目中的经验值:
在完成一个类似模切机项目后,我总结了三点关键经验:首先,运动控制系统的机械安装精度直接影响控制性能,必须确保机械系统的刚性;其次,张力控制需要根据材料特性动态调整PID参数,不能一套参数走天下;最后,结构化编程虽然前期工作量较大,但在后期调试和维护阶段能节省至少50%的时间。