FUNCTION_BLOCK "MZylinder"
TITLE = Zylinderansteuerung
{ S7_Optimized_Access := 'FALSE' }
AUTHOR : IBAE
FAMILY : Module
NAME : MZylinder
VERSION : 0.1
//SCL-Portierung des AWL-Bausteins FB92 "MZylinder" (verhaltensgleich).
//Schnittstelle und Instanzdaten (UDT "UZylinder") unveraendert.
   VAR_INPUT 
      Automatik : Bool;   // Automatikbetrieb ist aktiv
      Handbetrieb : Bool;   // Handbetrieb ist aktiv
      T_Ast : Int := 5;   // Zeit bis AST erreicht ist (*100ms)
      T_Gst : Int := 5;   // Zeit bis GST erreicht ist (*100ms)
   END_VAR

   VAR_OUTPUT 
      ZylAst : Bool;   // Vorwaerts-Ausgang des Antriebs
      ZylGst : Bool;   // Rueckwaerts-Ausgang des Antriebs
   END_VAR

   VAR 
      Stat : "UZylinder";
   END_VAR

   VAR_TEMP 
      tZeitNullen : Bool;   // AWL-Sprungziel "tdel": Zeitzelle nullen + Old_Ast nachfuehren
      tFehler : Bool;   // NW5: undefinierter Zustand / Befehl
      tFlanke : Bool;   // NW10: Flankenergebnis
   END_VAR


