TwinCAT3 PLC多轴编程的方法

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

方法一

定义每个轴的基本功能,包括上电、下电、走相对、走绝对、读位置、读状态、复位、停止等。
TwinCAT3 PLC多轴编程的方法_第1张图片
在Axis_Base_PTP中定义变量:

FUNCTION_BLOCK Axis_Base_PTP

VAR
	REF: AXIS_REF;
	mcMoveRela: MC_MoveRelative;
	mcPower: MC_Power;
	mcStop: MC_Stop;
	mcMoveAbs: MC_MoveAbsolute;
	mcReset: MC_Reset;
	mcReadPosition: MC_ReadActualPosition;
	mcReadStatus: MC_ReadStatus;
	mcHalt: MC_Halt;
	
	AxisPara:ST_AxisPara;
END_VAR

M_PowerOn方法代码:

METHOD M_PowerOn : BOOL
VAR_INPUT
	bExcute : BOOL;
END_VAR

VAR_OUTPUT
    bStatus  : BOOL; (* B *)
    bBusy    : BOOL; (* V *)
    bActive  : BOOL; (* V *)
    bError   : BOOL; (* B *)
    dErrorID : UDINT; (* E *)
END_VAR
IF bExcute THEN
	mcPower(
	Axis:= REF, 
	Enable:= TRUE, 
	Enable_Positive:= TRUE, 
	Enable_Negative:= TRUE, 
	Override:= AxisPara.rOverride, 
	BufferMode:= , 
	Options:= , 
	Status=> bStatus, 
	Busy=> bBusy, 
	Active=> bActive, 
	Error=> bError, 
	ErrorID=> dErrorID);
END_IF

M_MoveRela方法代码:

METHOD M_MoveRela : BOOL
VAR_INPUT
	bLimit_1 	: BOOL;
	bLimit_2 	: BOOL;
	rDistance 	: REAL;
	rVelocity   : REAL;
	bExcute 	: BOOL;
END_VAR

VAR_OUTPUT
    bDone    : BOOL; (* B *)
    bBusy    : BOOL; (* V *)
    bActive  : BOOL; (* V *)
    bError   : BOOL; (* B *)
    dErrorID : UDINT; (* E *)
END_VAR
IF rDistance>0 THEN
		mcHalt(
		Axis:= REF, 
		Execute:= bLimit_1, 
		Deceleration:= AxisPara.Deceleration, 
		Jerk:= , 
		BufferMode:= , 
		Options:= , 
		Done=> , 
		Busy=> ,                                   
		Active=> , 
		CommandAborted=> , 
		Error=> , 
		ErrorID=> );  
	IF NOT bLimit_1 THEN
		mcMoveRela(
		Axis:= REF, 
		Execute:= bExcute, 
		Distance:= rDistance, 
		Velocity:= rVelocity, 
		Acceleration:= AxisPara.Acceleration, 
		Deceleration:= AxisPara.Deceleration, 
		Jerk:= , 
		BufferMode:= , 
		Options:= , 
		Done=> bDone, 
		Busy=> bBusy, 
		Active=> bActive, 
		CommandAborted=> , 
		Error=> bError, 
		ErrorID=> dErrorID);
	END_IF
	
ELSIF rDistance<0 THEN
		mcHalt(
		Axis:= REF, 
		Execute:= bLimit_2, 
		Deceleration:= AxisPara.Deceleration, 
		Jerk:= , 
		BufferMode:= , 
		Options:= , 
		Done=> , 
		Busy=> ,                                   
		Active=> , 
		CommandAborted=> , 
		Error=> , 
		ErrorID=> ); 
	IF NOT bLimit_2 THEN
		mcMoveRela(
		Axis:= REF, 
		Execute:= bExcute, 
		Distance:= rDistance, 
		Velocity:= rVelocity, 
		Acceleration:= AxisPara.Acceleration, 
		Deceleration:= AxisPara.Deceleration, 
		Jerk:= , 
		BufferMode:= , 
		Options:= , 
		Done=> bDone, 
		Busy=> bBusy, 
		Active=> bActive, 
		CommandAborted=> , 
		Error=> bError, 
		ErrorID=> dErrorID);	
	END_IF
END_IF

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

FUNCTION_BLOCK Axis11_PTP EXTENDS Axis_Base_PTP
VAR_INPUT
END_VAR

VAR_OUTPUT
	bMagnet_1  AT%Q* : BOOL;
	bMagnet_2  AT%Q* : BOOL;
END_VAR

VAR
	bIn : BOOL :=FALSE;
	bOut: BOOL :=FALSE;
	
	TON_0: TON;
	TON_1: TON;
	
	bTemp1: BOOL;
	bTemp2: BOOL;
	
	MC_MoveRelative_0: MC_MoveRelative;
	mcHaltChange_0: MC_Halt;
	
END_VAR

M_TurnInOut方法代码:

METHOD M_TurnInOut : BOOL
VAR_INPUT
	bTurnIn	 : BOOL;
	bTurnOut : BOOL;
	bLimit1	 : BOOL;
