TwinCAT3 PLC多轴编程的方法

发布时间 2023-08-04 10:04:45作者: 一杯清酒邀明月

测试共有13个轴,前10个轴包含基本功能,后3个轴包含独有功能。

方法一

定义每个轴的基本功能,包括上电、下电、走相对、走绝对、读位置、读状态、复位、停止等。

 在Axis_Base_PTP中定义变量:

 1 FUNCTION_BLOCK Axis_Base_PTP
 2 
 3 VAR
 4     REF: AXIS_REF;
 5     mcMoveRela: MC_MoveRelative;
 6     mcPower: MC_Power;
 7     mcStop: MC_Stop;
 8     mcMoveAbs: MC_MoveAbsolute;
 9     mcReset: MC_Reset;
10     mcReadPosition: MC_ReadActualPosition;
11     mcReadStatus: MC_ReadStatus;
12     mcHalt: MC_Halt;
13     
14     AxisPara:ST_AxisPara;
15 END_VAR

M_PowerOn方法代码:

 1 METHOD M_PowerOn : BOOL
 2 VAR_INPUT
 3     bExcute : BOOL;
 4 END_VAR
 5 
 6 VAR_OUTPUT
 7     bStatus  : BOOL; (* B *)
 8     bBusy    : BOOL; (* V *)
 9     bActive  : BOOL; (* V *)
10     bError   : BOOL; (* B *)
11     dErrorID : UDINT; (* E *)
12 END_VAR
 1 IF bExcute THEN
 2     mcPower(
 3     Axis:= REF, 
 4     Enable:= TRUE, 
 5     Enable_Positive:= TRUE, 
 6     Enable_Negative:= TRUE, 
 7     Override:= AxisPara.rOverride, 
 8     BufferMode:= , 
 9     Options:= , 
10     Status=> bStatus, 
11     Busy=> bBusy, 
12     Active=> bActive, 
13     Error=> bError, 
14     ErrorID=> dErrorID);
15 END_IF

M_MoveRela方法代码:

 1 METHOD M_MoveRela : BOOL
 2 VAR_INPUT
 3     bLimit_1     : BOOL;
 4     bLimit_2     : BOOL;
 5     rDistance     : REAL;
 6     rVelocity   : REAL;
 7     bExcute     : BOOL;
 8 END_VAR
 9 
10 VAR_OUTPUT
11     bDone    : BOOL; (* B *)
12     bBusy    : BOOL; (* V *)
13     bActive  : BOOL; (* V *)
14     bError   : BOOL; (* B *)
15     dErrorID : UDINT; (* E *)
16 END_VAR
 1 IF rDistance>0 THEN
 2         mcHalt(
 3         Axis:= REF, 
 4         Execute:= bLimit_1, 
 5         Deceleration:= AxisPara.Deceleration, 
 6         Jerk:= , 
 7         BufferMode:= , 
 8         Options:= , 
 9         Done=> , 
10         Busy=> ,                                   
11         Active=> , 
12         CommandAborted=> , 
13         Error=> , 
14         ErrorID=> );  
15     IF NOT bLimit_1 THEN
16         mcMoveRela(
17         Axis:= REF, 
18         Execute:= bExcute, 
19         Distance:= rDistance, 
20         Velocity:= rVelocity, 
21         Acceleration:= AxisPara.Acceleration, 
22         Deceleration:= AxisPara.Deceleration, 
23         Jerk:= , 
24         BufferMode:= , 
25         Options:= , 
26         Done=> bDone, 
27         Busy=> bBusy, 
28         Active=> bActive, 
29         CommandAborted=> , 
30         Error=> bError, 
31         ErrorID=> dErrorID);
32     END_IF
33     
34 ELSIF rDistance<0 THEN
35         mcHalt(
36         Axis:= REF, 
37         Execute:= bLimit_2, 
38         Deceleration:= AxisPara.Deceleration, 
39         Jerk:= , 
40         BufferMode:= , 
41         Options:= , 
42         Done=> , 
43         Busy=> ,                                   
44         Active=> , 
45         CommandAborted=> , 
46         Error=> , 
47         ErrorID=> ); 
48     IF NOT bLimit_2 THEN
49         mcMoveRela(
50         Axis:= REF, 
51         Execute:= bExcute, 
52         Distance:= rDistance, 
53         Velocity:= rVelocity, 
54         Acceleration:= AxisPara.Acceleration, 
55         Deceleration:= AxisPara.Deceleration, 
56         Jerk:= , 
57         BufferMode:= , 
58         Options:= , 
59         Done=> bDone, 
60         Busy=> bBusy, 
61         Active=> bActive, 
62         CommandAborted=> , 
63         Error=> bError, 
64         ErrorID=> dErrorID);    
65     END_IF
66 END_IF