BEGIN
	   REGION NW1: Zeitwert loeschen
	       // Endstellung erreicht oder Fahrtrichtung hat gewechselt -> Zeit nullen
	       #tZeitNullen := (#ZylAst AND (#Stat.B_AST OR NOT #Stat.Old_Ast))
	                       OR (NOT #ZylAst AND (#Stat.B_GST OR #Stat.Old_Ast));
	   END_REGION
	
	   IF NOT #tZeitNullen THEN
	       REGION NW2: AST-Erreichtzeit abgelaufen ?
	           IF #Stat.T_AST_Akt = 9999 THEN
	               #Stat.T_AST_Akt := #T_Ast;   // Sollwert uebergeben (9999 = kein Zeitwert angegeben)
	           END_IF;
	
	           IF #ZylAst THEN   // Zylinder faehrt nach AST ?
	               #Stat.B_GST := FALSE;
	               IF #Stat.T_Zelle >= #Stat.T_AST_Akt THEN   // Gewollter Zeitwert erreicht ?
	                   #Stat.B_AST := TRUE;    // Zylinder hat AST erreicht
	                   #tZeitNullen := TRUE;   // AWL: JC tdel
	               END_IF;
	           ELSIF NOT #Stat.Typ5_3 THEN   // Zylinder haelt seine Stellung !
	               #Stat.B_AST := FALSE;
	           END_IF;
	       END_REGION
	   END_IF;
	
	   IF NOT #tZeitNullen THEN
	       REGION NW3: GST-Erreichtzeit abgelaufen ?
	           IF #Stat.T_GST_Akt = 9999 THEN
	               #Stat.T_GST_Akt := #T_Gst;   // Sollwert uebergeben (9999 = kein Zeitwert angegeben)
	           END_IF;
	
	           // Zylinder faehrt nach GST ? (2-fache Ansteuerung: ZylGst / 1-fache: ZylAst aus)
	           IF ((#Stat.Typ5_2 OR #Stat.Typ5_3) AND #ZylGst)
	              OR (#Stat.Typ3_2 AND NOT #ZylAst) THEN
	               #Stat.B_AST := FALSE;
	               IF #Stat.T_Zelle >= #Stat.T_GST_Akt THEN   // Gewollter Zeitwert erreicht ?
	                   #Stat.B_GST := TRUE;    // Zylinder hat GST erreicht
	                   #tZeitNullen := TRUE;   // AWL: JC tdel
	               END_IF;
	           ELSIF NOT #Stat.Typ5_3 THEN   // Zylinder haelt seine Stellung !
	               #Stat.B_GST := FALSE;
	           END_IF;
	       END_REGION
	   END_IF;
	
	   IF NOT #tZeitNullen THEN
	       REGION NW4: Zeit laeuft
	           // Nicht zaehlen, wenn 2-fach angesteuerter Zylinder gar nicht angesteuert wird;
	           // Zaehlung nur mit dem 100ms-Impuls
	           IF "100ms-Impuls"
	              AND NOT ((#Stat.Typ5_2 OR #Stat.Typ5_3) AND NOT #ZylGst AND NOT #ZylAst) THEN
	               #Stat.T_Zelle := #Stat.T_Zelle + WORD_TO_INT("MW2");   // 100ms-Takte
	           END_IF;
	       END_REGION
	   ELSE
	       // AWL-Sprungziel "tdel" (aus NW1/NW2/NW3)
	       #Stat.T_Zelle := 0;           // Zeitwert loeschen
	       #Stat.Old_Ast := #ZylAst;     // Fuhr letzten Zyklus nach AST
	   END_IF;
	
	   REGION NW5: Undefinierte Zustaende / Befehle
	       #tFehler := (#Automatik AND #Handbetrieb)                                    // Automatik + Hand aktiv
	                   OR (NOT #Automatik AND NOT #Handbetrieb)                         // keine Betriebsart
	                   OR (#Stat.Ast AND #Stat.Gst)                                     // AST- + GST-fahren gleichzeitig aktiv
	                   OR (NOT #Stat.Typ3_2 AND NOT #Stat.Typ5_2 AND NOT #Stat.Typ5_3)  // undefinierter Ventil-Typ
	                   OR (#Stat.Typ3_2 AND (#Stat.Typ5_2 OR #Stat.Typ5_3))             // mehrere Ventil-Typen
	                   OR (#Stat.Typ5_2 AND #Stat.Typ5_3);
	
	       IF #tFehler THEN   // Zylinderstellung bleibt eingefroren
	           IF #Stat.Typ5_3 THEN   // Zylinder haelt seine Stellung !
	               #Stat.Ast := FALSE;   // Bewegungsbits loeschen
	               #Stat.Gst := FALSE;
	           END_IF;
	           RETURN;   // AWL: BEU
	       END_IF;
	   END_REGION
	
	   REGION NW6: Zylinder auf Arbeitsstellung fahren
	       #ZylAst := #Stat.Ast;
	   END_REGION
	
	   REGION NW7: Zylinder auf Grundstellung fahren
	       #ZylGst := (#Stat.Typ5_2 OR #Stat.Typ5_3) AND #Stat.Gst;
	   END_REGION
	
	   REGION NW8: Daten, die zurueckgesetzt werden
	       IF #Stat.Typ5_3 THEN   // Zylinder haelt seine Stellung !
	           #Stat.Ast := FALSE;   // Bewegungsbits loeschen
	           #Stat.Gst := FALSE;
	       END_IF;
	       IF #Stat.Typ3_2 THEN
	           #Stat.Gst := FALSE;   // Es gibt kein GST fahren !
	       END_IF;
	   END_REGION
	
	   REGION NW9: Ausgaenge an OP uebergeben
	       #Stat.OP_Out_GST := #ZylGst;
	       #Stat.OP_Out_AST := #ZylAst;
	   END_REGION
	
	   REGION NW10: Statistik
	       // Positive Flanke ZylAst (AWL: FP Stat.FP_AST)
	       #tFlanke := #ZylAst AND NOT #Stat.FP_AST;
	       #Stat.FP_AST := #ZylAst;
	       IF #tFlanke THEN
	           #Stat.Statistik.AST_Schaltungen := #Stat.Statistik.AST_Schaltungen + 1;
	       END_IF;
	
	       // Positive Flanke ZylGst bei Typ5_3 (AWL: FP Stat.FP_AST2)
	       #tFlanke := #ZylGst AND #Stat.Typ5_3 AND NOT #Stat.FP_AST2;
	       #Stat.FP_AST2 := #ZylGst AND #Stat.Typ5_3;
	       IF #tFlanke THEN
	           #Stat.Statistik.AST2_Schaltungen := #Stat.Statistik.AST2_Schaltungen + 1;
	       END_IF;
	   END_REGION
END_FUNCTION_BLOCK

