FUNCTION_BLOCK "FB_StopperSimple"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      stInSensor : "UDT_Sensor";   // IN Sensor
      tInTrailing : Time := T#1500ms;   // Zeit wie lange ohne Belegung offen sein muss
   END_VAR
   VAR_INPUT RETAIN
      xInActive : Bool;   // Stopper aktiviert
   END_VAR
   VAR_INPUT 
      xInRelease : Bool;   // MT rauslassen
      xInReceive : Bool;   // MT aufnehmen
   END_VAR

   VAR_OUTPUT 
      nOutState : Int;   // Ausgang für aktuellen Schritt
      xOutStopper : Bool;   // MT Rauslassen
      xOutReleaseDone : Bool;   // Flanke dass MT rausgelassen
   END_VAR

   VAR RETAIN
      nState : Int;
   END_VAR
   VAR 
      fbStateManager : "FB_StateManager";
      tOnTrailing {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME;   // Timer für Öffnungszeit
   END_VAR
   VAR RETAIN
      nCountSensor { S7_SetPoint := 'True'} : Int;   // Flankenzähler vom eigenen Sensor
   END_VAR

   VAR_TEMP 
      tmpActUnivTon : Bool;
      xTmpOpenStopper : Bool;
      xTmpTrailing : Bool;
      xTmpReleaseDone : Bool;
   END_VAR

   VAR CONSTANT 
      cStepOff : Int := 0;
      cStepUndefined : Int := 100;
      cStepIdle : Int := 200;
      cStepReceive : Int := 300;
      cStepHold : Int := 400;
      cStepRelease : Int := 500;
      cStepWait : Int := 600;
   END_VAR


BEGIN
	REGION Count Sensor
	    //zählt Sensorflanken beim Ausfahren/Durchfahren vom In Sensor
	    IF #nState = #cStepRelease THEN
	        IF #stInSensor.xDirectEdgeNeg THEN
	            #nCountSensor += 1;
	        END_IF;
	    ELSE
	        #nCountSensor := 0;
	    END_IF;
	END_REGION
	
	REGION Schrittkette
	    CASE #nState OF
	        #cStepOff:
	            REGION 000: Off
	                #nOutState := #cStepOff;
	                
	                IF #xInActive THEN
	                    #xTmpOpenStopper := FALSE;
	                ELSE
	                    #xTmpOpenStopper := TRUE;
	                END_IF;
	                
	                
	            END_REGION
	            
	        #cStepUndefined:
	            REGION 100: Undefined
	                #nOutState := #cStepUndefined;
	                
	                IF #xInActive THEN
	                    #xTmpOpenStopper := FALSE;
	                ELSE
	                    #xTmpOpenStopper := TRUE;
	                END_IF;
	                
	                //////////////////////////////////////
	                
	                #nState := #cStepIdle;
	                
	            END_REGION
	            
	        #cStepIdle:
	            REGION 200: Idle
	                #nOutState := #cStepIdle;
	                
	                IF #xInActive THEN
	                    #xTmpOpenStopper := FALSE;
	                ELSE
	                    #xTmpOpenStopper := TRUE;
	                END_IF;
	                
	                ///////////////////////////////////////
	                
	                IF #xInReceive AND #xInActive THEN
	                    #nState := #cStepReceive;
	                END_IF;
	                
	            END_REGION
	            
	        #cStepReceive:
	            REGION 300: Receive
	                #nOutState := #cStepReceive;
	                
	                #xTmpOpenStopper := FALSE;
	                ///////////////////////////////////////
	                
	                IF #stInSensor.xDbncdSensor THEN
	                    #nState := #cStepHold;
	                END_IF;
	                
	            END_REGION
	            
	        #cStepHold:
	            REGION 400: Hold
	                #nOutState := #cStepHold;
	                
	                #xTmpOpenStopper := FALSE;
	                ///////////////////////////////////////
	                
	                IF NOT #stInSensor.xDirectSensor THEN
	                    #nState := #cStepReceive;
	                ELSIF #xInRelease AND #stInSensor.xDbncdSensor THEN
	                    #nState := #cStepRelease;
	                END_IF;
	                
	                
	            END_REGION
	            
	        #cStepRelease:
	            REGION 500: Release
	                #nOutState := #cStepRelease;
	                
	                #xTmpOpenStopper := TRUE;
	                ////////////////////////////////////
	                // IF NOT #stInSensor.xDbncdSensor THEN
	                //     #nState := #cStepWait;
	                // END_IF;
	                IF #nCountSensor >= 2 THEN
	                    #nState := #cStepWait;
	                END_IF;
	                
	            END_REGION
	            
	        #cStepWait:
	            REGION 600: Wait
	                #nOutState := #cStepWait;
	                
	                #xTmpOpenStopper := TRUE;
	                #xTmpTrailing := NOT #stInSensor.xDirectSensor;
	                ///////////////////////////////////////
	                
	                IF #tOnTrailing.Q THEN
	                    #xTmpOpenStopper := TRUE;
	                    #xTmpReleaseDone := TRUE;
	                    #nState := #cStepIdle;
	                END_IF;
	                
	            END_REGION
	            
	        ELSE  // Statement section ELSE
	            
	            
	            #nState := #cStepUndefined;
	    END_CASE;
	END_REGION
	
	REGION State Manager
	    #fbStateManager.stInSettings.nStartState := #cStepUndefined;
	    #fbStateManager.stInSettings.xActUnivTOn := TRUE;
	    #fbStateManager.stInSettings.xRestartAtStartState := FALSE;
	    #fbStateManager(xInFunctionEnabled := TRUE,
	                    xInRunUnivTOn := #tmpActUnivTon,
	                    nInOutState := #nState);
	END_REGION
	REGION Timer
	    #tOnTrailing(IN:=#xTmpTrailing,
	                 PT:=#tInTrailing);
	END_REGION
	
	REGION Ausgänge
	    #xOutStopper := #xTmpOpenStopper;
	    #xOutReleaseDone := #xTmpReleaseDone;
	END_REGION ;
END_FUNCTION_BLOCK

