TIA If Abfrage mit Boolschen Variablen

SanjaDO

Level-1
Beiträge
177
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute

ich habe heute ein Phänomen entdeckt was ich mir nicht erklären kann. Bisher habe ich eine IF abfrage folgendermaßen gestalltet:

Code:
VAR_INPUT
a:BOOL;
END_VAR

IF a THEN
 Anweisung;
END_IF;

Die hat auch immer funktioniert, wenn die Variable a=1 ist, ist die Abfrage "WAHR".

In meinem aktuellen Programm funktioniert das aber nur wenn ich auf a=1 abfrage....

Code:
VAR_INPUT
a:BOOL;
END_VAR

IF a=1 THEN
 Anweisung;
END_IF;

Hatte das Problem schon mal einer?

Ich habe das Programm auf einer 314CPU laufen

Danke
 
Strong Typed

Hallo Leute

ich habe heute ein Phänomen entdeckt was ich mir nicht erklären kann. Bisher habe ich eine IF abfrage folgendermaßen gestalltet:

Code:
VAR_INPUT
a:BOOL;
END_VAR

IF a THEN
 Anweisung;
END_IF;

Die hat auch immer funktioniert, wenn die Variable a=1 ist, ist die Abfrage "WAHR".

In meinem aktuellen Programm funktioniert das aber nur wenn ich auf a=1 abfrage....

Code:
VAR_INPUT
a:BOOL;
END_VAR

IF a=1 THEN
 Anweisung;
END_IF;

Hatte das Problem schon mal einer?

Ich habe das Programm auf einer 314CPU laufen

Danke

Ich habe keine Umgebung zum Testen aber ich würde immer auf True oder False testen. Der Stil, den Du da praktizierst, ist allerdings sehr üblich bei Programmierern, die die Sprache C mit der Muttermilch bekommen haben.

Übrigens, wenn es einen ELSE Zweig gibt, sollte man auf FALSE testen, das geht minimal vom Code schneller. Letzden Endes erzeugt der Compiler eine Subtraktion zwischen den beiden Werten und sieht nach, ob das Ergebnis = 0 ist.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
die Abfrage auf a vom Typ BOOL auf 1 ergibt m.E. nur deshalb ein TRUE weil der Compiler es gestattet. Wenn dann solltest du a auch auf TRUE (oder FALSE) abfragen.
In meiner bisherigen Welt (das ist allerdings S7-Classic) frage ich Boolsche Variablen auch nicht auf TRUE oder FALSE ab, da diese ja auch nur den Zustand haben können (ich code es also auch so, wie du es schreibst : IF a then ...).
Das du jetzt a auf seinen Inhalt prüfen mußt scheint mir eher ein TIA-Feature zu sein ...

Gruß
Larry
 
In meinem aktuellen Programm funktioniert das aber nur wenn ich auf a=1 abfrage....
Du meinst "IF a THEN" funktioniert nicht, Du mußt "IF a=1 THEN" schreiben?
Was meinst Du mit "funktioniert das aber nur ..." - meckert der SCL-Compiler oder funktioniert der Code auf der CPU nicht wie erwartet?
Mit welchem Aktualparameter wird a beim Aufruf versorgt?
Welche TIA-Version hast Du?


"IF ausdruck THEN" testet einen Ausdruck auf TRUE, dafür ist es absolut nicht nötig einen boolschen Ausdruck zusätzlich mit TRUE zu vergleichen.

Wenn Du für den Ausdruck einen Vergleich schreibst, dann müßtest Du statt "IF a=1 ..." eigentlich schreiben "IF a=TRUE ...", doch der Compiler verzeiht Dir und wandelt implizit die numerische 1 und 0 in boolsche TRUE und FALSE .

Harald
 
Ich habe keine Umgebung zum Testen aber ich würde immer auf True oder False testen. Der Stil, den Du da praktizierst, ist allerdings sehr üblich bei Programmierern, die die Sprache C mit der Muttermilch bekommen haben.

Naja so hat jeder seine Ansichten...

ich finde

Code:
IF a OR b OR NOT c THEN
übersichtlicher als

Code:
IF (a=true OR b=true OR c=false)=true THEN

aber das hat ja nichts mit dem Thema zu tun ;)