END_VAR

VAR_OUTPUT
END_VAR

TwinCAT3 PLC多轴编程的方法_第2张图片
轴12、13等同理,省略。

在Main函数中定义变量:

	//定义接口及继承关系
	Axis		:   ARRAY[1..10] OF Axis_Base_PTP;
	Axis11		:   Axis11_PTP;
	Axis12		:   Axis12_PTP;
	Axis13		:   Axis13_PTP;
	
	//选择电机轴号
	iAxisNum  AT%I* : UINT;(*电机轴号*)
	
	//定义电机运行相对距离参数
	rDistance  AT%I* : REAL;(*运动距离*)
	rVelocity  AT%I* : REAL;(*运动速度*)
	
	//定义结构体
	AxisPara:ST_AxisPara;(*轴参数结构体*)
	AxisStatus:ST_AxisStatus;(*轴状态结构体*)	
	PoweronStatus:ST_PoweronStatus;	(*上电模块结构体*)
	PoweroffStatus:ST_PoweroffStatus;(*下电模块结构体*)	
	MoveAbsStatus:ST_MoveAbsStatus;	(*绝对运动模式结构体*)
	MoveRelaStatus:ST_MoveRelaStatus;(*相对运动模式结构体*)	
	StopStatus:ST_StopStatus;(*停止模块结构体*)
	ResetStatus:ST_ResetStatus;(*复位模块结构体*)
	ReadPosStatus:ST_ReadPosStatus;(*读取轴位置结构体*)
	HomeStatus:ST_HomeStatus;(*寻参模块结构体*)
	LimitStatus:ST_LimitStatus;(*限位开关状态*)
	
	//定义指令
	bComPowerOn	 	AT%I* :  BOOL;(*上电命令*)
	bComPowerOff	AT%I* :  BOOL;(*下电命令*)
	bComMoveRela 	AT%I* :  BOOL;(*相对位置指令*)
	bComStop	 	AT%I* :  BOOL;(*停止指令*)
	bComMoveAbs	 	AT%I* :  BOOL;(*绝对位置指令*)
	bComRest	 	AT%I* :  BOOL;(*复位指令*)
	bComReadPos	 	AT%I* :  BOOL;(*读取当前位置指令*)
	bComReadStatus	AT%I* :  BOOL;(*读取电机状态指令*)
	bHome			AT%I* :  BOOL;(*电机13寻参指令*)
	bGlassForward	AT%I* :  BOOL;(*电机12更换保护玻璃前进*)
	bGlassBack		AT%I* :  BOOL;(*电机12更换保护玻璃后退*)
	bTurnIn			AT%I* :  BOOL;(*电机11转入*)
	bTurnOut		AT%I* :  BOOL;(*电机11转出*)
