TYPE "St_SetAxisData_Epos"
VERSION : 0.1
STRUCT
原点 : Bool;
额定转速 : DInt;
最大转速 : DInt;
最大位置 : Real;
最小位置 : Real;
回原模式 : Int;
激活软限位 : Bool;
激活硬限位 : Bool;
每一圈多少lu : DInt;
伺服每转位移 : Real;
设备标识符 : HW_IO;
END_STRUCT;
END_TYPE
TYPE "St_AxisIn_Epos"
VERSION : 0.1
STRUCT
i_xPowerOn : Bool; // 轴使能
i_xHome : Bool; // 轴回原
i_xJogP : Bool; // 轴正向点动
i_xJogN : Bool; // 轴反向点动
i_xAbsGo : Bool; // 轴绝对定位触发
i_xReset : Bool; // 轴复位
i_xStop : Bool; // 轴停止
i_xHalt : Bool; // 轴暂停
i_fJogVel : Real; // 轴点动速度
i_fAbsPos : Real; // 轴绝对定位位置
i_fAbsVel : Real; // 轴绝对定位速度
i_fRunAcc : Int := 100; // 轴运行加速度(绝对定位、相对定位、速度模式等)
i_fRunDec : Int := 100; // 轴运行减速度(绝对定位、相对定位、速度模式等)
END_STRUCT;
END_TYPE
TYPE "St_AxisOut_Epos"
VERSION : 0.1
STRUCT
o_iActMode : Int; // 当前模式
o_xPowerDone : Bool; // 使能完成
o_xAbsDone : Bool; // 绝对定位完成
o_xHomeFind : Bool; // 原点有效信号
o_xStandstill : Bool;
o_xLimitP : Bool; // 轴正限位
o_xLimitN : Bool; // 轴负限位
o_rActPosition : Real; // 当前位置
o_rActVelocity : Real; // 当前速度
o_axGetActPos : Array[0..19] of Bool; // 当前到达的位置点
o_wsStatus : WString[15];
o_xAxisError : Bool; // 轴错误
o_xError : Bool; // 块错误
o_xErrorID : Word; // 错误代号
END_STRUCT;
END_TYPE
TYPE "St_AxisWorkPosition"
VERSION : 0.1
STRUCT
i_fPosition : Real;
i_fVelocity : Real;
END_STRUCT;
END_TYPE
TYPE "系统输入"
VERSION : 0.1
STRUCT
"手动/自动" : Bool;
暂停 : Bool;
停止 : Bool;
急停 : Bool;
复位 : Bool;
END_STRUCT;
END_TYPE
TYPE "St_Axis_Epos"
VERSION : 0.1
STRUCT
配置参数 : "St_SetAxisData_Epos";
in : "St_AxisIn_Epos";
out : "St_AxisOut_Epos";
WorkPosition { S7_SetPoint := 'False'} : Array[0..19] of "St_AxisWorkPosition";
END_STRUCT;
END_TYPE
FUNCTION_BLOCK "FB_Axis_newEpos_ST_2"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
VAR_INPUT
i_stSystemIn : "系统输入";
END_VAR
VAR_IN_OUT
io_stAxis : "St_Axis_Epos";
END_VAR
VAR
SinaPos_Instance {InstructionName := 'SinaPos'; LibVersion := '2.1'} : SinaPos;
绝对定位触发上升沿 {InstructionName := 'R_TRIG'; LibVersion := '1.0'} : R_TRIG;
步数 : Int;
点动步数 : Int;
定位步数 : Int;
回原步数 : Int;
正向点动 { S7_SetPoint := 'True'} : Bool;
反向点动 : Bool;
停止 : Bool;
模式 : Int := 7;
激活模式 : Bool;
设定位置 : Real;
设定位置_1 : Real;
设定速度 : Real;
设定速度_1 : Real;
控制字 : DWord;
定位完成 : Bool;
当前位置 : Real;
当前速度 : Real;
状态字1 : Word;
状态字2 : Word;
状态 : Word;
报警代码 : Word;
故障代码 : Word;
设定定位位置不合理 : Bool;
设定定位速度超过最大转速 : Bool;
设定点动速度超过最大转速 : Bool;
Error : Bool;
需要的圈数 : Real;
轴就绪 : Bool;
最大速度 : Real;
END_VAR
VAR_TEMP
i : Int;
END_VAR
VAR CONSTANT
判断流程 : Int := 0;
点动流程 : Int := 10;
定位流程 : Int := 20;
回原流程 : Int := 30;
END_VAR
BEGIN
//================================================================================
//库文件:无
//功能描述:封装FB284
//硬件平台:S7-1200/S7-1500
//软件平台:TIA博途V19
//-----------------------------------------------------------------------------------------------------------------------------------
//版本记录
//版本 日期 作者
//V1.2 2024-09-01 CaiMiao
//================================================================================
//说明
//增加了20个位置点到达的信号判断,方便触摸屏上做位置信号,自动流程中还是只需要判断AxisOut中的AbsDone信号
//修补了判断最大转速的bug
//增加了解析控制字与状态字
//================================================================================
(********************************************************** 输入数据转换 **********************************************************)
//解析控制字
#控制字.%X0 := TRUE;
#控制字.%X1 := TRUE;
#控制字.%X2 := #io_stAxis.配置参数.激活软限位;
#控制字.%X3 := #io_stAxis.配置参数.激活硬限位;
#控制字.%X6 := #io_stAxis.配置参数.原点;
//圈数=伺服每转位移/位移数
#需要的圈数 := #io_stAxis.in.i_fAbsPos / #io_stAxis.配置参数.伺服每转位移;
IF ABS(#io_stAxis.配置参数.最小位置 - #io_stAxis.配置参数.最大位置) >= ABS(#io_stAxis.in.i_fAbsPos) THEN
#设定位置 := (#需要的圈数 * (DINT_TO_REAL(#io_stAxis.配置参数.每一圈多少lu)));
ELSIF
#io_stAxis.配置参数.最小位置 = 0 AND #io_stAxis.配置参数.最大位置 = 0
THEN
#设定位置 := (#需要的圈数 * (DINT_TO_REAL(#io_stAxis.配置参数.每一圈多少lu)));
ELSE
#设定定位位置不合理 := TRUE;
END_IF;
//速度=设定速度mm/s*60s
//#设定速度mm/min=设定速度mm/s*60s
//设定速度rpm/min=#设定速度mm/min / 伺服每转位移*10
#最大速度 := (DINT_TO_REAL(#io_stAxis.配置参数.最大转速) / 60.0 * #io_stAxis.配置参数.伺服每转位移);
IF #io_stAxis.in.i_xAbsGo THEN
IF #最大速度 >= #io_stAxis.in.i_fAbsVel THEN
#设定速度 := ((#io_stAxis.in.i_fAbsVel * 60.0) / #io_stAxis.配置参数.伺服每转位移 * 10.0);
ELSE
#设定定位速度超过最大转速 := TRUE;
END_IF;
END_IF;
IF (#io_stAxis.in.i_xJogP AND NOT #io_stAxis.in.i_xJogN)
OR (#io_stAxis.in.i_xJogN AND NOT #io_stAxis.in.i_xJogP)
THEN
IF #最大速度 >= #io_stAxis.in.i_fJogVel
THEN
#设定速度 := ((#io_stAxis.in.i_fJogVel * 60.0) / #io_stAxis.配置参数.伺服每转位移 * 10.0);
ELSE
#设定点动速度超过最大转速 := TRUE;
END_IF;
END_IF;
//复位
IF #io_stAxis.in.i_xReset THEN
#设定定位位置不合理 := FALSE;
#设定定位速度超过最大转速 := FALSE;
#设定点动速度超过最大转速 := FALSE;
END_IF;
(********************************************************** 点动与绝对定位的流程 **********************************************************)
#绝对定位触发上升沿(CLK := #io_stAxis.in.i_xAbsGo);
CASE #步数 OF
#判断流程://进入点动的条件
IF (#io_stAxis.in.i_xJogP AND NOT #io_stAxis.in.i_xJogN)
OR (#io_stAxis.in.i_xJogN AND NOT #io_stAxis.in.i_xJogP)
AND #SinaPos_Instance.AxisEnabled
AND #轴就绪
AND NOT #i_stSystemIn."手动/自动"
THEN
#模式 := 3;
IF #SinaPos_Instance.ActMode = 3 AND #SinaPos_Instance.swStatus = 16#7002 THEN
IF (#io_stAxis.in.i_xJogP AND NOT #io_stAxis.in.i_xJogN) THEN
#设定速度_1 := #设定速度;
#反向点动 := TRUE;
#步数 := #点动流程;
ELSIF
(#io_stAxis.in.i_xJogN AND NOT #io_stAxis.in.i_xJogP) THEN
#设定速度_1 := #设定速度;
#正向点动 := TRUE;
#步数 := #点动流程;
END_IF;
END_IF;
END_IF;
//进入绝对定位条件
IF #绝对定位触发上升沿.Q
AND #轴就绪
AND #SinaPos_Instance.AxisEnabled
AND #SinaPos_Instance.AxisRef
THEN
#模式 := 2;//有绝对定位信号后,把数据给到sinapos功能块
IF #SinaPos_Instance.ActMode = 2 AND #SinaPos_Instance.swStatus = 16#7002 THEN
#设定位置_1 := #设定位置;
#设定速度_1 := #设定速度;
#步数 := #定位流程;
END_IF;
END_IF;
//进入回原的条件
IF #io_stAxis.in.i_xHome
AND #SinaPos_Instance.AxisEnabled
AND #SinaPos_Instance.EPosZSW2 = 0
AND NOT #i_stSystemIn."手动/自动"
THEN
#模式 := #io_stAxis.配置参数.回原模式;
#步数 := #回原流程;
END_IF;
#点动流程://点动自动流程
CASE #点动步数 OF
0:
#激活模式 := TRUE;
IF NOT #io_stAxis.in.i_xJogP AND NOT #io_stAxis.in.i_xJogN THEN
#正向点动 := FALSE;
#反向点动 := FALSE;
#停止 := TRUE;
#激活模式 := FALSE;
#点动步数 := 10;
END_IF;
10:
#停止 := FALSE;
IF #SinaPos_Instance.AxisPosOk
AND #SinaPos_Instance.AxisSpFixed
AND #SinaPos_Instance.EPosZSW2 = 0
THEN
#点动步数 := 0;
#步数 := #判断流程;
END_IF;
END_CASE;
#定位流程://定位自动流程
CASE #定位步数 OF
0:
#激活模式 := TRUE;
IF NOT #io_stAxis.in.i_xAbsGo OR (ABS(#设定位置_1 - #当前位置) < 1) THEN
#激活模式 := FALSE;
IF ABS(#设定位置_1 - #当前位置) < 1 THEN
#io_stAxis.out.o_xAbsDone := TRUE;
END_IF;
#定位步数 := 10;
END_IF;
10:
#定位步数 := 0;
#步数 := #判断流程;
END_CASE;
#回原流程://回原自动流程
CASE #回原步数 OF
0:
#激活模式 := TRUE;
IF #SinaPos_Instance.AxisRef AND #当前位置 = 0 THEN
#激活模式 := FALSE;
#回原步数 := 10;
END_IF;
10:
#激活模式 := FALSE;
#回原步数 := 0;
#步数 := #判断流程;
END_CASE;
END_CASE;
(****************************************************************** 功能块调用************************************************************************)
#SinaPos_Instance(ModePos := #模式,
EnableAxis := #io_stAxis.in.i_xPowerOn,
CancelTraversing := NOT #io_stAxis.in.i_xStop AND NOT #停止 AND NOT #i_stSystemIn.停止 AND NOT #i_stSystemIn.急停,
IntermediateStop := NOT #io_stAxis.in.i_xHalt AND NOT #i_stSystemIn.暂停,
Positive := #正向点动,
Negative := #反向点动,
AckError := #io_stAxis.in.i_xReset,
ExecuteMode := #激活模式,
Position := REAL_TO_DINT(#设定位置_1),
Velocity := REAL_TO_DINT(#设定速度_1),
OverV := 100,
OverAcc := #io_stAxis.in.i_fRunAcc,
OverDec := #io_stAxis.in.i_fRunDec,
ConfigEPos := #控制字,
HWIDSTW := #io_stAxis.配置参数.设备标识符,
HWIDZSW := #io_stAxis.配置参数.设备标识符,
AxisEnabled => #io_stAxis.out.o_xPowerDone,
AxisPosOk => #定位完成,
AxisRef => #io_stAxis.out.o_xHomeFind,
ActVelocity => #当前速度,
ActPosition => #当前位置,
ActMode => #io_stAxis.out.o_iActMode,
EPosZSW1 => #状态字1,
EPosZSW2 => #状态字2,
ActWarn => #报警代码,
ActFault => #故障代码,
Error => #Error,
Status => #状态);
(***************************************************************************************** 输出数据**************************************************************************************)
//当前位置=lu的数量*每lu的距离
#io_stAxis.out.o_rActPosition := ((#当前位置) * #io_stAxis.配置参数.伺服每转位移 / (DINT_TO_REAL(#io_stAxis.配置参数.每一圈多少lu)));
//当前速度=额定转速*输出转速/1073741824/60s*每转位移
#io_stAxis.out.o_rActVelocity := (DINT_TO_REAL(#io_stAxis.配置参数.额定转速) * #当前速度 / 1073741824.0) / 60.0 * #io_stAxis.配置参数.伺服每转位移;
(********************************************************** 状态输出**********************************************************)
CASE #状态 OF
16#7002:
#io_stAxis.out.o_wsStatus := WSTRING#'没错误,功能块正在执行';
16#8401:
#io_stAxis.out.o_wsStatus := WSTRING#'驱动错误';
16#8402:
#io_stAxis.out.o_wsStatus := WSTRING#'驱动禁止启动';
16#8403:
#io_stAxis.out.o_wsStatus := WSTRING#'运行中回零不能开始';
16#8600:
#io_stAxis.out.o_wsStatus := WSTRING#'DPRD_DAT错误';
16#8601:
#io_stAxis.out.o_wsStatus := WSTRING#'DPWR_DAT错误';
16#8202:
#io_stAxis.out.o_wsStatus := WSTRING#'不正确的运行模式选择';
16#8203:
#io_stAxis.out.o_wsStatus := WSTRING#'不正确的设定值参数';
16#8204:
#io_stAxis.out.o_wsStatus := WSTRING#'不正确的程序段号';
END_CASE;
IF #设定定位位置不合理 THEN
#io_stAxis.out.o_wsStatus := WSTRING#'设定定位位置不合理';
ELSIF #设定定位速度超过最大转速 THEN
#io_stAxis.out.o_wsStatus := WSTRING#'设定定位速度超过最大转速';
ELSIF #设定点动速度超过最大转速 THEN
#io_stAxis.out.o_wsStatus := WSTRING#'设定点动速度超过最大转速';
ELSIF #状态字1.%X9 THEN
#io_stAxis.out.o_wsStatus := WSTRING#'轴到达正极限';
ELSIF #状态字1.%X9 THEN
#io_stAxis.out.o_wsStatus := WSTRING#'轴到达负极限';
ELSIF #SinaPos_Instance.AxisError
AND NOT #状态=16#8401
AND NOT #状态=16#8402
AND NOT #状态=16#8403
AND NOT #状态=16#8600
AND NOT #状态=16#8601
AND NOT #状态=16#8602
AND NOT #状态=16#8203
AND NOT #状态=16#8204
THEN
#io_stAxis.out.o_wsStatus := WSTRING#'轴错误';
ELSIF #轴就绪 THEN
#io_stAxis.out.o_wsStatus := WSTRING#'轴就绪';
ELSIF (#状态字2.%X4 OR #状态字2.%X5) AND #SinaPos_Instance.EnableAxis AND NOT #io_stAxis.out.o_xError THEN
#io_stAxis.out.o_wsStatus := WSTRING#'轴在运动状态';
END_IF;
//解析状态字
#io_stAxis.out.o_xStandstill:= #轴就绪 := (NOT #状态字2.%X4
AND NOT #状态字2.%X5
AND NOT #io_stAxis.out.o_xError)
AND #SinaPos_Instance.EnableAxis;
#io_stAxis.out.o_xLimitP := #状态字1.%X9;
#io_stAxis.out.o_xLimitN := #状态字1.%X8;
#io_stAxis.out.o_xErrorID := #状态;
#定位完成 := #SinaPos_Instance.AxisPosOk
OR #定位完成;
#io_stAxis.out.o_xAxisError := #SinaPos_Instance.AxisError
OR #SinaPos_Instance.AxisWarn;
#io_stAxis.out.o_xError := #Error
OR #io_stAxis.out.o_xAxisError
OR #设定定位位置不合理
OR #设定定位速度超过最大转速
OR #设定点动速度超过最大转速;
(********************************************************** 位置到达信号输出**********************************************************)
//遍历当前位置大概在哪个工作位置,获取下标
FOR #i := 0 TO 19 DO
IF ABS(#io_stAxis.out.o_rActPosition - #io_stAxis.WorkPosition[#i].i_fPosition) < 0.5
AND NOT #状态字2.%X4
AND NOT #状态字2.%X5
THEN
#io_stAxis.out.o_axGetActPos[#i] := TRUE;
EXIT;
END_IF;
END_FOR;
//当轴再次开始运动时,把所有位置点完成信号都复位
IF #状态字2.%X4 OR #状态字2.%X5 THEN
#io_stAxis.out.o_xAbsDone := FALSE;
FOR #i := 0 TO 19 DO
#io_stAxis.out.o_axGetActPos[#i] := FALSE;
END_FOR;
END_IF;
END_FUNCTION_BLOCK
FB_Axis_newEpos_ST_2.scl |