Wäre doch schon ein ziemlicher Bug. aber warten wir mal ab, welche Version der TE benutzt.

Gruß.
 
Der Compiler meckert nicht, die IF abfrage ist dann einfach nicht "true"! Ich habe sehr viele Programme so geschrieben die auch bis jetzt funktionieren. Nur das aktuelle Projekt nicht...
Da bin ich total überfragt warum es gerade in einer von 10 if schleifen nicht geht (im gleichen FB)....
 
du meinst "if a then" funktioniert nicht, du mußt "if a=1 then" schreiben?
Was meinst du mit "funktioniert das aber nur ..." - meckert der scl-compiler oder funktioniert der code auf der cpu nicht wie erwartet?
Mit welchem aktualparameter wird a beim aufruf versorgt?
Welche tia-version hast du?


"if ausdruck then" testet einen ausdruck auf true, dafür ist es absolut nicht nötig einen boolschen ausdruck zusätzlich mit true zu vergleichen.

Wenn du für den ausdruck einen vergleich schreibst, dann müßtest du statt "if a=1 ..." eigentlich schreiben "if a=true ...", doch der compiler verzeiht dir und wandelt implizit die numerische 1 und 0 in boolsche true und false .

Harald

tia v12, sp1
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn du noch Step7 zur Verfügung hast, kannst du dir ja mal den AWL Code ansehen den das TIA Portal generiert. Dazu öffnest du mit Step7 online den relevanten Baustein, der Editor schaltet dann auch AWL um und du kannst dir das Ergebnis ansehen.

Mit dem TIA-Portal geht das leider nicht mehr, das kann einem den Bausteincode nicht mehr anzeigen wenn die Bausteinsprache auf SCL steht und es die Quelle dazu nicht mehr hat. Eine einfache Variante des Knoff-Hoff-Schutzes für Tia-Trolle.

Ich habe mir mal mit V12 SP1 einen FC mit deinem Beispiel erstellt und den AWL Code angesehen. Mir ist da nichts fehlerhaftes aufgefallen.

Warum sollte man a=true schreiben müssen, wenn a vom Typ Bool ist?
Bei einer If-Anweisung muss die Bedingung den Datentyp Bool haben. Bei SCL gibt es keine implizite Datentypkonvertierung nach Bool (wie z.B. bei C).
Wenn a vom Datentyp Bool ist kann daran nichts falsch sein.

Wer hier IF a=True then.. schreibt, der müsste auch wenn er einem Ausgang einen Eingang zuweisen will anstatt
A0.0 := E0.0;
dann
A0.0 := E0.0 = true;
schreiben.
 
Übrigens, wenn es einen ELSE Zweig gibt, sollte man auf FALSE testen, das geht minimal vom Code schneller. Letzden Endes erzeugt der Compiler eine Subtraktion zwischen den beiden Werten und sieht nach, ob das Ergebnis = 0 ist.
Was höchstens für Architekturen gilt die keinen wirklichen Bit-Datentyp besitzen, und bei denen Bool = Int ist.
Wir sind hier aber bei Simatic S7, und da gibt es wirkliche Bitadressen. Also solche Spezialoptimierungen gleich wieder vergessen.
 
Wer hier IF a=True then.. schreibt, der müsste auch wenn er einem Ausgang einen Eingang zuweisen will anstatt
A0.0 := E0.0;
dann
A0.0 := E0.0 = true;
schreiben.
Konsequenterweise schreiben diejenigen eher so:
Code:
IF E0.0=TRUE THEN
  A0.0 := TRUE ;
ELSE
  A0.0 := FALSE ;
END_IF ;



Der Compiler meckert nicht, die IF abfrage ist dann einfach nicht "true"!
[...]
Da bin ich total überfragt warum es gerade in einer von 10 if schleifen nicht geht (im gleichen FB)....
Da solltest Du uns wohl doch mal den echten nicht funktionierenden Code zeigen. Dein Problem muß eine andere Ursache haben.

btw: "IF" ist keine Schleife

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
So! Mein Problem ist aber immer noch nicht geklärt. Hier der kompletter Code, Im Schritt 4 (SM[4]) ist das angesprochene Problem. Da musste ich "#fuellstand_erreicht=1" auf 1 prüfen, sonst geht das Programm nicht in diese Unterabfrage rein:

