FUNCTION_BLOCK "FB_EncoderMonitor"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      sInConveyorName : String[10];
      sInEncoderName : String[10];
      nInEncoderValue : DInt;   // Direkter Encoder Wert
      xInClock : Bool;   // Clock Eingang
      xInConveyorRun : Bool;   // Conveyor Full Speed
      xInQuit : Bool;   // Quittieren für Fehler
      xInActivate : Bool;   // true = Überwachung aktiv
      nInEncoderMax : DInt;
      nInEncMonVal : DInt;
   END_VAR

   VAR_OUTPUT 
      xOutError : Bool;   // Fehler Ausgang. Stoppt Conveyor
   END_VAR

   VAR_IN_OUT 
      stInOutControlUnitCabinet : "UDT_MainState";
   END_VAR

   VAR 
      rTrigClock {InstructionName := 'R_TRIG'; LibVersion := '1.0'} : R_TRIG;
   END_VAR
   VAR RETAIN
      nValue1 : DInt;   // 1. Wert für Differenz
      nValue2 : DInt;   // 2. Wert für Differenz
      nResult : DInt;   // Differenz der zwei Werte
      nStep : Int;   // Step in Schrittkette
      xError : Bool;   // Fehlerbit wenn Differenz zu klein
   END_VAR
   VAR 
      fbMonitoringEncoder { S7_SetPoint := 'False'} : "FB_Monitoring";
   END_VAR

   VAR_TEMP 
      xClock : Bool;   // Taktbit vom Clock
   END_VAR


BEGIN
	(*
	Überwachung für Pinband mit Encoder ohne sonstige Sensorik, nur anhand von Encoder-Werten. Encodereinstellung und Schwellwert werden mit den entspr. Konstanten vorgegeben
	Es wird im Clock-Takt ermittelt, ob sich bei laufendem Motor der Encoder-Wert wie gewünscht verändert.
	Bei jeder Taktflanke wird ein Encoderwert gespeichert und danach die Differenz gebildet. Ist diese unterhalb des gewünschten Schwellwertes, wird Fehler-Bit ausgegeben mit welchem
	der Motor gestoppt werden kann.
	*)
	
	REGION Takt
	    #rTrigClock(CLK := #xInClock AND #xInConveyorRun, //Beispiel: Clock_2Hz, um alle 500 ms einen Wert zu ermitteln, bei Ermittlung des 2. Wertes wird Berechnung durchgeführt
	                Q => #xClock);
	END_REGION
	
	IF #xInActivate THEN
	    IF #xInConveyorRun THEN //Startbedingung für Überwachung
	        
	        REGION Schrittkette
	            CASE #nStep OF
	                0:
	                    REGION 000: Init
	                        #nValue1 := 0;
	                        #nValue2 := 0;
	                        #xError := FALSE;
	                        #nResult := 0;
	                        #nStep := 1;
	                    END_REGION
	                    
	                1:
	                    REGION 001: Erster Wert
	                        IF #xClock THEN
	                            #nValue1 := #nInEncoderValue;
	                            #nStep := 2;
	                        END_IF;
	                    END_REGION
	                    
	                2:
	                    REGION 0002: Zweiter Wert
	                        IF #xClock THEN
	                            #nValue2 := #nInEncoderValue;
	                            REGION Berechnung
	                                #nResult := #nValue2 - #nValue1;
	                                IF #nResult < 0 THEN //Falls negativ wegen Überlauf von Encoder
	                                    #nResult := #nResult + #nInEncoderMax; //negatives Ergebnis + MaxWert von Encoder ergibt "normale" Differenz
	                                END_IF;
	                            END_REGION
	                            
	                            REGION Vergleich
	                                IF #nResult < #nInEncMonVal THEN //True deutet darauf hin dass Band sich nicht oder deutlich langsamer bewegt
	                                    #xError := TRUE;
	                                ELSE
	                                    #nStep := 1; //normal weiter
	                                END_IF;
	                            END_REGION
	                            
	                        END_IF;
	                    END_REGION
	                    
	                ELSE
	                    ;
	            END_CASE;
	        END_REGION
	        
	    ELSE
	        #nStep := 0;
	        
	    END_IF;
	ELSE
	    // #xError := FALSE;
	    #nStep := 0;
	END_IF;
	
	
	REGION Output
	    #xOutError := #xError AND #xInActivate;
	END_REGION
	
	REGION Quittieren
	    IF #xError AND #xInQuit AND #xInActivate THEN
	        #xError := FALSE;
	        #nStep := 0;
	    END_IF;
	END_REGION
	
	REGION Monitoring
	    #fbMonitoringEncoder.stSettings.nErrorType := 1;
	    #fbMonitoringEncoder.stSettings.xErrLedIfMachineIsOff := TRUE;
	    #fbMonitoringEncoder.stSettings.xSelfQuit := TRUE;
	    #fbMonitoringEncoder.stSettings.tDelay := T#1s;
	    #fbMonitoringEncoder(sInFctnName := 'Bandueberwachung Encoder',
	                         sInPrefix := #sInConveyorName,
	                         wInTextListId_Function := 2000,
	                         wInTextListId_Message := 2000,
	                         sInSuffix := #sInEncoderName,
	                         InOutMachineState := #stInOutControlUnitCabinet,
	                         xInQuitError := #stInOutControlUnitCabinet.xQuitError,
	                         xInSignal := NOT (#xError AND #xInActivate),
	                         sInAlarmMessage := 'Bandueberwachung ausgeloest');
	END_REGION
END_FUNCTION_BLOCK

