之前分享了5U的结构化编程带了JEC伺服的封装FB,这次是项目实例中的一部分,还是CClink IE FB协议PLC最直接控制伺服,刚调试完成,所有功能都OK
三菱Q系列PLC,伺服驱动器使用的JET伺服,本来打算还是用JEC的,结果没货
和JEC相比,ControlWord和StatusWord中的数据有变更,PDO映射中的顺序有变化,其次是Jog功能的实现方式有少许变化其他差距不大,值得一提的是GW2不支持结构体中嵌套结构体,导致我的控制字和状态字的控制比较麻烦,需要在功能能块中,做中转
BSET( ControlWord.bSwitchOn ,K0,MapOut.ControlWord);
BRST(NOT ControlWord.bSwitchOn ,K0, MapOut.ControlWord );
TEST( TRUE , MapIn.StatusWord, K0 ,StatusWord.bReady );
使用 bSet bRst指令置位字地址的位
使用TEST指令读取字地址中的位
有积分下载附件查看驱动器设定和程序原文件
没有积分的看手册和程序(没有结构体信息)
程序如下
ENO:=EN;
(********************************ControlWord************************************)
BSET( ControlWord.bSwitchOn ,K0,MapOut.ControlWord);
BRST(NOT ControlWord.bSwitchOn ,K0, MapOut.ControlWord );
BSET( ControlWord.bEnableVolatge ,K1, MapOut.ControlWord );
BRST(NOT ControlWord.bEnableVolatge , K1, MapOut.ControlWord );
BSET( ControlWord.bQuickStop ,K2, MapOut.ControlWord );
BRST(NOT ControlWord.bQuickStop ,K2, MapOut.ControlWord );
BSET( ControlWord.bEnableOpreation , K3,MapOut.ControlWord );
BRST(NOT ControlWord.bEnableOpreation ,K3, MapOut.ControlWord );
BSET( ControlWord.Bit04,K4, MapOut.ControlWord );
BRST(NOT ControlWord.Bit04, K4,MapOut.ControlWord );
BSET( ControlWord.Bit05, K5,MapOut.ControlWord );
BRST(NOT ControlWord.Bit05, K5,MapOut.ControlWord );
BSET( ControlWord.Bit06,K6, MapOut.ControlWord );
BRST(NOT ControlWord.Bit06,K6, MapOut.ControlWord );
BSET( ControlWord.bFaultReset ,K7, MapOut.ControlWord );
BRST(NOT ControlWord.bFaultReset ,K7, MapOut.ControlWord);
BSET( ControlWord.bHalt,K8, MapOut.ControlWord);
BRST(NOT ControlWord.bHalt,K8, MapOut.ControlWord );
BSET( ControlWord.Bit09,K9, MapOut.ControlWord );
BRST(NOT ControlWord.Bit09,K9, MapOut.ControlWord);
BSET( ControlWord.Bit10, K10,MapOut.ControlWord );
BRST(NOT ControlWord.Bit10,K10, MapOut.ControlWord );
BSET( ControlWord.Bit11,K11, MapOut.ControlWord );
BRST(NOT ControlWord.Bit11,K11, MapOut.ControlWord );
BSET( ControlWord.Bit12,K12, MapOut.ControlWord );
BRST(NOT ControlWord.Bit12,K12, MapOut.ControlWord );
BSET( ControlWord.Bit13,K13, MapOut.ControlWord );
BRST(NOT ControlWord.Bit13,K13, MapOut.ControlWord);
BSET( ControlWord.Bit14,K14, MapOut.ControlWord );
BRST(NOT ControlWord.Bit14,K14, MapOut.ControlWord );
BSET( ControlWord.Bit15,K15, MapOut.ControlWord );
BRST(NOT ControlWord.Bit15,K15, MapOut.ControlWord );
(********************************StatusWord************************************)
TEST( TRUE , MapIn.StatusWord, K0 ,StatusWord.bReady );
TEST( TRUE , MapIn.StatusWord, K1 ,StatusWord.bSwitchedOn);
TEST( TRUE , MapIn.StatusWord, K2 ,StatusWord.bOperationEnabled);
TEST( TRUE , MapIn.StatusWord, K3 ,StatusWord.bFault);
TEST( TRUE , MapIn.StatusWord, K4 ,StatusWord.bVoltageEnabled);
TEST( TRUE , MapIn.StatusWord, K5 ,StatusWord.bQuickStop);
TEST( TRUE , MapIn.StatusWord, K6 ,StatusWord.bSwitchOnDisabled);
TEST( TRUE , MapIn.StatusWord, K7 ,StatusWord.bWarning);
TEST( TRUE , MapIn.StatusWord, K8 ,StatusWord.Bit08);
TEST( TRUE , MapIn.StatusWord, K9 ,StatusWord.Bit09);
TEST( TRUE , MapIn.StatusWord, K10 ,StatusWord.bTargetReached);
TEST( TRUE , MapIn.StatusWord, K11 ,StatusWord.bInternalLimitActive);
TEST( TRUE , MapIn.StatusWord, K12 ,StatusWord.Bit12);
TEST( TRUE , MapIn.StatusWord, K13 ,StatusWord.Bit13);
TEST( TRUE , MapIn.StatusWord, K14 ,StatusWord.Bit14);
TEST( TRUE , MapIn.StatusWord, K15 ,StatusWord.Bit15);
(********************************使能************************************)
ControlWord.bQuickStop:=TRUE;
ControlWord.bEnableVolatge:=TRUE;
ControlWord.bSwitchOn:=bEnable AND StatusWord.bVoltageEnabled AND StatusWord.bQuickStop AND StatusWord.bReady AND NOT StatusWord.bSwitchOnDisabled;
ControlWord.bEnableOpreation:=StatusWord.bSwitchedOn AND NOT Operation.bHMI_ServoOn AND bEnable;
S_MotionOperation:=StatusWord.bOperationEnabled;
Status.bServoOn:=S_MotionOperation;
bBreak:=(S_MotionOperation AND NOT Operation.bHMI_Break) OR (NOT S_MotionOperation AND Operation.bHMI_Break);
(*刹车自动打开*)
IF NOT bManual THEN
Operation.bHMI_Break:=FALSE;
Operation.bHMI_ServoOn:=FALSE;
END_IF;
(******************************公共**********************************)
(*单位转换*)
IF Parameter.nEncoderResolution<>0.0 AND Parameter.nPitch<>0.0 THEN
Status.nActPos:=DINT_TO_REAL(MapIn.ActPos)/Parameter.nEncoderResolution*Parameter.nPitch;
Status.nActVel:=DINT_TO_REAL(MapIn.ActVel)/6000.0*Parameter.nPitch;
MapOut.TargetPos:=REAL_TO_DINT(nTargetPos/Parameter.nPitch*Parameter.nEncoderResolution);
MapOut.ProfileVel:=REAL_TO_DINT(nTargetVel/Parameter.nPitch*6000.0);
MapOut.TargetVel:=REAL_TO_DINT(nTargetVel/Parameter.nPitch*6000.0);
END_IF;
(*加减速度*)
MapOut.nACC:=Parameter.nACC;
MapOut.nDEC:=Parameter.nDEC;
(*模式切换*)
IF NOT bEnable THEN
MapOut.ModesOfOperation:=0;
END_IF;
(********************************JOG*************************************)
(*使用PV模式(Mode OF Operation=3)实现JOG功能
//ControlWord.Bit08在PV模式为下 0为实施定位、1为电机停止
//ControlWord.Bit15在PV模式下为执行定位*)
IF Operation.bHMI_JogN OR Operation.bHMI_JogP THEN
MapOut.ModesOfOperation:=3;
END_IF;
IF MapIn.ModesOfOperationDisplay=3 THEN
IF Operation.bHMI_Jogp OR Operation.bHMI_JogN THEN
IF Operation.bHMI_Jogp THEN
nTargetVel:=Parameter.nJogVel;
END_IF;
IF Operation.bHMI_JogN THEN
nTargetVel:=-Parameter.nJogVel;
END_IF;
ELSE
nTargetVel:=0.0;
END_IF;
ControlWord.Bit15:=(Operation.bHMI_JogN OR Operation.bHMI_JogP) AND S_MotionOperation;
END_IF;
(******************************原点搜索**********************************)
(*原点复归方式为:位置设定型,使用HM模式(Mode OF Operation=6)
//ControlWord.Bit04在HM模式下为原点复归
//StatusWord.Bit12在HM模式下为原点复归完成
//StatusWord.Bit13在HM模式下为原点复归报警 *)
(*切换HM模式*)
IF Operation.bHMI_Orgin THEN
MapOut.ModesOfOperation:=6;
END_IF;
IF MapIn.ModesOfOperationDisplay=6 THEN
(*原点复归执行位*)
ControlWord.Bit04:=Operation.bHMI_Orgin ;
END_IF;
(*原点复归完成*)
Status.bHomed:=StatusWord.Bit12;
(********************************定位执行************************************)
(*使用PP模式(Mode OF Operation=1)实现定位功能
//ControlWord.Bit04在PP模式为下为定位执行
//ControlWord.Bit06在PP模式为下 0为绝对定位、1为相对定位模式
//ControlWord.Bit08在PP模式为下 0为实施定位、1为电机停止
//StatusWord.Bit10在PP模式为下为定位完成
//StatusWord.Bit12在PP模式为下为定位中
//StatusWord.Bit13在PP模式为下为位置偏差报警*)
(*PP模式切换*)
IF bPosExcute THEN
MapOut.ModesOfOperation:=1;
END_IF;
(*定位执行*)
IF MapIn.ModesOfOperationDisplay=1 THEN
(*相对模式*)
ControlWord.Bit06:=Operation.bRelative;
ControlWord.Bit04:=bPosExcute AND S_MotionOperation AND Operation.bPermit;
END_IF;
(*手自动定位执行16点位*)
bPosExcute:=((bManual AND (Operation.bHMI_PosExecute[0] OR Operation.bHMI_PosExecute[1] OR Operation.bHMI_PosExecute[2] OR
Operation.bHMI_PosExecute[3] OR Operation.bHMI_PosExecute[4]OR Operation.bHMI_PosExecute[5]OR
Operation.bHMI_PosExecute[6] OR Operation.bHMI_PosExecute[7] OR Operation.bHMI_PosExecute[8] OR
Operation.bHMI_PosExecute[9] OR Operation.bHMI_PosExecute[10] OR Operation.bHMI_PosExecute[11] OR
Operation.bHMI_PosExecute[12] OR Operation.bHMI_PosExecute[13] OR Operation.bHMI_PosExecute[14] OR
Operation.bHMI_PosExecute[15] ))OR
(Operation.bAuto_PosExecute[0] OR Operation.bAuto_PosExecute[1] OR Operation.bAuto_PosExecute[2] OR
Operation.bAuto_PosExecute[3] OR Operation.bAuto_PosExecute[4] OR Operation.bAuto_PosExecute[5] OR
Operation.bAuto_PosExecute[6] OR Operation.bAuto_PosExecute[7] OR Operation.bAuto_PosExecute[8] OR
Operation.bAuto_PosExecute[9] OR Operation.bAuto_PosExecute[10] OR Operation.bAuto_PosExecute[11] OR
Operation.bAuto_PosExecute[12] OR Operation.bAuto_PosExecute[13] OR Operation.bAuto_PosExecute[14] OR
Operation.bAuto_PosExecute[15]))
AND Operation.bPermit AND S_MotionOperation;
(*定位参数调用&定位完成判定*)
FOR nNumber := 0 TO 15 DO
(*定位参数设定*)
IF Operation.bHMI_SetPos[nNumber] THEN
Parameter.nPOS[nNumber]:=Status.nActPos;
END_IF;
(*定位数据上下限*)
nUpLimit[nNumber]:=Parameter.nPOS[nNumber]+Parameter.nDeviation;
nLowLimit[nNumber]:=Parameter.nPOS[nNumber]-Parameter.nDeviation;
(*定位参数调用*)
IF Operation.bAuto_PosExecute[nNumber] OR Operation.bHMI_PosExecute[nNumber] THEN
IF bManual THEN
nTargetVel:=Parameter.nManualVel;
ELSE
nTargetVel:=Parameter.nAutoVel[nNumber];
END_IF;
nTargetPos:=Parameter.nPOS[nNumber];
END_IF;
(*定位完成判定*)
IF nUpLimit[nNumber]>=Status.nActPos AND nLowLimit[nNumber]<=Status.nActPos THEN
Status.bDone[nNumber]:=TRUE;
ELSE
Status.bDone[nNumber]:=FALSE;
END_IF;
END_FOR;
(******************************报警&复位**********************************)
(*复位*)
ControlWord.bFaultReset:=bReset OR Operation.bHMI_Reset;
(*报警&报警代码*)
Status.nErrorID:=MapIn.CurrentAlarm;
Status.bError:=StatusWord.bWarning OR StatusWord.bFault;
(*********************************状态************************************)
Status.bBusy:=StatusWord.Bit12;
IF Status.bError THEN
Status.nStatus:=0;
ELSE
IF NOT StatusWord.bOperationEnabled THEN
Status.nStatus:=1;
ELSIF Status.bBusy THEN
Status.nStatus:=2;
ELSE
Status.nStatus:=3;
END_IF;
END_IF;