Code:
FUNCTION_BLOCK "Petri"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
   VAR_INPUT 
      fuellstand_erreicht : Bool;
      B2_abgesperrt : Bool;
      B2_entleert : Bool;
      entleerventile_geschlossen : Bool;
      B2_evakuiert : Bool;
      Ventlie_geschlossen : Bool;
      Anlage_entspannt : Bool;
      Anlage_entleert : Bool;
      Uebefuehrventil_WA_geoeffnet : Bool;
      Entleerventil_WA_geoeffnet : Bool;
      Produktion_start : Bool;
      Produktion_stop : Bool;
      Reinigung_start : Bool;
      Reinigung_stop : Bool;
      Reinigung_halt : Bool;
      Reinigung_weiter : Bool;
      Entleert : Bool;
      Evakuiert : Bool;
   END_VAR


   VAR_OUTPUT 
      SM : Array [0..20] of Bool;
   END_VAR


   VAR 
      Timer1 {OriginalPartName := 'TON'; VersionGUID := 'b966b86b-3345-49ba-8b4b-c930e1b67fde'} : TON;
      Timer2 {OriginalPartName := 'TON'; VersionGUID := 'b966b86b-3345-49ba-8b4b-c930e1b67fde'} : TON;
   END_VAR


   VAR_TEMP 
      index : Int;
   END_VAR




BEGIN
	
	
	IF "Wiederanlauf" THEN
	  #SM[0]:=1;
	  FOR #index := 1 TO 20 DO
	    #SM[#index]:=0;
	  END_FOR;
	  "Panel".Start_Produktion:=0;
	  "Panel".Start_Reinigung:=0;
	END_IF;
	
	#Timer1(IN:=#SM[0],PT:=T#20s);
	
	IF #SM[0] THEN
	  IF #Timer1.Q THEN
	    "Wiederanlauf":=0;
	    #SM[0]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[1] THEN
	  IF #Produktion_start THEN
	  #SM[1]:=0;
	  #SM[2]:=1;
	  ELSIF #Reinigung_start THEN
	  #SM[1]:=0;
	  #SM[15]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[2] THEN
	  IF #Entleert THEN
	    #SM[2]:=0;
	    #SM[3]:=1;
	  ELSIF #Produktion_stop THEN
	    #SM[2]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[3] THEN
	  IF #Evakuiert THEN
	    #SM[3]:=0;
	    #SM[4]:=1;
	  ELSIF #Produktion_stop THEN
	    #SM[3]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[4] THEN
	  IF #fuellstand_erreicht=1 THEN
	    #SM[4]:=0;
	    #SM[5]:=1;
	  ELSIF #Produktion_stop THEN
	    #SM[4]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[5] THEN
	  IF #B2_abgesperrt THEN
	    #SM[5]:=0;
	    #SM[6]:=1;
	  ELSIF #Produktion_stop THEN
	    #SM[5]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[6] THEN
	  IF #B2_entleert THEN
	    #SM[6]:=0;
	    #SM[7]:=1;
	  ELSIF #Produktion_stop THEN
	    #SM[6]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[7] THEN
	  IF #entleerventile_geschlossen THEN
	    #SM[7]:=0;
	    #SM[8]:=1;
	  ELSIF #Produktion_stop THEN
	    #SM[7]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[8] THEN
	  IF #B2_evakuiert THEN
	    #SM[8]:=0;
	    #SM[9]:=1;
	  ELSIF #Produktion_stop THEN
	    #SM[8]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[9] THEN
	  IF #Ventlie_geschlossen THEN
	    #SM[9]:=0;
	    #SM[10]:=1;
	  ELSIF #Produktion_stop THEN
	    #SM[9]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[10] THEN
	  IF #Anlage_entspannt THEN
	    #SM[10]:=0;
	    #SM[11]:=1;
	  ELSIF #Produktion_stop THEN
	    #SM[10]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[11] THEN
	  IF #Anlage_entleert THEN
	    #SM[11]:=0;
	    #SM[12]:=1;
	  ELSIF #Produktion_stop THEN
	    #SM[11]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[12] THEN
	  IF #Uebefuehrventil_WA_geoeffnet THEN
	    #SM[12]:=0;
	    #SM[13]:=1;
	  ELSIF #Produktion_stop THEN
	    #SM[12]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	IF #SM[13] THEN
	  IF #Entleerventil_WA_geoeffnet THEN
	    #SM[13]:=0;
	    #SM[2]:=1;
	  ELSIF #Produktion_stop THEN
	    #SM[13]:=0;
	    #SM[1]:=1;
	  END_IF;
	END_IF;
	
	