对于附加功能的轴11,继承Axis_Base_PTP,独有的方法M_TurnInOut另外添加。
Axis_Base_PTP继承自基类并定义变量:

 1 FUNCTION_BLOCK Axis11_PTP EXTENDS Axis_Base_PTP
 2 VAR_INPUT
 3 END_VAR
 4 
 5 VAR_OUTPUT
 6     bMagnet_1  AT%Q* : BOOL;
 7     bMagnet_2  AT%Q* : BOOL;
 8 END_VAR
 9 
10 VAR
11     bIn : BOOL :=FALSE;
12     bOut: BOOL :=FALSE;
13     
14     TON_0: TON;
15     TON_1: TON;
16     
17     bTemp1: BOOL;
18     bTemp2: BOOL;
19     
20     MC_MoveRelative_0: MC_MoveRelative;
21     mcHaltChange_0: MC_Halt;
22     
23 END_VAR

M_TurnInOut方法代码:

1 METHOD M_TurnInOut : BOOL
2 VAR_INPUT
3     bTurnIn     : BOOL;
4     bTurnOut : BOOL;
5     bLimit1     : BOOL;
6 END_VAR
7 
8 VAR_OUTPUT
9 END_VAR

轴12、13等同理,省略。

在Main函数中定义变量:

 1     //定义接口及继承关系
 2     Axis        :   ARRAY[1..10] OF Axis_Base_PTP;
 3     Axis11        :   Axis11_PTP;
 4     Axis12        :   Axis12_PTP;
 5     Axis13        :   Axis13_PTP;
 6     
 7     //选择电机轴号
 8     iAxisNum  AT%I* : UINT;(*电机轴号*)
 9     
10     //定义电机运行相对距离参数
11     rDistance  AT%I* : REAL;(*运动距离*)
12     rVelocity  AT%I* : REAL;(*运动速度*)
13     
14     //定义结构体
15     AxisPara:ST_AxisPara;(*轴参数结构体*)
16     AxisStatus:ST_AxisStatus;(*轴状态结构体*)    
17     PoweronStatus:ST_PoweronStatus;    (*上电模块结构体*)
18     PoweroffStatus:ST_PoweroffStatus;(*下电模块结构体*)    
19     MoveAbsStatus:ST_MoveAbsStatus;    (*绝对运动模式结构体*)
20     MoveRelaStatus:ST_MoveRelaStatus;(*相对运动模式结构体*)    
21     StopStatus:ST_StopStatus;(*停止模块结构体*)
22     ResetStatus:ST_ResetStatus;(*复位模块结构体*)
23     ReadPosStatus:ST_ReadPosStatus;(*读取轴位置结构体*)
24     HomeStatus:ST_HomeStatus;(*寻参模块结构体*)
25     LimitStatus:ST_LimitStatus;(*限位开关状态*)
26     
27     //定义指令
28     bComPowerOn         AT%I* :  BOOL;(*上电命令*)
29     bComPowerOff    AT%I* :  BOOL;(*下电命令*)
30     bComMoveRela     AT%I* :  BOOL;(*相对位置指令*)
31     bComStop         AT%I* :  BOOL;(*停止指令*)
32     bComMoveAbs         AT%I* :  BOOL;(*绝对位置指令*)
33     bComRest         AT%I* :  BOOL;(*复位指令*)
34     bComReadPos         AT%I* :  BOOL;(*读取当前位置指令*)
35     bComReadStatus    AT%I* :  BOOL;(*读取电机状态指令*)
36     bHome            AT%I* :  BOOL;(*电机13寻参指令*)
37     bGlassForward    AT%I* :  BOOL;(*电机12更换保护玻璃前进*)
38     bGlassBack        AT%I* :  BOOL;(*电机12更换保护玻璃后退*)
39     bTurnIn            AT%I* :  BOOL;(*电机11转入*)
40     bTurnOut        AT%I* :  BOOL;(*电机11转出*)
 1 CASE iAxisNum OF
 2     1:
 3         Axis[1].M_PowerOn(bExcute:=bComPowerOn,bStatus=>PoweronStatus.bStatus,bBusy=>PoweronStatus.bBusy,bActive=>PoweronStatus.bActive,bError=>PoweronStatus.bErr,dErrorID=>PoweronStatus.dErrID);
 4         Axis[1].M_PowerOff(bExcute:=bComPowerOff,bStatus=>PoweroffStatus.bStatus,bBusy=>PoweroffStatus.bBusy,bActive=>PoweroffStatus.bActive,bError=>PoweroffStatus.bErr,dErrorID=>PoweroffStatus.dErrID);
 5         Axis[1].M_MoveAbs(bLimit_1:=LimitStatus.Axis_1_Limit_1,bLimit_2:=LimitStatus.Axis_1_Limit_2,rDistance:=rDistance,rVelocity:=rVelocity,bExcute:=bComMoveAbs,bDone=>MoveAbsStatus.bDone,bBusy=>MoveAbsStatus.bBusy,bActive=>MoveAbsStatus.bActive,bError=>MoveAbsStatus.bErr,dErrorID=>MoveAbsStatus.dErrID);
 6         Axis[1].M_MoveRela(bLimit_1:=LimitStatus.Axis_1_Limit_1,bLimit_2:=LimitStatus.Axis_1_Limit_2,rDistance:=rDistance,rVelocity:=rVelocity,bExcute:=bComMoveRela,bDone=>MoveRelaStatus.bDone,bBusy=>MoveRelaStatus.bBusy,bActive=>MoveRelaStatus.bActive,bError=>MoveRelaStatus.bErr,dErrorID=>MoveRelaStatus.dErrID);
 7         Axis[1].M_Stop(bExcute:=bComStop,bDone=>StopStatus.bDone,bBusy=>StopStatus.bBusy,bActive=>StopStatus.bActive,bError=>StopStatus.bErr,dErrorID=>StopStatus.dErrID);
 8         Axis[1].M_Reset(bExcute:=bComRest,bDone=>ResetStatus.bDone,bBusy=>ResetStatus.bBusy,bError=>ResetStatus.bErr,dErrorID=>ResetStatus.dErrID);
 9         Axis[1].M_ReadPosition(bExcute:=bComReadPos,bValid=>ReadPosStatus.bValid,bBusy=>ReadPosStatus.bBusy,bError=>ReadPosStatus.bErr,dErrorID=>ReadPosStatus.dErrID,lPosition=>ReadPosStatus.lPosition);
