TIA Abbruchbedingung FOR- Schleife wird ignoriert

Zombie

Level-1
Beiträge
732
Reaktionspunkte
120
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi zusammen,

ich sitze heute abend im Hotel auf Inbetriebnahme und brüte gerade über den Fehlern des Tages.
Zu diesem hier kann ich mir absolut keinen Reim darauf machen.

Folgender Code erzeugt Längenfehler beim Arrayzugriff:
Code:
For siLaufvar = 1 to 120 Do
    If "dbTaghist".saTagval[siLaufvar] = 9999 Then
        siBadcount := siBadcount + 1;
    End_If;
End_For;
If siBadcount >= 3 Then
    //Fehler melden
    saSto[2] := TRUE;
End_If;
Im Instanzdatenbaustein kann man sehen, dass der Wert von siLaufvar auf 121 geht zu welchem Punkt die Steuerung Fehler meldet und die Bearbeitung des Bausteins stoppt.
Schreibe ich die Abbruchbedingung dagegen auf 119 fest, läuft es ganz normal durch und der Wert im Instanzdatenbaustein bleibt bei 120 stehen.

Folgende Frage lässt mir keine Ruhe, wieso bricht die For Schleife nicht wie gewollt bei 120 ab, sondern macht noch einen Durchlauf?
Bin ich einfach nur Übermüdet und sehe meinen Fehler nicht, oder ist da was Faul im Staate Dänemark?

Steuerungen sind 1214C AC/DC/RLY 1BG30 und 1BG31 alle mit V2.2, bzw eine mit V3.0. Alles Bestandssteuerungen des Kunden.
Programmiert wird mit TIA V15.0.

Danke
 
Das ist nicht ungewöhnlich. Die Schleife wird so lange ausgeführt wie die Laufvariable innerhalb deiner Grenzen ist. Bei 120 ist sie das noch, bei 121 nicht mehr. Darum ist die Laufvariable nach der Schleife um 1 größer wie der Wert deiner Abbruchbedingung, weil die Inkrement-Anweisung für die Laufvariable vor der Überprüfung auf die Grenze ausgeführt wird.

Wenn du meinst da ist ein Fehler, dann kannst du ja innerhalb der Schleife ein Merkerbit setzen, wenn der Index 120 überschreitet. Für solche Tests würde ich immer Merkervariablen verwenden, weil diese Zugriffe vermutlich nicht wegoptimiert werden.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich sitz auch im Hotel (IBN) und habs gerade mit PLC Sim probiert. Lege ich die Laufvariable in einem DB an ist der Beobachtungswert im DB 121. verwende ich eine temporäre Variable kann die CPU ohne OB121 nicht starten. Lädt und löscht man OB121 nun 🤔 und weist der DB-Variable in der Schleife die temporäre zu steht als Beobachtungswert 120... verwendet man wieder die DB-Variable als Laufvariable steht wieder 121... vlt hätt ich doch ein Bier weniger trinkem sollen... oder eins mehr

Edit: Oh, die Antwort steht ja schon da
 
Zuletzt bearbeitet:
Hi, danke für die Antworten.

Ich hab komplett vergessen zu schreiben dass saTagval ein Array of Int [1..120] ist.
Die For- Schleife soll ja bei 120 aufhören den inneren Teil abzuarbeiten. Dass sie dabei auf 121 geht leuchtet mir ein. Das ist mir aber gelinde gesagt Wurst. Das ist ja nicht das Problem, da ich die Variable nirgendwo sonst benötige. Deshalb kann sie auf egal welchen Wert steigen.
Ich bin mir aktuell (ohne eine CPU oder PLCSim hier zu haben) ziemlich sicher dass er versucht auf das 121 Element im Zielarray zuzgreifen, wo er doch eigentlich bei ereichen der 120 aufhören müsste die Bedingung in der For- Schleife abzuarbeiten. Anders kann ich mir das nicht erklären dass es keinen Zugriffsfehler gibt wenn die For- Schleife bei 119 aufhört.

Wenn ich das Array morgen auf 121 vergößere, ist vermutlich wieder alles in Butter.
Aber wieso?

Am Ende ist das wieder so eine Wechselwirkung zwischen zu neuer Programmierumgebung und zu alter Steuerungsfirmware.
Naja, Gute Nacht zusammen, ich brauch Schlaf.
 
Zuletzt bearbeitet:
Hi,