END_FUNCTION_BLOCK

Danke
 
Grundsätzlich müsste das funktionieren wenn du tatsächlich füllstand erreicht auf 1 hast.

Ist dir bewusst dass deine FOR Schleife nicht zwingend funktionieren muss?

mfG René
 
Auf einmal gehts wieder... Keine Ahnung was da passiert ist. Jetzt macht mir dieser Fehler noch mehr Angst weil ich den jetzt nicht reproduzieren kann. Warum funktioniert die for schleife nicht???
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Weil die Index Variable temporär ist und du diese nicht initialisierst.
Der Zustand einer Temporären Variable ist aus Sicht des Bausteins, zufällig.
Bin mir jetzt aber garnicht mehr sicher ob for die variable nicht selbst initialisiert?

mfG René
 
Zuletzt bearbeitet:
FOR enthält die Initialisierung der Index-/Schleifen-Variable auf einen Anfangswert:
Code:
	  FOR [COLOR="#0000FF"]#index := 1[/COLOR] TO 20 DO
	    #SM[#index]:=0;
	  END_FOR;

Harald
 
Code:
FUNCTION_BLOCK "Petri"
{ S7_Optimized_Access := 'FALSE' }
VERSION : 0.1
   VAR_INPUT 
      fuellstand_erreicht : Bool;
      B2_abgesperrt : Bool;
      B2_entleert : Bool;
      entleerventile_geschlossen : Bool;
      B2_evakuiert : Bool;
      Ventlie_geschlossen : Bool;
      Anlage_entspannt : Bool;
      Anlage_entleert : Bool;
      Uebefuehrventil_WA_geoeffnet : Bool;
      Entleerventil_WA_geoeffnet : Bool;
      Produktion_start : Bool;
      Produktion_stop : Bool;
      Reinigung_start : Bool;
      Reinigung_stop : Bool;
      Reinigung_halt : Bool;
      Reinigung_weiter : Bool;
      Entleert : Bool;
      Evakuiert : Bool;
   END_VAR


   VAR_OUTPUT 
      SM : Array [0..20] of Bool;
   END_VAR


   VAR 
      Timer1 {OriginalPartName := 'TON'; VersionGUID := 'b966b86b-3345-49ba-8b4b-c930e1b67fde'} : TON;
      Timer2 {OriginalPartName := 'TON'; VersionGUID := 'b966b86b-3345-49ba-8b4b-c930e1b67fde'} : TON;
   END_VAR


   VAR_TEMP 
      index : Int;
   END_VAR




