FUNCTION_BLOCK "FB_Tilt_TEST"
{ S7_Optimized_Access := 'TRUE' }
VERSION : 0.1
   VAR_INPUT 
      wInTilt { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Word;   // Eingangswert von Sensor
      xInClock : Bool;   // Frequenz für Mittelwert Ermittlung
      xInTiltActive : Bool;   // Aktiviert die Überwachung
      xInTiltAdjust : Bool;   // Es wird aktiv nachgeregelt
      stInSettings : Struct
         tDiff : Time := T#1000ms;   // Solange muss Abweichung bestehen damit nachgeregelt wird
         tZero : Time := T#1000ms;   // Solange muss ca. Null bestehen damit gestoppt wird
         nDiff : Int := 10;   // Abweichung > oder <  als nDiff? ---> Nachregeln
         nZeroOk : Int := 5;   // Bereich um Null in welchem nachregeln aufgehört wird
         xComp : Bool;   // Flanke um Kompensationswert einzustellen
         nTiltComp : Int := 0;   // Wert von User um Tilt zu kompensieren, +X um größer zu werden, -X um kleiner zu werden
      END_STRUCT;
   END_VAR

   VAR_OUTPUT 
      stOutTilt : Struct
         nTiltRaw { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;   // Neigungswert Raw in 1/100 Grad
         nTiltComp : Int;   // Neigungswert Raw in 1/100 Grad kompensiert durch User
         nTiltRawMed : Int;   // Neigung-Mittelswert Raw
         nTiltCompMed : Int;   // Neigungs-Mittelwert in 1/100 Grad kompensiert durch User
      END_STRUCT;
      xOutToHigh : Bool;   // Merker dass Winkel zu hoch
      xOutToLow : Bool;   // Merker dass Winkel zu niedrig
      xOutTeachNec : Bool;   // Teachen notwendig
   END_VAR

   VAR 
      nCountINT : Int;   // Zählt in eingestellter Frequenz hoch
      rTrigClock {InstructionName := 'R_TRIG'; LibVersion := '1.0'; S7_SetPoint := 'False'} : R_TRIG;   // Hochzählzeitpunkt
      nTilt { ExternalAccessible := 'False'; ExternalVisible := 'False'; ExternalWritable := 'False'} : Int;   // aktueller Wert mit welchem gerechnet wird
      nTiltMed : Int;   // errechneter Mittelwert
      nSum : Int;   // Summe für Mittelwert
   END_VAR
   VAR RETAIN
      nTiltComp : Int;   // Offset welcher zum Rohwert hinzugerechnet wird
   END_VAR
   VAR 
      tOnDiff {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME;   // Timer zum Feststellen der Abweichung
      tOnZero {InstructionName := 'TON_TIME'; LibVersion := '1.0'} : TON_TIME;   // Timer zum Feststellen ob wieder Null
   END_VAR
   VAR RETAIN
      xDiff : Bool;   // Abweichung vorhanden
      xZeroReached : Bool;   // Näherung ausreichend gegen Null
      xAimForZero : Bool;   // Merker dass nach Abweichung nun gegen Null gefahren wird
      xToHigh : Bool;   // Merker dass Winkel zu hoch
      xToLow : Bool;   // Merker dass Winkel zu niedrig
   END_VAR

   VAR CONSTANT 
      cMaxCount : Int := 10;
   END_VAR


BEGIN
	REGION Kompensationswert prüfen
	    IF #stInSettings.xComp THEN
	        IF #stInSettings.nTiltComp <> 0 AND (#stInSettings.nTiltComp < -1000 OR #stInSettings.nTiltComp > 1000) THEN
	            #nTiltComp := 0;
	        ELSE
	            #nTiltComp := #stInSettings.nTiltComp;
	        END_IF;
	    END_IF;
	END_REGION
	
	REGION Rohwert umwandeln
	    #stOutTilt.#nTiltRaw := #nTilt := WORD_TO_INT(#wInTilt);
	    #stOutTilt.nTiltComp := #nTilt := #nTilt + #nTiltComp;
	END_REGION
	
	#rTrigClock(CLK:=#xInClock);
	
	REGION INT Berechnung Mittelwert
	    IF #rTrigClock.Q THEN
	        IF #nCountINT < #cMaxCount THEN
	            #nSum := #nSum + #nTilt;
	            #nCountINT := #nCountINT + 1;
	        ELSE
	            // Wenn die maximale Anzahl erreicht ist, den ältesten Wert abziehen
	            #nSum := #nSum - (#nSum / #nCountINT);
	            #nCountINT := 1;
	        END_IF;
	        
	        // Mittelwert berechnen
	        IF #nCountINT = 1 THEN
	            (* #stOutTilt.nTiltRawMed *) #stOutTilt.nTiltCompMed := #nTiltMed := (#nSum / #nCountINT) / 10;
	            #nSum := 0;
	        ELSE
	            (* #stOutTilt.nTiltRawMed *) #stOutTilt.nTiltCompMed := #nTiltMed;
	        END_IF;
	    END_IF;
	END_REGION
	
	REGION Abweichung feststellen
	    IF #xInTiltActive THEN
	        
	        REGION aktuell Abweichung?
	            IF #nTiltMed > #stInSettings.nDiff OR #nTiltMed < ( - #stInSettings.nDiff) THEN
	                #xDiff := TRUE;
	            ELSE
	                #xDiff := FALSE;
	            END_IF;
	        END_REGION
	        
	        REGION Merken in welche Richtung
	            IF #tOnDiff.Q AND #nTiltMed > #stInSettings.nDiff THEN
	                #xAimForZero := TRUE;
	                #xToHigh := TRUE;
	                #xToLow := FALSE;
	            ELSIF #tOnDiff.Q AND #nTiltMed < ( - #stInSettings.nDiff) THEN
	                #xAimForZero := TRUE;
	                #xToHigh := FALSE;
	                #xToLow := TRUE;
	            ELSE
	                #xAimForZero := FALSE;
	                #xToHigh := FALSE;
	                #xToLow := FALSE;
	            END_IF;
	        END_REGION
	        
	    ELSIF NOT #xInTiltActive OR #tOnZero.Q THEN
	        //nicht mehr aktiv
	        #xDiff := FALSE;
	        #xAimForZero := FALSE;
	        #xToHigh := FALSE;
	        #xToLow := FALSE;
	        // #xZeroReached := FALSE;
	    END_IF;
	    
	END_REGION
	
	REGION Nachregeln prüfen
	    IF #xInTiltAdjust AND #xAimForZero THEN
	        IF #nTiltMed < #stInSettings.nZeroOk AND #nTiltMed > (- #stInSettings.nZeroOk) THEN
	            #xZeroReached := TRUE;
	        ELSE
	            #xZeroReached := FALSE;
	        END_IF;
	    END_IF;
	END_REGION
	
	REGION Timer
	    #tOnDiff(IN := #xDiff,
	             PT := #stInSettings.tDiff);
	    #tOnZero(IN := #xZeroReached,
	             PT := #stInSettings.tZero);
	END_REGION
	
	REGION Ausgänge
	    #xOutToHigh := #xToHigh;
	    #xOutToLow := #xToLow;
	    #xOutTeachNec := #nTiltComp = 0;
	END_REGION
	(* // #rTilt := INT_TO_REAL(#nTilt);
	// #rOutTiltRaw := #rTilt := #rTilt / 100;
	// REGION REAL
	//     // Berechnung des Mittelwerts
	//     IF #rTrigClock.Q THEN
	//         IF #nCountREAL < #cMaxCount THEN
	//             #rSum := #rSum + #rTilt;
	//             #nCountREAL := #nCountREAL + 1;
	//         ELSE
	//             // Wenn die maximale Anzahl erreicht ist, den ältesten Wert abziehen
	//             #rSum := #rSum - (#rSum / INT_TO_REAL(#nCountREAL));
	//             #nCountREAL := 1;
	//         END_IF;
	        
	//         // Mittelwert berechnen
	//         IF #nCountREAL = 1 THEN
	//             #rOutTiltMed := #rTiltMed := (#rSum / INT_TO_REAL(#nCountREAL)) / 10.0;
	//             #rSum := 0.0;
	//         ELSE
	//             #rOutTiltMed := #rTiltMed;
	//         END_IF;
	//     END_IF;
	// END_REGION *)
	
END_FUNCTION_BLOCK

