<?xml version="1.0" encoding="utf-8"?>
<TcPlcObject Version="1.1.0.1" ProductVersion="3.1.4024.13">
  <POU Name="FB_SeparatingModule" Id="{1cd6642c-70df-4ec5-93ae-b787415d2814}" SpecialFunc="None">
    <Declaration><![CDATA[// 分隔物料、输送物料的系统
FUNCTION_BLOCK FB_SeparatingModule EXTENDS FB_Subsystem_Root
VAR_INPUT
	// =============== Control the state and mode of machine ========================
	bExecute					: BOOL;							// 如果为TRUE，则该系统进入运行状态
	bSemiStart					: BOOL;							// 如果为TRUE，则将改系统切换至半自动状态
	
	// =============== Information about number of boxes being sorted ===============
	nBoxesOnTheWay				: INT;							// 当前输送皮带上的物料数量
	
	// =============== Cylinders buttons ============================================
	bButtonClampToWorkIn   AT%I*: BOOL;							// 将正位气缸移动到目标位置的按钮
	bButtonClampToBaseIn   		: BOOL;							// 将正位气缸移动到基始位置的按钮
	bButtonBarrierToWorkIn AT%I*: BOOL;							// 将栏杆气缸移动到基始位置的按钮
	bButtonBarrierToBaseIn 		: BOOL;							// 将栏杆气缸移动到基始位置的按钮
END_VAR
VAR_OUTPUT
	// =============== Process information ==========================================
	bSeparated					: BOOL;							// 如果为TRUE，则分割物料完成

	// =============== For movement simulation on visualization =====================
	bClampToWork				: BOOL;							// 如果为TRUE，则正位气缸往目标位置移动的信号为TRUE
	bBarrierToWork				: BOOL;							// 如果为TRUE，则栏杆气缸往目标位置移动的信号为TRUE
		
	// =============== Error variables ==============================================
	bClampError					: BOOL;							// 如果为TRUE，则正位气缸发生报错
	sClampErrorMsg				: STRING;						// 正位气缸的报错信息
	bBarrierError				: BOOL;							// 如果为TRUE，则栏杆气缸发生报错
	sBarrierErrorMsg			: STRING;						// 栏杆气缸的报错信息
	
	// =============== Temperature recordings =======================================
	aClampTemps					: ARRAY[1..100] OF LREAL;		// 正位气缸记录的温度数据
	aBarrierTemps				: ARRAY[1..100] OF LREAL;		// 栏杆气缸记录的温度数据
	
	// =============== Button return signals ========================================
	bButtonClampToWorkOut		: BOOL;							// 将正位气缸移动到目标位置的按钮信号经过信号处理功能块的输出
	bButtonClampToBaseOut		: BOOL;							// 将正位气缸移动到基始位置的按钮信号经过信号处理功能块的输出
	bButtonBarrierToWorkOut		: BOOL;							// 将栏杆气缸移动到目标位置的按钮信号经过信号处理功能块的输出
	bButtonBarrierToBaseOut		: BOOL;							// 将栏杆气缸移动到基始位置的按钮信号经过信号处理功能块的输出
END_VAR

VAR
	// =============== Function block instance of sensor ============================
	fbSensor					: FB_SignalHandling;			// 信号处理功能块
	
	// =============== Function block instances for clamp cylinder ==================
	fbClamp						: FB_Cylinder;					// 正位气缸对象
	
	// =============== Function block instances for barrier cylinder ================
	fbBarrier					: FB_Cylinder;					// 栏杆气缸对象
		
	// =============== Cylinder parameters for clamp and barrier ====================
	tTimeOutClamp				: TIME;							// 判定正位气缸为超时的设定时间
	tTimeOutBarrier				: TIME;							// 判定栏杆气缸为超时的设定时间
	tRecordIntervalClamp		: TIME;							// 记录正位气缸温度的时间
	tRecordIntervalBarrier		: TIME;							// 记录栏杆气缸温度的时间
	tBarrierAtWork				: TIME;							// 栏杆气缸打开的时间（目标位置）
	
	// =============== Manual cylinder control ======================================
	fbButtonClampToWork			: FB_SignalHandling;			// 处理正位气缸移动到目标位置的按钮信号功能块
	fbButtonClampToBase			: FB_SignalHandling;			// 处理正位气缸移动到基始位置的按钮信号功能块
	fbButtonBarrierToWork		: FB_SignalHandling;			// 处理栏杆气缸移动到目标位置的按钮信号功能块
	fbButtonBarrierToBase		: FB_SignalHandling;			// 处理栏杆气缸移动到基始位置的按钮信号功能块
	
	// =============== Common variables ==============================================
	fbTimerBarrierAtWork		: TON;							// 处理栏杆气缸打开延时的TON功能块
	eStateAuto					: E_StateSeparatingAuto;		// 自动流程的CASE变量
	eStateSemiAuto				: E_StateSeparatingAuto;		// 半自动流程的CASE变量
	fbTriggerSemiHalt           : R_TRIG;						// 半自动暂停信号的上升沿功能块
	
	BoxUndertheCylinderPosition	: BOOL;							// 如果为TRUE，则物料到达指定气缸的正下方（输送皮带暂停输送的标志位）
	rtBoxUndertheCylinderPosition: R_TRIG;						// 物料到达指定气缸的正下方的上升沿功能块
	
	CylinderWorkDone			: BOOL;							// 如果为TRUE，指定气缸到达目标位置（输送皮带回复输送的标志位）
	rtCylinderWorkDone			: R_TRIG;						// 物料到达指定气缸的正下方的上升沿功能块
	
	HaltRequestTemp				: BOOL;							// 临时暂停请求，用于确保在HaltDone之前继续执行暂停
END_VAR]]></Declaration>
    <Implementation>
      <ST><![CDATA[// =========================================================
;
// =========================================================]]></ST>
    </Implementation>
    <Method Name="Automatic" Id="{e59f27bb-af42-4ba1-a900-e76a3d37bc98}">
      <Declaration><![CDATA[METHOD Automatic
VAR_INPUT
END_VAR
]]></Declaration>
      <Implementation>
        <ST><![CDATA[// =========================================================
// 检测物料在气缸正下方、分拣系统气缸到目标位	
	rtBoxUndertheCylinderPosition(CLK:= BoxUndertheCylinderPosition);
	rtCylinderWorkDone			 (CLK:= CylinderWorkDone);
	
// 栏杆气缸延迟的TON功能块
	fbTimerBarrierAtWork		 (PT := tBarrierAtWork);

// =========================================================
// 输送皮带控制

// 检查 bHaltRequest（停机请求）是否为真，并且 HaltRequestTemp（临时停机请求）为假。如果条件成立，调用Halt方法。
    IF bHaltRequest THEN
		Halt(bHalt := TRUE);
			
// 其他情况下，轴一直转			
	ELSE		
		fbAxis.MoveFw();
		Halt(bHalt := FALSE);
	END_IF

// =========================================================
// 分割物料的过程
	
	CASE eStateAuto OF
		
		// ==========================初始化===============================
		E_StateSeparatingAuto.Init:
		
				// 确保栏杆气缸回到基始位
				fbBarrier.MoveToBase();
				
				// 栏杆气缸回到基始位完成之后且bExecute为TRUE之后，进入Start步
				IF fbBarrier.bState_AtBasePos AND bExecute THEN
					eStateAuto := E_StateSeparatingAuto.Start;
				END_IF
			
		// =========================================================
		E_StateSeparatingAuto.Start:
		
				// 如果输送带上的传感器检测到物料、且输送皮带在移动，进入到CloseClamp步
				IF fbSensor.bOut AND fbAxis.bMoves THEN
					eStateAuto := E_StateSeparatingAuto.CloseClamp;
				
				// 如果正位气缸没有到达目标位置、让气缸移动到目标位置，确保待输送的物料能移动到栏杆前
				ELSIF NOT fbClamp.bState_AtWorkPos THEN
					fbClamp.MoveToWork();
				END_IF
			
		// =========================================================
		E_StateSeparatingAuto.CloseClamp:
				
				// 检测到栏杆前已经存在物料了，将正位气缸移动到基始位置，固定后续的物料
				fbClamp.MoveToBase();
				
				// 如果正位气缸到达基始位置，也就是固定好物料之后，则bSeparated为TRUE，判定为物料分割完成，进入到OpenBarrier步
				IF fbClamp.bState_AtBasePos THEN
					bSeparated 	:= TRUE;
					eStateAuto 	:= E_StateSeparatingAuto.OpenBarrier;
				END_IF
			
		// =========================================================
		E_StateSeparatingAuto.OpenBarrier:
				
				// 将栏杆气缸移动到目标位，确保物料能够被运出
				fbBarrier.MoveToWork();			
				
				// 如果正位气缸到达目标位置、则将TON的IN置为TRUE
				IF fbBarrier.bState_AtWorkPos THEN
					fbTimerBarrierAtWork.IN := TRUE;
				END_IF
				
				// 到达设定时间之后，复位计时器，进入到CloseBarrier步
				IF fbTimerBarrierAtWork.Q THEN
					fbTimerBarrierAtWork.IN := FALSE;
					eStateAuto := E_StateSeparatingAuto.CloseBarrier;
				END_IF
			
		// =========================================================
		E_StateSeparatingAuto.CloseBarrier:
		
				// 将栏杆气缸移动到基始位置
				fbBarrier.MoveToBase();
				
				// 如果栏杆气缸到达基始位置，进入到OpenClamp步
				IF fbBarrier.bState_AtBasePos THEN
					bSeparated 	:= FALSE;
					eStateAuto	:= E_StateSeparatingAuto.OpenClamp;
				END_IF
			
		// =========================================================
		E_StateSeparatingAuto.OpenClamp:		
				// 将正位气缸移动到目标位置，让下一批物料推进
				fbClamp.MoveToWork();
				
				// 如果正位气缸到达目标位置，回到Init步
				IF fbClamp.bState_AtWorkPos THEN
					eStateAuto := E_StateSeparatingAuto.Init;
				END_IF
	END_CASE

// =========================================================]]></ST>
      </Implementation>
    </Method>
    <Property Name="bState_BarrierAtBasePos" Id="{c05d674a-ba50-4dc2-afb6-3819fdd8e436}">
      <Declaration><![CDATA[PROPERTY bState_BarrierAtBasePos : BOOL]]></Declaration>
      <Get Name="Get" Id="{bc1bc49c-c1e3-4b6e-b2a5-e35ca2c91762}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[bState_BarrierAtBasePos := fbBarrier.bState_AtBasePos;]]></ST>
        </Implementation>
      </Get>
    </Property>
    <Property Name="bState_BarrierAtWorkPos" Id="{fb3bd0c5-a792-4365-9c30-dfe9e6db17f0}">
      <Declaration><![CDATA[PROPERTY bState_BarrierAtWorkPos : BOOL]]></Declaration>
      <Get Name="Get" Id="{05f4413d-0836-4cc3-95ac-12c66e30269e}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[bState_BarrierAtWorkPos := fbBarrier.bState_AtWorkPos;]]></ST>
        </Implementation>
      </Get>
    </Property>
    <Property Name="bState_ClampAtBasePos" Id="{b94c1a5b-94d5-48ed-881c-de2bb2656d4d}">
      <Declaration><![CDATA[PROPERTY bState_ClampAtBasePos : BOOL]]></Declaration>
      <Get Name="Get" Id="{50340f67-32ab-4697-ad1c-8e51747928a2}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[bState_ClampAtBasePos := fbClamp.bState_AtBasePos;]]></ST>
        </Implementation>
      </Get>
    </Property>
    <Property Name="bState_ClampAtWorkPos" Id="{0f5bfbdb-ca98-4083-a7c8-fd24a0873d55}">
      <Declaration><![CDATA[PROPERTY bState_ClampAtWorkPos : BOOL]]></Declaration>
      <Get Name="Get" Id="{e2431b9a-0749-4bf5-b6ca-5eeb339fd7c1}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[bState_ClampAtWorkPos := fbClamp.bState_AtWorkPos;]]></ST>
        </Implementation>
      </Get>
    </Property>
    <Method Name="CylinderOptions" Id="{c2b1ed8f-dd11-41c7-a55d-122a3369494a}">
      <Declaration><![CDATA[METHOD CylinderOptions
VAR_INPUT
	bClampDiag			: BOOL;		// If true the clamp cylinder has diagnosis functionality
	bClampTemp			: BOOL;		// If true the clamp cylinder has temperature functionality
	bClampRecord		: BOOL;		// If true the clamp cylinder has recording functionality
	bBarrierDiag		: BOOL;		// If true the barrier cylinder has diagnosis functionality
	bBarrierTemp		: BOOL;		// If true the barrier cylinder has temperature functionality
	bBarrierRecord		: BOOL;		// If true the barrier cylinder has recording functionality
END_VAR
]]></Declaration>
      <Implementation>
        <ST><![CDATA[// =========================================================
// Selecting clamp cylinder

	// Checking variables to enable/disable diagnosis and temperature mode
	IF bClampDiag THEN
		IF bClampTemp THEN
			// ============== FB with diagnosis and temperature mode ==============
			bClampError 	:= fbClampTempDiag.bError;								// Assigning output variable of chosen FB to local output variable
			sClampErrorMsg 	:= fbClampTempDiag.sErrorMsg;
			fbClamp 		:= fbClampTempDiag;										// Assigning chosen FB instance to interface instance
		
		ELSE
			// ============== FB with diagnosis and without temperature mode ==============
			fbClampDiag.tTimeOut 	:= tTimeOutClamp;								// Setting special data for selected FB
			bClampError 			:= fbClampDiag.bError;							// Assigning output variable of chosen FB to local output variable	
			sClampErrorMsg 			:= fbClampDiag.sErrorMsg;
			fbClamp 				:= fbClampDiag;									// Assigning chosen FB instance to interface instance
		END_IF
	ELSE
		bClampError 	:= FALSE;
		sClampErrorMsg 	:= '';
		
		IF bClampTemp THEN
			IF bClampRecord THEN
				// ============== FB without diagnosis and with temperature recording ==============
				fbClampTempRecord.tIntervalTime	:= tRecordIntervalClamp;			// Time of record interval
				fbClampTempRecord.bRecordStart	:= bComprAirEnabledLocal;			// Recording if compressed air is set
				
				fbClampTempRecord.Record();											// Calling method of function block FB_CylinderTempRecord
				
				aClampTemps 	:= fbClampTempRecord.aTemps;						// Saving output variable
				fbClamp 		:= fbClampTempRecord;								// Assigning chosen FB instance to interface instance
			ELSE
				// ============== FB without diagnosis and with temperature mode, but without recording ==============
				fbClamp 		:= fbClampTemp;										// Assigning chosen FB instance to interface instance
			END_IF
		ELSE
			// ============== FB without diagnosis and without temperature mode ==============
			fbClamp := fbClamp;														// Assigning chosen FB instance to interface instance		
		END_IF	
	END_IF
									
// =========================================================
// Selecting barrier cylinder

	// Checking variables to enable/disable diagnosis and temperature mode
	IF bBarrierDiag THEN
		IF bBarrierTemp THEN
			// ============== FB with diagnosis and temperature mode ==============
			bBarrierError 		:= fbBarrierTempDiag.bError;						// Assigning output variable of chosen FB to local output variable
			sBarrierErrorMsg 	:= fbBarrierTempDiag.sErrorMsg;
			fbCylinder 			:= fbBarrierTempDiag;								// Assigning chosen FB instance to interface instance
		
		ELSE
			// ============== FB with diagnosis and without temperature mode ==============
			fbBarrierDiag.tTimeOut	:= tTimeOutBarrier;								// Setting special data for selected FB
			bBarrierError 			:= fbBarrierDiag.bError;						// Assigning output variable of chosen FB to local output variable
			sBarrierErrorMsg 		:= fbBarrierDiag.sErrorMsg;
			fbCylinder 				:= fbBarrierDiag;								// Assigning chosen FB instance to interface instance
		END_IF
	ELSE
		bBarrierError := FALSE;
		sBarrierErrorMsg := '';
		
		IF bBarrierTemp THEN
			IF bBarrierRecord THEN
				// ============== FB without diagnosis and with temperature recording ==============
				fbBarrierTempRecord.tIntervalTime 	:= tRecordIntervalBarrier;		// Time of record interval
				fbBarrierTempRecord.bRecordStart 	:= bComprAirEnabledLocal;		// Recording if compressed air is set
				
				fbBarrierTempRecord.Record();										// Calling method of function block FB_CylinderTempRecord
				
				aBarrierTemps 	:= fbBarrierTempRecord.aTemps;						// Saving output variable
				fbCylinder 		:= fbBarrierTempRecord;								// Assigning chosen FB instance to interface instance
			ELSE
				// ============== FB without diagnosis and with temperature mode, but without recording ==============
				fbCylinder 		:= fbBarrierTemp; 									// Assigning chosen FB instance to interface instance
			END_IF
		ELSE
			// ============== FB without diagnosis and without temperature mode ==============
			fbCylinder := fbBarrier;													// Assigning chosen FB instance to interface instance				
		END_IF	
	END_IF
									
// =========================================================]]></ST>
      </Implementation>
    </Method>
    <Method Name="Enable" Id="{be40bacc-343e-46a1-b18d-83b27ead23a9}">
      <Declaration><![CDATA[METHOD Enable
VAR_INPUT
	bComprAirEnabled		: BOOL;			// Enable of compressed air
	bAxisEnable				: BOOL;			// Enable of axis
	bSensorEnable			: BOOL;			// Enable of sensor
	bManualAxisEnable		: BOOL;			// Enable of manual axis control
END_VAR
]]></Declaration>
      <Implementation>
        <ST><![CDATA[// =========================================================
// Calling method Enable of base class FB_Module via 'SUPER^.'
		
	SUPER^.Enable(	bComprAirEnabled	:= bComprAirEnabled,
					bAxisEnable			:= bAxisEnable,
					bSensorEnable		:= bSensorEnable,
					bManualAxisEnable	:= bManualAxisEnable);

// =========================================================
// Sensor control
		
	fbSensor.Enable(bEnable := bSensorEnable);

// =========================================================
// Cylinder control (accessing property of FB via interfaces intances)
	
	// Clamp cylinder
	fbButtonClampToWork.Enable(bEnable := bManualCylinderEnable );		
	fbButtonClampToBase.Enable(bEnable := bManualCylinderEnable );
	
	
	// Barrier cylinder
	fbButtonBarrierToWork.Enable(bEnable := bManualCylinderEnable );
	fbButtonBarrierToBase.Enable(bEnable := bManualCylinderEnable );
	

// =========================================================]]></ST>
      </Implementation>
    </Method>
    <Method Name="InputOutput" Id="{8a244ee5-6546-4c44-9222-895835d438e8}">
      <Declaration><![CDATA[METHOD InputOutput
VAR_INPUT
END_VAR
]]></Declaration>
      <Implementation>
        <ST><![CDATA[// =========================================================
// Calling method SetOutput of base class FB_Module via 'SUPER^.'
		
	SUPER^.InputOutput();						

// =========================================================
// Sensor
		
	fbSensor.SetOutput();

// =========================================================
// Cylinder buttons
		
	fbButtonClampToWork.SetOutput();
	fbButtonClampToBase.SetOutput();
	fbButtonBarrierToWork.SetOutput();
	fbButtonBarrierToBase.SetOutput();

// =========================================================
// Output variables for cylinders
	
	// Accessing properties of selected FB via interface instances
	bClampToWork 	:= fbClamp.bState_MoveToWork;
	bBarrierToWork 	:= fbBarrier.bState_MoveToWork;

// =========================================================
// Buttons
    bButtonBarrierToBaseIn:= NOT bButtonBarrierToWorkIn;
	bButtonClampToBaseIn  := NOT bButtonClampToWorkIn;

    fbButtonBarrierToBase( bInput:= bButtonBarrierToBaseIn AND NOT bButtonBarrierToWorkIn, bOut=> bButtonBarrierToBaseOut );
    fbButtonBarrierToWork( bInput:= bButtonBarrierToWorkIn AND NOT bButtonBarrierToBaseIn, bOut=> bButtonBarrierToWorkOut );
    fbButtonClampToBase  ( bInput:= bButtonClampToBaseIn   AND NOT bButtonClampToWorkIn  , bOut=> bButtonClampToBaseOut   );
    fbButtonClampToWork  ( bInput:= bButtonClampToWorkIn   AND NOT bButtonClampToBaseIn  , bOut=> bButtonClampToWorkOut   );

// =========================================================]]></ST>
      </Implementation>
    </Method>
    <Method Name="Maintenance" Id="{af3bddc7-b4d8-4398-b628-b8a7df3887c3}">
      <Declaration><![CDATA[METHOD Maintenance
VAR_INPUT
END_VAR
]]></Declaration>
      <Implementation>
        <ST><![CDATA[// =========================================================
// Calling own method Manual of this class FB_SeparatingModule via 'THIS^.'
		
	THIS^.Manual();				

// =========================================================]]></ST>
      </Implementation>
    </Method>
    <Method Name="Manual" Id="{98177fb3-ae88-4ee2-961a-e7a4d47bece4}">
      <Declaration><![CDATA[METHOD Manual
VAR_INPUT
END_VAR
]]></Declaration>
      <Implementation>
        <ST><![CDATA[// =========================================================
// Calling method Manual of base class FB_Module via 'SUPER^.'
		
	SUPER^.Manual();							

// =========================================================
// Manual cylinder control (Calling methods of FBs via interface instances)
	
	// Clamp cylinder to work position
	IF fbButtonClampToWork.bOut THEN
		fbClamp.MoveToWork();
	// Clamp cylinder to base position
	ELSIF fbButtonClampToBase.bOut THEN
		fbClamp.MoveToBase();
	END_IF
	
	// Barrier cylinder to work position
	IF fbButtonBarrierToWork.bOut THEN
		fbBarrier.MoveToWork();
	// Barrier cylinder to base position
	ELSIF fbButtonBarrierToBase.bOut THEN
		fbBarrier.MoveToBase();
	END_IF

// =========================================================]]></ST>
      </Implementation>
    </Method>
    <Property Name="P_BoxUndertheCylinderPosition" Id="{5a9dd2de-7121-42c2-b074-eae28df7b7fa}">
      <Declaration><![CDATA[PROPERTY P_BoxUndertheCylinderPosition : BOOL]]></Declaration>
      <Get Name="Get" Id="{a108e363-5f49-4800-a908-e37db618ff8d}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[P_BoxUndertheCylinderPosition	:= BoxUndertheCylinderPosition;]]></ST>
        </Implementation>
      </Get>
      <Set Name="Set" Id="{1eefb432-685c-4e21-8e52-be0efc7af10a}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[BoxUndertheCylinderPosition	:= P_BoxUndertheCylinderPosition;]]></ST>
        </Implementation>
      </Set>
    </Property>
    <Property Name="P_CylinderWorkDone" Id="{63ad202d-ce50-4ad6-9625-91c0405bb436}">
      <Declaration><![CDATA[PROPERTY P_CylinderWorkDone : BOOL]]></Declaration>
      <Get Name="Get" Id="{5a9fd59b-6b20-4741-be8d-9cd0d84e4491}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[P_CylinderWorkDone	:= CylinderWorkDone;]]></ST>
        </Implementation>
      </Get>
      <Set Name="Set" Id="{c7deaa39-ef6f-4fca-9177-a2c44bc0ab38}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[CylinderWorkDone	:= P_CylinderWorkDone;]]></ST>
        </Implementation>
      </Set>
    </Property>
    <Method Name="Reset" Id="{9e207282-6346-44e9-aaeb-d1ec60a8a10a}">
      <Declaration><![CDATA[METHOD Reset
VAR_INPUT
	bReset		: BOOL;				// True if machine is in state RESETTING
END_VAR
]]></Declaration>
      <Implementation>
        <ST><![CDATA[// =========================================================
// Calling method Reset of base class FB_Module via 'SUPER^.'
		
	SUPER^.Reset(bReset := bReset);

// =========================================================
// Resetting cylinder and axis
	
	IF fbTriggerResetStart.Q THEN
		bSeparated := FALSE;
		HaltRequestTemp	:= FALSE;
		fbTimerBarrierAtWork(IN := FALSE);
		
		// Calling methods of FBs via interface instances
		fbClamp.Reset();
		fbBarrier.Reset();
	END_IF

// =========================================================]]></ST>
      </Implementation>
    </Method>
    <Method Name="ResetState" Id="{2fa3e8f4-fda4-4baa-8c06-ea392d8fd9a2}">
      <Declaration><![CDATA[METHOD PROTECTED ResetState
VAR_INPUT
END_VAR
]]></Declaration>
      <Implementation>
        <ST><![CDATA[// =========================================================

eStateAuto 		:= E_StateSeparatingAuto.Init;
eStateSemiAuto	:= E_StateSeparatingAuto.Init;
//eStateAxisAuto	:= E_StateSeparatingAxisAuto.Moving;

// =========================================================]]></ST>
      </Implementation>
    </Method>
    <Method Name="Semiautomatic" Id="{445d25ee-f4b9-4b0f-bf71-e6c5d1b48024}">
      <Declaration><![CDATA[METHOD Semiautomatic
VAR_INPUT
END_VAR
]]></Declaration>
      <Implementation>
        <ST><![CDATA[// =========================================================
// 检测物料在气缸正下方、分拣系统气缸到目标位	
	rtBoxUndertheCylinderPosition(CLK:= BoxUndertheCylinderPosition);
	rtCylinderWorkDone			 (CLK:= CylinderWorkDone);
	fbTimerBarrierAtWork		 (PT := tBarrierAtWork);

// =========================================================
// 输送皮带控制

// 检查 在运输过程当中物料的数量是否为0，并且流程步在初始化阶段。如果条件成立，调用Halt方法。    
    IF (nBoxesOnTheWay = 0) AND (eStateSemiAuto = E_StateSeparatingAuto.Init) THEN
		Halt(bHalt := TRUE);
		
// 检测到物料到达气缸正下方的上升沿，那么将HaltRequestTemp置为TRUE，并调用Halt方法
	ELSIF rtBoxUndertheCylinderPosition.Q THEN 
		HaltRequestTemp	:= TRUE;
		Halt(bHalt := TRUE);
		
// 如果停止没有完成，且HaltRequestTemp为TRUE，依然执行Halt方法，确保上一步执行完成
	ELSIF (NOT bHaltDone) AND HaltRequestTemp THEN
			Halt(bHalt := TRUE);
			IF bHaltDone THEN
				 HaltRequestTemp	:= FALSE;
			END_IF
			
// 其他情况下，轴一直转	
	ELSE	
		fbAxis.MoveFw();
		Halt(bHalt := FALSE);
	END_IF


// =========================================================
// 分割物料的过程
	
	CASE eStateSemiAuto OF
		// =========================================================
		E_StateSeparatingAuto.Init:
		
				// 确保栏杆气缸回到基始位
				fbBarrier.MoveToBase();
				
				// 栏杆气缸回到基始位完成之后且bExecute和bSemiStart（每一次半自动模式下按下的启动信号）都为TRUE之后，进入Start步
				IF fbBarrier.bState_AtBasePos AND bExecute AND bSemiStart THEN
					eStateSemiAuto := E_StateSeparatingAuto.Start;
				END_IF
			
		// =========================================================
		E_StateSeparatingAuto.Start:
		
				// 如果输送带上的传感器检测到物料、且输送皮带在移动，进入到CloseClamp步
				IF fbSensor.bOut THEN
					eStateSemiAuto := E_StateSeparatingAuto.CloseClamp;
					
				// 如果正位气缸没有到达目标位置、让气缸移动到目标位置，确保待输送的物料能移动到栏杆前	
				ELSIF NOT fbClamp.bState_AtWorkPos THEN
						fbClamp.MoveToWork();
				END_IF

			
		// =========================================================
		E_StateSeparatingAuto.CloseClamp:
		
				// 检测到栏杆前已经存在物料了，将正位气缸移动到基始位置，固定后续的物料
				fbClamp.MoveToBase();
				
				// 如果正位气缸到达基始位置，也就是固定好物料之后，则bSeparated为TRUE，判定为物料分割完成，进入到OpenBarrier步
				IF fbClamp.bState_AtBasePos THEN
					bSeparated 		:= TRUE;
					eStateSemiAuto 	:= E_StateSeparatingAuto.OpenBarrier;
				END_IF
			
		// =========================================================
		E_StateSeparatingAuto.OpenBarrier:
		
				// 将栏杆气缸移动到目标位，确保物料能够被运出
				fbBarrier.MoveToWork();
				
				// 如果正位气缸到达目标位置、则将TON的IN置为TRUE
				IF fbBarrier.bState_AtWorkPos THEN
					fbTimerBarrierAtWork.IN := TRUE ;
				END_IF
				
				// 到达设定时间之后，复位计时器，进入到CloseBarrier步
				IF fbTimerBarrierAtWork.Q THEN
					fbTimerBarrierAtWork.IN := FALSE ;
					eStateSemiAuto := E_StateSeparatingAuto.CloseBarrier;
				END_IF
			
		// =========================================================
		E_StateSeparatingAuto.CloseBarrier:
		
				/// 将栏杆气缸移动到基始位置
				fbBarrier.MoveToBase();
				
				// 如果栏杆气缸到达基始位置，进入到OpenClamp步
				IF fbBarrier.bState_AtBasePos THEN
					bSeparated 		:= FALSE;
					eStateSemiAuto 	:= E_StateSeparatingAuto.OpenClamp;
				END_IF
			
		// =========================================================
		E_StateSeparatingAuto.OpenClamp:
		
				// 将正位气缸移动到目标位置，让下一批物料推进
				fbClamp.MoveToWork();
				
				// 如果正位气缸到达目标位置，回到Init步
				IF fbClamp.bState_AtWorkPos THEN
					eStateSemiAuto := E_StateSeparatingAuto.Init;
				END_IF
	END_CASE

// =========================================================]]></ST>
      </Implementation>
    </Method>
    <Property Name="tBarrierAtWorkPos" Id="{e5502ac1-ccce-4794-a522-94c556a581df}">
      <Declaration><![CDATA[PROPERTY tBarrierAtWorkPos : TIME]]></Declaration>
      <Get Name="Get" Id="{244e63e8-eadd-4477-88c9-64902ad858c1}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[tBarrierAtWorkPos := tBarrierAtWork;]]></ST>
        </Implementation>
      </Get>
      <Set Name="Set" Id="{ac50d5fa-f0de-4ff2-8aa4-c10af97e66f8}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[tBarrierAtWork := tBarrierAtWorkPos;]]></ST>
        </Implementation>
      </Set>
    </Property>
    <Property Name="tRecordIntervalOfBarrier" Id="{bc72d55b-21ef-4b72-a724-ec5e11f643d1}">
      <Declaration><![CDATA[PROPERTY tRecordIntervalOfBarrier : TIME]]></Declaration>
      <Get Name="Get" Id="{8ee2624f-fd14-4092-a4ad-ae887f679966}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[tRecordIntervalOfBarrier := tRecordIntervalBarrier;]]></ST>
        </Implementation>
      </Get>
      <Set Name="Set" Id="{14928053-3bb4-4a6e-8fda-93d0d78b75ca}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[tRecordIntervalBarrier := tRecordIntervalOfBarrier;]]></ST>
        </Implementation>
      </Set>
    </Property>
    <Property Name="tRecordIntervalOfClamp" Id="{9d7be071-f1a3-42ad-8873-9df7964c7e9e}">
      <Declaration><![CDATA[PROPERTY tRecordIntervalOfClamp : TIME]]></Declaration>
      <Get Name="Get" Id="{61b1ca7e-5497-4e54-bffe-b401a28958ae}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[tRecordIntervalOfClamp := tRecordIntervalClamp;]]></ST>
        </Implementation>
      </Get>
      <Set Name="Set" Id="{b872381e-1612-406d-b4b7-d43f301db157}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[tRecordIntervalClamp := tRecordIntervalOfClamp;]]></ST>
        </Implementation>
      </Set>
    </Property>
    <Property Name="tTimeOutOfBarrier" Id="{ecdc6176-1693-494d-9085-f885339a571b}">
      <Declaration><![CDATA[PROPERTY tTimeOutOfBarrier : TIME]]></Declaration>
      <Get Name="Get" Id="{89086eb2-8824-4982-9765-9eae94dd67fc}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[tTimeOutOfBarrier := tTimeOutBarrier;]]></ST>
        </Implementation>
      </Get>
      <Set Name="Set" Id="{b70fc62a-0d18-4fa4-9bc6-eac8fad2e439}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[tTimeOutBarrier := tTimeOutOfBarrier;]]></ST>
        </Implementation>
      </Set>
    </Property>
    <Property Name="tTimeOutOfClamp" Id="{1be67291-ac48-4a42-8555-e58733a5a64d}">
      <Declaration><![CDATA[PROPERTY tTimeOutOfClamp : TIME]]></Declaration>
      <Get Name="Get" Id="{aabc126b-87e1-4a41-8430-8a3c55f4a922}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[tTimeOutOfClamp := tTimeOutClamp;]]></ST>
        </Implementation>
      </Get>
      <Set Name="Set" Id="{1c3b0045-83c9-47fd-89be-8b76f3b5a58a}">
        <Declaration><![CDATA[VAR
END_VAR
]]></Declaration>
        <Implementation>
          <ST><![CDATA[tTimeOutClamp := tTimeOutOfClamp;]]></ST>
        </Implementation>
      </Set>
    </Property>
    <LineIds Name="FB_SeparatingModule">
      <LineId Id="3" Count="1" />
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.Automatic">
      <LineId Id="3" Count="2" />
      <LineId Id="246" Count="0" />
      <LineId Id="256" Count="1" />
      <LineId Id="6" Count="3" />
      <LineId Id="258" Count="1" />
      <LineId Id="231" Count="1" />
      <LineId Id="264" Count="1" />
      <LineId Id="241" Count="0" />
      <LineId Id="243" Count="2" />
      <LineId Id="19" Count="0" />
      <LineId Id="21" Count="18" />
      <LineId Id="266" Count="0" />
      <LineId Id="40" Count="4" />
      <LineId Id="46" Count="10" />
      <LineId Id="226" Count="0" />
      <LineId Id="150" Count="0" />
      <LineId Id="59" Count="4" />
      <LineId Id="267" Count="0" />
      <LineId Id="251" Count="0" />
      <LineId Id="66" Count="5" />
      <LineId Id="268" Count="0" />
      <LineId Id="72" Count="18" />
      <LineId Id="92" Count="8" />
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.bState_BarrierAtBasePos.Get">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.bState_BarrierAtWorkPos.Get">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.bState_ClampAtBasePos.Get">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.bState_ClampAtWorkPos.Get">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.CylinderOptions">
      <LineId Id="3" Count="83" />
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.Enable">
      <LineId Id="3" Count="19" />
      <LineId Id="24" Count="4" />
      <LineId Id="30" Count="0" />
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.InputOutput">
      <LineId Id="3" Count="26" />
      <LineId Id="51" Count="1" />
      <LineId Id="43" Count="1" />
      <LineId Id="46" Count="1" />
      <LineId Id="45" Count="0" />
      <LineId Id="39" Count="0" />
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.Maintenance">
      <LineId Id="3" Count="4" />
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.Manual">
      <LineId Id="3" Count="23" />
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.P_BoxUndertheCylinderPosition.Get">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.P_BoxUndertheCylinderPosition.Set">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.P_CylinderWorkDone.Get">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.P_CylinderWorkDone.Set">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.Reset">
      <LineId Id="3" Count="17" />
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.ResetState">
      <LineId Id="3" Count="3" />
      <LineId Id="11" Count="0" />
      <LineId Id="7" Count="0" />
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.Semiautomatic">
      <LineId Id="3" Count="1" />
      <LineId Id="221" Count="0" />
      <LineId Id="5" Count="4" />
      <LineId Id="235" Count="0" />
      <LineId Id="132" Count="0" />
      <LineId Id="204" Count="1" />
      <LineId Id="236" Count="1" />
      <LineId Id="222" Count="0" />
      <LineId Id="227" Count="0" />
      <LineId Id="223" Count="0" />
      <LineId Id="238" Count="1" />
      <LineId Id="225" Count="1" />
      <LineId Id="229" Count="2" />
      <LineId Id="240" Count="1" />
      <LineId Id="214" Count="1" />
      <LineId Id="217" Count="0" />
      <LineId Id="216" Count="0" />
      <LineId Id="23" Count="19" />
      <LineId Id="242" Count="0" />
      <LineId Id="43" Count="1" />
      <LineId Id="243" Count="1" />
      <LineId Id="47" Count="0" />
      <LineId Id="49" Count="1" />
      <LineId Id="53" Count="23" />
      <LineId Id="245" Count="0" />
      <LineId Id="77" Count="29" />
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.tBarrierAtWorkPos.Get">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.tBarrierAtWorkPos.Set">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.tRecordIntervalOfBarrier.Get">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.tRecordIntervalOfBarrier.Set">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.tRecordIntervalOfClamp.Get">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.tRecordIntervalOfClamp.Set">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.tTimeOutOfBarrier.Get">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.tTimeOutOfBarrier.Set">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.tTimeOutOfClamp.Get">
      <LineId Id="2" Count="0" />
    </LineIds>
    <LineIds Name="FB_SeparatingModule.tTimeOutOfClamp.Set">
      <LineId Id="2" Count="0" />
    </LineIds>
  </POU>
</TcPlcObject>