BEGIN
    
    
    IF "Wiederanlauf" THEN
      #SM[0]:=1;
      FOR #index := 1 TO 20 DO
        #SM[#index]:=0;
      END_FOR;
      "Panel".Start_Produktion:=0;
      "Panel".Start_Reinigung:=0;
    END_IF;
    
    #Timer1(IN:=#SM[0],PT:=T#20s);
    
    IF #SM[0] THEN
      IF #Timer1.Q THEN
        "Wiederanlauf":=0;
        #SM[0]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    IF #SM[1] THEN
      IF #Produktion_start THEN
      #SM[1]:=0;
      #SM[2]:=1;
      ELSIF #Reinigung_start THEN
      #SM[1]:=0;
      #SM[15]:=1;
      END_IF;
    END_IF;
    
    IF #SM[2] THEN
      IF #Entleert THEN
        #SM[2]:=0;
        #SM[3]:=1;
      ELSIF #Produktion_stop THEN
        #SM[2]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    IF #SM[3] THEN
      IF #Evakuiert THEN
        #SM[3]:=0;
        #SM[4]:=1;
      ELSIF #Produktion_stop THEN
        #SM[3]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    IF #SM[4] THEN
      IF #fuellstand_erreicht=1 THEN
        #SM[4]:=0;
        #SM[5]:=1;
      ELSIF #Produktion_stop THEN
        #SM[4]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    IF #SM[5] THEN
      IF #B2_abgesperrt THEN
        #SM[5]:=0;
        #SM[6]:=1;
      ELSIF #Produktion_stop THEN
        #SM[5]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    IF #SM[6] THEN
      IF #B2_entleert THEN
        #SM[6]:=0;
        #SM[7]:=1;
      ELSIF #Produktion_stop THEN
        #SM[6]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    IF #SM[7] THEN
      IF #entleerventile_geschlossen THEN
        #SM[7]:=0;
        #SM[8]:=1;
      ELSIF #Produktion_stop THEN
        #SM[7]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    IF #SM[8] THEN
      IF #B2_evakuiert THEN
        #SM[8]:=0;
        #SM[9]:=1;
      ELSIF #Produktion_stop THEN
        #SM[8]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    IF #SM[9] THEN
      IF #Ventlie_geschlossen THEN
        #SM[9]:=0;
        #SM[10]:=1;
      ELSIF #Produktion_stop THEN
        #SM[9]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    IF #SM[10] THEN
      IF #Anlage_entspannt THEN
        #SM[10]:=0;
        #SM[11]:=1;
      ELSIF #Produktion_stop THEN
        #SM[10]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    IF #SM[11] THEN
      IF #Anlage_entleert THEN
        #SM[11]:=0;
        #SM[12]:=1;
      ELSIF #Produktion_stop THEN
        #SM[11]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    IF #SM[12] THEN
      IF #Uebefuehrventil_WA_geoeffnet THEN
        #SM[12]:=0;
        #SM[13]:=1;
      ELSIF #Produktion_stop THEN
        #SM[12]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    IF #SM[13] THEN
      IF #Entleerventil_WA_geoeffnet THEN
        #SM[13]:=0;
        #SM[2]:=1;
      ELSIF #Produktion_stop THEN
        #SM[13]:=0;
        #SM[1]:=1;
      END_IF;
    END_IF;
    
    
END_FUNCTION_BLOCK
Ich würde da an Deiner Stelle schon die Möglichkeiten von SCL nutzen, anstatt alles doppelt und dreifach zu schreiben.
Mal als (ungetestete S7 Classic-) Anregung:
Code:
FUNCTION_BLOCK "Petri"


VAR_INPUT
    Fuellstand_erreicht :           BOOL;
    B2_abgesperrt :                 BOOL;
    B2_entleert :                   BOOL;
    Entleerventile_geschlossen :    BOOL;
    B2_evakuiert :                  BOOL;
    Ventle_geschlossen :            BOOL;
    Anlage_entspannt :              BOOL;
    Anlage_entleert :               BOOL;
    Uebefuehrventil_WA_geoeffnet :  BOOL;
    Entleerventil_WA_geoeffnet :    BOOL;
    Produktion_Start :              BOOL;
    Produktion_Stop :               BOOL;
    Reinigung_Start :               BOOL;
    Reinigung_Stop :                BOOL;
    Reinigung_Halt :                BOOL;
    Reinigung_Weiter :              BOOL;
    Entleert :                      BOOL;
    Evakuiert :                     BOOL;
END_VAR

VAR_IN_OUT
    Wiederanlauf :                  BOOL;
    Start_Produktion :              INT; 
    Start_Reinigung :               INT; 
END_VAR

VAR_OUTPUT 
    SM :                            ARRAY [0..20] OF BOOL;
END_VAR

VAR
    Aktiver_Schritt :               INT;
    Anlauftimer :                   "TON";
    Timer2 :                        "TON";
END_VAR

VAR_TEMP 
    Naechster_Schritt :             INT;
    Index :                         INT;