10         Axis[1].M_ReadStatus(bExcute:=bComReadStatus,bValid=>AxisStatus.Axis_Valid,bBusy=>AxisStatus.Axis_Busy,bError=>AxisStatus.Axis_Err,dErrorID=>AxisStatus.Axis_ErrID,bErrorStop=>AxisStatus.Axis_ErrorStop,bDisabled=>AxisStatus.Axis_Disabled,bStopping=>AxisStatus.Axis_Stopping,bStandStill=>AxisStatus.Axis_StandStill,bDiscreteMotion=>AxisStatus.Axis_DiscreteMotion,bContinuousMotion=>AxisStatus.Axis_ContinuousMotion,bSynchronizedMotion=>AxisStatus.Axis_SynchronizedMotion,bHoming=>AxisStatus.Axis_Homing,bConstantVelocity=>AxisStatus.Axis_ConstantVelocity,bAccelerating=>AxisStatus.Axis_Accelerating,bDecelerating=>AxisStatus.Axis_Decelerating);
11     2:
12         Axis[2].M_PowerOn(bExcute:=bComPowerOn,bStatus=>PoweronStatus.bStatus,bBusy=>PoweronStatus.bBusy,bActive=>PoweronStatus.bActive,bError=>PoweronStatus.bErr,dErrorID=>PoweronStatus.dErrID);
13         Axis[2].M_PowerOff(bExcute:=bComPowerOff,bStatus=>PoweroffStatus.bStatus,bBusy=>PoweroffStatus.bBusy,bActive=>PoweroffStatus.bActive,bError=>PoweroffStatus.bErr,dErrorID=>PoweroffStatus.dErrID);
14         Axis[2].M_MoveAbs(bLimit_1:=LimitStatus.Axis_2_Limit_1,bLimit_2:=LimitStatus.Axis_2_Limit_2,rDistance:=rDistance,rVelocity:=rVelocity,bExcute:=bComMoveAbs,bDone=>MoveAbsStatus.bDone,bBusy=>MoveAbsStatus.bBusy,bActive=>MoveAbsStatus.bActive,bError=>MoveAbsStatus.bErr,dErrorID=>MoveAbsStatus.dErrID);
15         Axis[2].M_MoveRela(bLimit_1:=LimitStatus.Axis_2_Limit_1,bLimit_2:=LimitStatus.Axis_2_Limit_2,rDistance:=rDistance,rVelocity:=rVelocity,bExcute:=bComMoveRela,bDone=>MoveRelaStatus.bDone,bBusy=>MoveRelaStatus.bBusy,bActive=>MoveRelaStatus.bActive,bError=>MoveRelaStatus.bErr,dErrorID=>MoveRelaStatus.dErrID);
16         Axis[2].M_Stop(bExcute:=bComStop,bDone=>StopStatus.bDone,bBusy=>StopStatus.bBusy,bActive=>StopStatus.bActive,bError=>StopStatus.bErr,dErrorID=>StopStatus.dErrID);
17         Axis[2].M_Reset(bExcute:=bComRest,bDone=>ResetStatus.bDone,bBusy=>ResetStatus.bBusy,bError=>ResetStatus.bErr,dErrorID=>ResetStatus.dErrID);
18         Axis[2].M_ReadPosition(bExcute:=bComReadPos,bValid=>ReadPosStatus.bValid,bBusy=>ReadPosStatus.bBusy,bError=>ReadPosStatus.bErr,dErrorID=>ReadPosStatus.dErrID,lPosition=>ReadPosStatus.lPosition);
19         Axis[2].M_ReadStatus(bExcute:=bComReadStatus,bValid=>AxisStatus.Axis_Valid,bBusy=>AxisStatus.Axis_Busy,bError=>AxisStatus.Axis_Err,dErrorID=>AxisStatus.Axis_ErrID,bErrorStop=>AxisStatus.Axis_ErrorStop,bDisabled=>AxisStatus.Axis_Disabled,bStopping=>AxisStatus.Axis_Stopping,bStandStill=>AxisStatus.Axis_StandStill,bDiscreteMotion=>AxisStatus.Axis_DiscreteMotion,bContinuousMotion=>AxisStatus.Axis_ContinuousMotion,bSynchronizedMotion=>AxisStatus.Axis_SynchronizedMotion,bHoming=>AxisStatus.Axis_Homing,bConstantVelocity=>AxisStatus.Axis_ConstantVelocity,bAccelerating=>AxisStatus.Axis_Accelerating,bDecelerating=>AxisStatus.Axis_Decelerating);
20         ……………………
21     13:
22         Axis13.M_PowerOn(bExcute:=bComPowerOn,bStatus=>PoweronStatus.bStatus,bBusy=>PoweronStatus.bBusy,bActive=>PoweronStatus.bActive,bError=>PoweronStatus.bErr,dErrorID=>PoweronStatus.dErrID);
23         Axis13.M_PowerOff(bExcute:=bComPowerOff,bStatus=>PoweroffStatus.bStatus,bBusy=>PoweroffStatus.bBusy,bActive=>PoweroffStatus.bActive,bError=>PoweroffStatus.bErr,dErrorID=>PoweroffStatus.dErrID);
24         Axis13.M_MoveAbs(bLimit_1:=LimitStatus.Axis_13_Limit_1,bLimit_2:=LimitStatus.Axis_13_Limit_2,rDistance:=rDistance,rVelocity:=rVelocity,bExcute:=bComMoveAbs,bDone=>MoveAbsStatus.bDone,bBusy=>MoveAbsStatus.bBusy,bActive=>MoveAbsStatus.bActive,bError=>MoveAbsStatus.bErr,dErrorID=>MoveAbsStatus.dErrID);
25         Axis13.M_MoveRela(bLimit_1:=LimitStatus.Axis_13_Limit_1,bLimit_2:=LimitStatus.Axis_13_Limit_2,rDistance:=rDistance,rVelocity:=rVelocity,bExcute:=bComMoveRela,bDone=>MoveRelaStatus.bDone,bBusy=>MoveRelaStatus.bBusy,bActive=>MoveRelaStatus.bActive,bError=>MoveRelaStatus.bErr,dErrorID=>MoveRelaStatus.dErrID);
26         Axis13.M_Stop(bExcute:=bComStop,bDone=>StopStatus.bDone,bBusy=>StopStatus.bBusy,bActive=>StopStatus.bActive,bError=>StopStatus.bErr,dErrorID=>StopStatus.dErrID);
27         Axis13.M_Reset(bExcute:=bComRest,bDone=>ResetStatus.bDone,bBusy=>ResetStatus.bBusy,bError=>ResetStatus.bErr,dErrorID=>ResetStatus.dErrID);
28         Axis13.M_ReadPosition(bExcute:=bComReadPos,bValid=>ReadPosStatus.bValid,bBusy=>ReadPosStatus.bBusy,bError=>ReadPosStatus.bErr,dErrorID=>ReadPosStatus.dErrID,lPosition=>ReadPosStatus.lPosition);
29         Axis13.M_ReadStatus(bExcute:=bComReadStatus,bValid=>AxisStatus.Axis_Valid,bBusy=>AxisStatus.Axis_Busy,bError=>AxisStatus.Axis_Err,dErrorID=>AxisStatus.Axis_ErrID,bErrorStop=>AxisStatus.Axis_ErrorStop,bDisabled=>AxisStatus.Axis_Disabled,bStopping=>AxisStatus.Axis_Stopping,bStandStill=>AxisStatus.Axis_StandStill,bDiscreteMotion=>AxisStatus.Axis_DiscreteMotion,bContinuousMotion=>AxisStatus.Axis_ContinuousMotion,bSynchronizedMotion=>AxisStatus.Axis_SynchronizedMotion,bHoming=>AxisStatus.Axis_Homing,bConstantVelocity=>AxisStatus.Axis_ConstantVelocity,bAccelerating=>AxisStatus.Axis_Accelerating,bDecelerating=>AxisStatus.Axis_Decelerating);
30         Axis13.M_Home(bExcute:=bHome,bCalibrationCam:=Axis_13_CaliCam,bDone=>HomeStatus.bDone,bBusy=>HomeStatus.bBusy,bActive=>HomeStatus.bActive,bError=>HomeStatus.bErr,dErrorID=>HomeStatus.dErrID);
31 END_CASE