Ja, es ist definitiv die For- Schleife.
Ich hab sie heute morgen auskommentiert und der Fehler blieb weg. Zusätzlich habe ich dann nochmal die If- Bedingung innerhalb der Schleife entfernt und er kam ebenfalls nicht wieder.
Gleiches wenn man die Abbruchbedingung auf 119 stellt. Das Array im DB vergrößern hab ich wegen der reinitialsierung noch nicht gemacht.
Anscheinend funktioniert das doch anders wie gedacht.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Kann es sein, dass die [0] der Schleifenvariable das Problem verursacht.
Du schreibst ja: For SiLaufVar = 1 to 120
Da bräuchte es aber ein := um die Variable zu initialisieren...
Dein Array beginnt ja bei [1]
 
Hallo Zombie,

entspricht der Code in #1 wirklich dem Original? Kannst du den ganzen Baustein online stellen? Oder wenigstens den Anfang bis zur Fehlerstelle, einschließlich Variablendeklaration? Gibt es Bausteinparameter?


Gruß, Onkel
 
Das hier ist der Code, die Fehlerauswertung am Ende hab ich weggelassen

Code:
//Baustein soll eine Scannerhistorie verwalten
//Wird ein neuer Tag gelesen, wird dieser als String in den DB gespeichert
//Anhand des gespeicherten Scans kann nachverfolgt werden welcher Tag der vor dem NoScan gelesene war
IF #ixNeuScan AND NOT #sxScan THEN
    //Position im Speicher lesen
    #tiFüllstand := "dbTaghist".iFüllstand;
    //Grenzen kontrollieren
    IF #tiFüllstand < 1 OR #tiFüllstand > 120 THEN
        #tiFüllstand := 1;
    END_IF;
    //Eintrag anlegen
    "dbTaghist".saTagval[#tiFüllstand] := #iiRead;
    //Position auf nächsten SPeicher legen
    #tiFüllstand := #tiFüllstand + 1;
    //Speicherposition aktualisieren
    "dbTaghist".iFüllstand := #tiFüllstand;
ELSE
    ;//Platzhalter
END_IF;
//Scannerhistorie auslesen ob zu viele NoScans auftauchen
#siBadcount := 0;
FOR #siLaufvar := 1 TO 119 DO
    IF "dbTaghist".saTagval[#siLaufvar] = 9999 THEN
        #siBadcount := #siBadcount + 1;
    END_IF;
END_FOR;
IF #siBadcount >= 3 THEN
    //Fehler melden
    #saSto[2] := TRUE;
END_IF;
.
.
.
.
.
.
//Flanke zuweisen
sxScan := ixNeuScan;
Das ist die Variablendeklaration im FB
Code:
    Input
    ixNeuScan    Bool    false    Nicht remanent    True    True    True    False    
    iiRead    Int    0    Nicht remanent    True    True    True    False    
                                    
    Output                                
                                    
    InOut                                
                                    
    Static                                
    sxScan    Bool    false    Nicht remanent    True    True    True    False    
    siBadcount    Int    0    Nicht remanent    True    True    True    False    
    saSto    Array[1..16] of Bool        Nicht remanent    True    True    True    False    
    siLaufvar    Int    0    Nicht remanent    True    True    True    False    
                                    
    Temp                                
    tiFüllstand    Int
Und so sieht der DB aus
Code:
    iFüllstand    Int    0    False    True    True    True    False    
    saTagval    Array[1..120] of Int        False    True    True    True    False
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich hab hier gerade eine 1215 als Austauschsteuerung bekommen.
Die hat Firmware v3.0, damit funktioniert genau dieser Code, bei einer V2.2 kommt ein LängenZugriffsfehler.

Ich hoffe ihr könnt mir beweisen dass ich einem Geist hinterherjage, ich zweifel gerade an mir selbst und allem was ich bisher gemacht hab. :confused::confused:
 
Zuletzt bearbeitet:
Thomas hat Dir schon zweimal geschrieben wie Du in der Schleife auf einen fehlerhaften Wert der Laufvariable prüfst. Wenn diese Prüfung anschlägt, dann weißt Du daß Du einen Compilerfehler oder Firmwarefehler gefunden hast. Du könntest den Siemens Support fragen/informieren, allerdings bezweifle ich daß Siemens den Fehler wegen der alten CPU beseitigt...
EDIT: liegt wohl doch nicht an der CPU sondern eher am TIA V15... da besteht dann doch die Chance daß der eventuelle Fehler irgendwann beseitigt wird

Harald
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Dann war da ja noch was mit optimiert/nichtoptimiert. Wie sind denn deine Bausteine diesbezüglich gepolt? Vielleicht ist es dir möglich zu probieren, ob es hierbei unterschiedliche Verhalten gibt?

Ich hab hier gerade eine 1215 als Austauschsteuerung bekommen.
Die hat Firmware v3.0, damit funktioniert genau dieser Code, bei einer V2.2 kommt ein LängenZugriffsfehler. ..
An dieser Stelle kannst du den Fall eigentlich nur noch an Siemens übergeben. Ob es zwischen "optimiert" und "weniger optimiert" :ROFLMAO: Unterschiede gibt, wäre dennoch interessant.
 
Zuletzt bearbeitet:
Die Bausteine sind alle optimiert.

Muss ich dabei die Bausteine neu initialisieren oder die CPUs stoppen?
Falls ja, muss das bis zum nächsten Stillstand warten. Der ist in Gott weiß wievielen Wochen geplant. Ob vorher was unplanmäßiges reinkommt weiß ich aktuell nicht.
 
Zuletzt bearbeitet:
Ich habe nochmal deinen kompletten Code von oben in einer 1214 FW 2.2 und TIA V14 V1 getestet, funktioniert ohne Fehler.
An welche Stelle im Editor springt der Cursor denn wenn du im Diagnosepuffer bei dem Ereignis auf "Im Editor öffnen" klickst?

Wenn ich bei mir den Index in der For-Schleife bis 121 laufen lasse um einen Bereichslängenfehler zu provozieren, dann springt er auch direkt in die Zeile mit dem IF "dbTaghist".saTagval[#siLaufvar] ...
Außerdem wird im Diagnosepuffer auch die DB-Nummer vermerkt bei der der Bereichslängenfehler aufgetreten ist. Stimmt diese mit der Nummer des DBs von dbTaghist bei dir überein?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich hab hier gerade eine 1215 als Austauschsteuerung bekommen.
Die hat Firmware v3.0, damit funktioniert genau dieser Code, bei einer V2.2 kommt ein LängenZugriffsfehler.
Hast Du da auch in der Gerätekonfig die Version der CPU von V2.2 auf V3.0 geändert und alles komplett übersetzt oder einfach das für V2.2 compilierte Programm auf die V3.0-CPU geladen?

Harald
 
Ich habe nochmal deinen kompletten Code von oben in einer 1214 FW 2.2 und TIA V14 V1 getestet, funktioniert ohne Fehler.
An welche Stelle im Editor springt der Cursor denn wenn du im Diagnosepuffer bei dem Ereignis auf "Im Editor öffnen" klickst?
Ich bin mir sicher, dass ich genau so auf die For Schleife gekommen bin.

Wenn ich bei mir den Index in der For-Schleife bis 121 laufen lasse um einen Bereichslängenfehler zu provozieren, dann springt er auch direkt in die Zeile mit dem IF "dbTaghist".saTagval[#siLaufvar] ...
Außerdem wird im Diagnosepuffer auch die DB-Nummer vermerkt bei der der Bereichslängenfehler aufgetreten ist. Stimmt diese mit der Nummer des DBs von dbTaghist bei dir überein?
Auch da bin ich mir sicher.

Hast Du da auch in der Gerätekonfig die Version der CPU von V2.2 auf V3.0 geändert und alles komplett übersetzt oder einfach das für V2.2 compilierte Programm auf die V3.0-CPU geladen?

Hab ein komplett neues Projekt angelegt, gleich mit der richtigen CPU Version. Dann die Bausteine reinkopiert und komplett übersetzt. Nicht nur Änderungsübersetzen, komplett übersetzt.
 
Zuletzt bearbeitet:
Hier mal drei Screenshots aus dem Diagnosepuffer einer der Steuerungen.

https://picload.org/view/dlicgwow/bereichslaengenfehler.jpg.html
https://picload.org/view/dlicgwla/bereichslaengenfehler3.jpg.html
https://picload.org/view/dlicgwlr/bereichslaengenfehler2.jpg.html

FB45 ist der betreffende FB, DB62 der Datenspeicher.
Nicht wundern warum das nun anders heißt und anders funktioniert, dem Instandhaltungsleiter waren meine Bezeichnungen zu kryptisch, deshalb musste ich das alles umschreiben und auch das abspeichern des Integers war ihm nicht geheuer. Er wollte direkt den gelesenen Tag in einem Array of Char zur Verfügung haben.

An der Stelle ist das Thema dann für mich auch vorbei, denn die Funktion läuft ohne Probleme, weshalb ich da nicht noch mehr Zeit und Energie reinstecken kann. Und wie schon geschrieben wurde wird, bei der alten CPU, selbst wenn es ein Compilerfehler anstatt eines Computerfehlers sein sollte, vermutlich nichts mehr dran geändert, warum also anstrengen.
Bei den CPUs die schon gegen BG31 ausgetauscht wurden tritt der Fehler, ebenso wie bei den neuen mit V4.2, nicht auf.
 
Zurück
Oben