CASE iAxisNum OF
	1:
		Axis[1].M_PowerOn(bExcute:=bComPowerOn,bStatus=>PoweronStatus.bStatus,bBusy=>PoweronStatus.bBusy,bActive=>PoweronStatus.bActive,bError=>PoweronStatus.bErr,dErrorID=>PoweronStatus.dErrID);
		Axis[1].M_PowerOff(bExcute:=bComPowerOff,bStatus=>PoweroffStatus.bStatus,bBusy=>PoweroffStatus.bBusy,bActive=>PoweroffStatus.bActive,bError=>PoweroffStatus.bErr,dErrorID=>PoweroffStatus.dErrID);
		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);
		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);
		Axis[1].M_Stop(bExcute:=bComStop,bDone=>StopStatus.bDone,bBusy=>StopStatus.bBusy,bActive=>StopStatus.bActive,bError=>StopStatus.bErr,dErrorID=>StopStatus.dErrID);
		Axis[1].M_Reset(bExcute:=bComRest,bDone=>ResetStatus.bDone,bBusy=>ResetStatus.bBusy,bError=>ResetStatus.bErr,dErrorID=>ResetStatus.dErrID);
		Axis[1].M_ReadPosition(bExcute:=bComReadPos,bValid=>ReadPosStatus.bValid,bBusy=>ReadPosStatus.bBusy,bError=>ReadPosStatus.bErr,dErrorID=>ReadPosStatus.dErrID,lPosition=>ReadPosStatus.lPosition);
		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);
	2:
		Axis[2].M_PowerOn(bExcute:=bComPowerOn,bStatus=>PoweronStatus.bStatus,bBusy=>PoweronStatus.bBusy,bActive=>PoweronStatus.bActive,bError=>PoweronStatus.bErr,dErrorID=>PoweronStatus.dErrID);
		Axis[2].M_PowerOff(bExcute:=bComPowerOff,bStatus=>PoweroffStatus.bStatus,bBusy=>PoweroffStatus.bBusy,bActive=>PoweroffStatus.bActive,bError=>PoweroffStatus.bErr,dErrorID=>PoweroffStatus.dErrID);
		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);
		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);
		Axis[2].M_Stop(bExcute:=bComStop,bDone=>StopStatus.bDone,bBusy=>StopStatus.bBusy,bActive=>StopStatus.bActive,bError=>StopStatus.bErr,dErrorID=>StopStatus.dErrID);
		Axis[2].M_Reset(bExcute:=bComRest,bDone=>ResetStatus.bDone,bBusy=>ResetStatus.bBusy,bError=>ResetStatus.bErr,dErrorID=>ResetStatus.dErrID);
		Axis[2].M_ReadPosition(bExcute:=bComReadPos,bValid=>ReadPosStatus.bValid,bBusy=>ReadPosStatus.bBusy,bError=>ReadPosStatus.bErr,dErrorID=>ReadPosStatus.dErrID,lPosition=>ReadPosStatus.lPosition);
		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);
		……………………
	13:
		Axis13.M_PowerOn(bExcute:=bComPowerOn,bStatus=>PoweronStatus.bStatus,bBusy=>PoweronStatus.bBusy,bActive=>PoweronStatus.bActive,bError=>PoweronStatus.bErr,dErrorID=>PoweronStatus.dErrID);
		Axis13.M_PowerOff(bExcute:=bComPowerOff,bStatus=>PoweroffStatus.bStatus,bBusy=>PoweroffStatus.bBusy,bActive=>PoweroffStatus.bActive,bError=>PoweroffStatus.bErr,dErrorID=>PoweroffStatus.dErrID);
		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);
		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);
		Axis13.M_Stop(bExcute:=bComStop,bDone=>StopStatus.bDone,bBusy=>StopStatus.bBusy,bActive=>StopStatus.bActive,bError=>StopStatus.bErr,dErrorID=>StopStatus.dErrID);
		Axis13.M_Reset(bExcute:=bComRest,bDone=>ResetStatus.bDone,bBusy=>ResetStatus.bBusy,bError=>ResetStatus.bErr,dErrorID=>ResetStatus.dErrID);
		Axis13.M_ReadPosition(bExcute:=bComReadPos,bValid=>ReadPosStatus.bValid,bBusy=>ReadPosStatus.bBusy,bError=>ReadPosStatus.bErr,dErrorID=>ReadPosStatus.dErrID,lPosition=>ReadPosStatus.lPosition);
		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);
	    Axis13.M_Home(bExcute:=bHome,bCalibrationCam:=Axis_13_CaliCam,bDone=>HomeStatus.bDone,bBusy=>HomeStatus.bBusy,bActive=>HomeStatus.bActive,bError=>HomeStatus.bErr,dErrorID=>HomeStatus.dErrID);
END_CASE

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

方法二

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

在Main中添加Action
TwinCAT3 PLC多轴编程的方法_第3张图片
ACT_PowerOn方法代码,其余类似。

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

Main函数代码:

	//定义接口及继承关系
	Axis		:   ARRAY[1..10] OF Axis_Base_PTP;
	Axis11		:   Axis11_PTP;
	Axis12		:   Axis12_PTP;
	Axis13		:   Axis13_PTP;
	
	cmdPowerOn 		AT%I* : ARRAY[1..13] OF BOOL;
	cmdPowerOff 	AT%I* : ARRAY[1..13] OF BOOL;
	cmdMoveRela 	AT%I* : ARRAY[1..13] OF BOOL;
	cmdMoveAbs		AT%I* : ARRAY[1..13] OF BOOL;
	cmdReset 		AT%I* : ARRAY[1..13] OF BOOL;
	cmdStop 		AT%I* : ARRAY[1..13] OF BOOL;
	cmdReadPos 		AT%I* : ARRAY[1..13] OF BOOL;
	cmdReadStatus 	AT%I* : ARRAY[1..13] OF BOOL;
	cmdHome			AT%I* : BOOL;
	cmdGlassForward	AT%I* : BOOL;
	cmdGlassBack	AT%I* : BOOL;
	cmdTurnIn		AT%I* : BOOL;
	cmdTurnOut		AT%I* : BOOL;

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

ACT_PowerOn();
ACT_PowerOff();
ACT_MoveAbs();
ACT_MoveRela();
ACT_Reset();
ACT_Stop();
ACT_ReadPos();
ACT_ReadStatus();

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

方法三

利用面向对象中的接口和继承方法。借鉴示例。
首先定义接口及属性方法,定义一个基类实现接口中的属性和方法,若需要再定义类继承基类。
TwinCAT3 PLC多轴编程的方法_第4张图片
Main函数;

PROGRAM MAIN
VAR
	fbGenerator1 : FB_Generator;
	fbGenerator2 : FB_GeneratorEX;
	iGenerator : I_Generator;
	tCycletime: TIME :=T#3S;
	sVendor: STRING;
	change: BOOL :=TRUE;
	output: BOOL;
END_VAR
IF change THEN
	iGenerator:=fbGenerator1;
ELSE
	iGenerator:=fbGenerator2;
END_IF

output:=iGenerator.Flash();
iGenerator.Cycletime:=tcycletime;
sVendor:=iGenerator.Vendor;

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

优缺点比较

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

你可能感兴趣的:(Beckhoff)