运行时,先输入iAxisNum,再执行命令即可。

方法二

定义轴基本功能,同上。区别在于Main主函数:

在Main中添加Action

 ACT_PowerOn方法代码,其余类似。

1 FOR i:=1 TO 13 DO
2     Axis[i].M_PowerOn(bExcute:=cmdPowerOn[i],bStatus=>PoweronStatus.bStatus,bBusy=>PoweronStatus.bBusy,bActive=>PoweronStatus.bActive,bError=>PoweronStatus.bErr,dErrorID=>PoweronStatus.dErrID);
3 END_FOR

Main函数代码:

 1     //定义接口及继承关系
 2     Axis        :   ARRAY[1..10] OF Axis_Base_PTP;
 3     Axis11        :   Axis11_PTP;
 4     Axis12        :   Axis12_PTP;
 5     Axis13        :   Axis13_PTP;
 6     
 7     cmdPowerOn         AT%I* : ARRAY[1..13] OF BOOL;
 8     cmdPowerOff     AT%I* : ARRAY[1..13] OF BOOL;
 9     cmdMoveRela     AT%I* : ARRAY[1..13] OF BOOL;
10     cmdMoveAbs        AT%I* : ARRAY[1..13] OF BOOL;
11     cmdReset         AT%I* : ARRAY[1..13] OF BOOL;
12     cmdStop         AT%I* : ARRAY[1..13] OF BOOL;
13     cmdReadPos         AT%I* : ARRAY[1..13] OF BOOL;
14     cmdReadStatus     AT%I* : ARRAY[1..13] OF BOOL;
15     cmdHome            AT%I* : BOOL;
16     cmdGlassForward    AT%I* : BOOL;
17     cmdGlassBack    AT%I* : BOOL;
18     cmdTurnIn        AT%I* : BOOL;
19     cmdTurnOut        AT%I* : BOOL;