END_VAR


    // Initialisierung
    IF Wiederanlauf THEN
        Aktiver_Schritt := 0;
    END_IF;
    
    // Schrittkette
    CASE Aktiver_Schritt OF
         0 : Start_Produktion := 0;
             Start_Reinigung  := 0;
             Wiederanlauf     := SEL(G:= Anlauftimer.Q,                IN1:= false, IN0:= true);
             Naechster_Schritt:= SEL(G:= Anlauftimer.Q,                IN1:=  1,    IN0:=  0);
         1 : Naechster_Schritt:= SEL(G:= Produktion_Start,             IN1:=  2,    IN0:= SEL(G:= Reinigung_Start, IN1:= 15, IN0:= 1));
         2 : Naechster_Schritt:= SEL(G:= Entleert,                     IN1:=  3,    IN0:=  2);
         3 : Naechster_Schritt:= SEL(G:= Evakuiert,                    IN1:=  4,    IN0:=  3);
         4 : Naechster_Schritt:= SEL(G:= Fuellstand_erreicht,          IN1:=  5,    IN0:=  4);
         5 : Naechster_Schritt:= SEL(G:= B2_abgesperrt,                IN1:=  6,    IN0:=  5);
         6 : Naechster_Schritt:= SEL(G:= B2_entleert,                  IN1:=  7,    IN0:=  6);
         7 : Naechster_Schritt:= SEL(G:= entleerventile_geschlossen,   IN1:=  8,    IN0:=  7);
         8 : Naechster_Schritt:= SEL(G:= B2_evakuiert,                 IN1:=  9,    IN0:=  8);
         9 : Naechster_Schritt:= SEL(G:= Ventle_geschlossen,           IN1:= 10,    IN0:=  9);
        10 : Naechster_Schritt:= SEL(G:= Anlage_entspannt,             IN1:= 11,    IN0:= 10);
        11 : Naechster_Schritt:= SEL(G:= Anlage_entleert,              IN1:= 12,    IN0:= 11);
        12 : Naechster_Schritt:= SEL(G:= Uebefuehrventil_WA_geoeffnet, IN1:= 13,    IN0:= 12);
        13 : Naechster_Schritt:= SEL(G:= Entleerventil_WA_geoeffnet,   IN1:=  2,    IN0:= 13);
        14 : Naechster_Schritt:= SEL(G:= true,                         IN1:= 15,    IN0:= 14);
        15 : Naechster_Schritt:= SEL(G:= true,                         IN1:= 16,    IN0:= 15);
        16 : Naechster_Schritt:= SEL(G:= true,                         IN1:= 17,    IN0:= 16);
        17 : Naechster_Schritt:= SEL(G:= true,                         IN1:= 18,    IN0:= 17);
        18 : Naechster_Schritt:= SEL(G:= true,                         IN1:= 19,    IN0:= 18);
        19 : Naechster_Schritt:= SEL(G:= true,                         IN1:= 20,    IN0:= 19);
        20 : Naechster_Schritt:= SEL(G:= true,                         IN1:=  1,    IN0:= 20);
    END_CASE;
    
    // Schrittweiterschaltung
    Aktiver_Schritt:= SEL(G:= Produktion_Stop AND NOT Wiederanlauf, IN1:= 1, IN0:= Naechster_Schritt);
    
    // Timer
    Anlauftimer(IN:= Wiederanlauf, PT:= T#20s);
    Timer2     (IN:= false,        PT:= T#1s);
        
    // Ausgabe
    FOR Index := 0 TO 20 BY 1 DO
        SM[Index]:= SEL(G:= Index = Aktiver_Schritt, IN1:= True, IN0:= False);
    END_FOR;

    
END_FUNCTION_BLOCK
 
Was mir noch aufgefallen ist...

Warum deklarierst Du "SM" als output?

Code:
VAR_OUTPUT
    SM : Array [0..20] of Bool;
END_VAR

Sofern Du den Schrittmerker nicht außerhalb brauchst, könntest daraus eine statische Variable machen.

Und wenn Du die Variable doch außerhalb brauchst, so sollte das als "VAR_IN_OUT" deklariert sein, da die Variable auch lesend verarbeitet wird.
 
Und dann stellt sich mir die viel grundsätzlichere Frage wieso den ganzen SM[..], obwohl sie vom Typ Bool sind, immer "0" oder "1" zugewiesen wird und nicht "False" oder "True". Dieser durch den Compiler hingenommene, hininterpretierte Stil funktioniert zwar (leider), aber sauber geht anders. Wer weiß, vielleicht steckte hier der Knoten im Compiler, dass "fuellstand_erreicht" auf "1" anstatt "True" geprüft werden musste - es gibt schließlich die unmöglichsten Fehler.
 
Zurück
Oben