主函数调用Action方法进行轮询:

1 ACT_PowerOn();
2 ACT_PowerOff();
3 ACT_MoveAbs();
4 ACT_MoveRela();
5 ACT_Reset();
6 ACT_Stop();
7 ACT_ReadPos();
8 ACT_ReadStatus();

运行时,需针对每个轴的每个指令进行下发。

方法三

利用面向对象中的接口和继承方法。借鉴示例。
首先定义接口及属性方法,定义一个基类实现接口中的属性和方法,若需要再定义类继承基类。

 Main函数;

 1 PROGRAM MAIN
 2 VAR
 3     fbGenerator1 : FB_Generator;
 4     fbGenerator2 : FB_GeneratorEX;
 5     iGenerator : I_Generator;
 6     tCycletime: TIME :=T#3S;
 7     sVendor: STRING;
 8     change: BOOL :=TRUE;
 9     output: BOOL;
10 END_VAR
1 IF change THEN
2     iGenerator:=fbGenerator1;
3 ELSE
4     iGenerator:=fbGenerator2;
5 END_IF
6 
7 output:=iGenerator.Flash();
8 iGenerator.Cycletime:=tcycletime;
9 sVendor:=iGenerator.Vendor;

运行时,通过接口切换调用不同轴模块。

优缺点比较

方法一:上位机调用变量较少,主程序复杂;
方法二:上位机调用变量较多,主程序简单;
方法三:上位机调用变量较少,主程序轴联动复杂;