Step 7 CPU 315-2 DP: Fehler mit Zeitstempel "fangen"

Xaar

Level-1
Beiträge
70
Reaktionspunkte
3
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo!

Ich habe folgendes Problem: Bei uns ist seit fast 20 Jahren eine alte S7-300 (CPU 315-2 DP, eine 6ES7 315-2AF01-0AB0, Firmwarestand im Moment noch unbekannt) für die Steuerung von einigen Pumpen im Einsatz. Die Programmierung der Steuerung ist hinsichtlich des Steuerungsprogramms recht komplex, die Anlage sehr wichtig und darf nicht ausfallen. Das Steuerungsprogramm wurde seit vielen Jahren (so um 2004 rum vermutlich) nicht mehr angerührt.

Nun gibt es in der letzten Zeit das Phänomen, dass eine der Pumpen immer wieder "rausgeworfen" wird, ohne, dass im übergeordneten Leitsystem dauerhaft eine eindeutige Fehlermeldung ersichtlich ist. An der Anbindung im Leitsystem bzw. deren Meldesystem kann ich nichts ändern. Da diese Störung natürlich sehr schlecht nachzuverfolgen ist (scheinbar nur kurze "Wischer"), will ich eine Art "Fehlerfang-Baustein" bauen, bei dem ich alle mögliche Abschaltbedingungen überwache - und sobald eine davon eintritt einen Zähler ansteuern, der sich um 1 erhöht. Soweit dürfte das für mich als Nicht-Programmierer auch kein Problem sein.

Nun würde ich aber auch ganz gern zum Nachvollziehen, wann dieser Fehler aufgetreten ist, den Zeitstempel von diesem Zeitpunkt speichern. Meine Lösungsvariante wäre hier die Folgende:

Zur "Definition":

Zähler: Zählt die Anzahl der eingetretenen Fehler der jeweiligen Abschaltbedingung
Merkerbereich 1...10: Speicherbereich für den Zeitstempel

Programm-Ablauf:


  1. Zähler überprüfen, ob vor "Überlauf" (>= 255). Wenn vor Überlauf, dann auf "0" setzen und Überlauf-Bit setzen
  2. Fehler tritt auf.
  3. Zähler um 1 erhöhen.
  4. Bisher gespeicherte Zeitstempel in den nächsten Merkerbereich schieben (9 -> 10, 8 -> 9 ... 1 -> 2)
  5. Zeitstempel der Steuerung auslesen (SFC1) und in den Merkerbereich 1 schreiben.

Das Ganze habe ich mal versucht umzusetzen - siehe FC1.pdf im Anhang. Der Aufruf des FCs würde sich dann so darstellen, wie in der OB1.pdf im Anhang zu sehen (Symbol-Tabelle in der Symbole.pdf). Die Netzwerke 1 bis 6 sind für die Zähler-Geschichte da, die Netzwerke 7 bis 24 für die Zeitstempel-Schieberei und schließlich die Netzwerke 25 bis 27 für das Auslesen und abspeichern des jüngsten Zeitstempels.

Nun ist das ziemlich umfangreich, verbraucht doch Einiges an Merkern - und irgendwie erscheint's mir auch recht umständlich, gerade die Verschieberei mit den einzelnen Zeitstempel-Einträgen.

Ein wenig habe ich auch im Forum gestöbert und diesen Beitrag gefunden: http://www.sps-forum.de/simatic/72611-uhrzeit-bei-stoerung-aufzeichnen.html

Dort wird das Ganze mittels DB gelöst - nur habe ich DBs bisher nicht wirklich genutzt (nur als "Merker missbraucht"). Irgendwie komme ich nicht mit den DBs und der Pointer-Geschichte klar :confused: Speziell der Transfer der Daten in den DB kriege ich nicht hin. Ich habe mir testweise einen Global-DB mit 10 Datensätzen vom Typ DATE_AND_TIME angelegt, in die ich den ausgelesenen Zeitstempel schieben würde - aber selbst, wenn ich versuche da einen Datensatz anzugeben, krieg ich Fehlermeldungen. Scheinbar stimmt die Syntax nicht. Ich weiß aber auch nicht, wie ich da einen Datensatz vom Typ DATE_AND_TIME angeben kann.

Weiterhin würde ich ganz gern beim Aufruf des FC eine DB-Nummer angeben, in dem dann die Daten gespeichert werden. Das Verschieben der Daten (analog Pkt. 4 oben) sollte auch erfolgen, so dass die aktuellste Störung ganz oben steht (oder unten - wäre ja egal, solange es "sortiert" bleibt).

Und noch etwas "bewegt" mich: Wäre die Geschichte in einem FB ggf. besser aufgehoben? Aus meiner Berufsausbildung (schon über ein Jahrzehnt her) hab' ich irgendwie noch in Erinnerung, dass bei mehrfachen Aufrufen von FCs nach dem Ende des Aufrufs der genutzte Lokaldatenbereich von anderen Bausteinen überschrieben werden kann - bei FBs werden die Lokaldaten nach Ende des Aufrufs wohl im Instanz-DB gespeichert und beim nächsten Aufruf "wiederhergestellt". Es kann aber auch sein, dass ich mich hier irre... Ursächlich für diese Frage ist hier die Nutzung des Zählers - wie verhält es sich da mit den Zählerständen? Wenn ich den FC mehrfach (für zwei verschiedene Fehlerursachen bspw.) hintereinander aufrufe, kommen dann auch zwei verschiedene Zählerstände raus oder gibt's da Probleme, weil ich ja für beide Aufrufe den selben Zähler nutze? Wie sieht das mit einem FB aus? Oder muss ich generell verschiedene Zähler nutzen? Wie kann ich das dann mit einem FC/FB realisieren, das bei der wiederholten Nutzung ein anderer Zähler genutzt wird?

So viele Fragen... Ich hoffe, es ist nicht zu verwirrend geschrieben :confused: Eine Lösung in FUP wäre erstrebenswert, AWL würde notfalls aber auch gehen. SCL steht nicht zur Verfügung.

Besten Dank schonmal vorab für die Antworten! :)

Grüße, Xaar.
 

Anhänge

  • FC1.pdf
    18,9 KB · Aufrufe: 16
  • OB1.pdf
    8,3 KB · Aufrufe: 3
  • Symbole.pdf
    6,4 KB · Aufrufe: 3
Zuletzt bearbeitet:
Hallo Xaar,
Die Aufgabe vor die du hier gestellt bist sollte eigentlich
Recht einfach zu lösen sein. Wie Du schon selbst festgestellt
Hast würde sich ein FB anbieten da ja auch ein größerer
Speicherbedarf besteht. Deine anhänge konnte ich mir
Leider nicht ansehen da ich nicht am PC bin.
Hast Du die Möglichkeit scl einzusetzen, dann könnte man
Dir schnell was zusammenschreiben.

Aber noch eine andere Frage stellt sich mir, wie
Werden deinr Störungen gebildet. Sollte die Störung
Nicht so lange anstehen bis eine quittierung von der
Leitwarte kommt?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich bin gerade mit was ähnlichem beschäftigt.
An unserer Anlage sollen die Prüfergebnisse der letzten x Bauteile ausgewertet werden.
Im DB40 gibt es dafür 3 bool-Arrays für drei Prüfergebnisse und ein real-Array für einen Analogwert.
Das Stichwort hier heisst Ringspeicher.
Vielleicht hilfts dir ja.


Code:
   U     "1P".Abtastimpuls
      U(    
      L     "DB_Klappenfehler".Anzahl_Teile
      L     0
      >I    
      )     
      SPBN  mend
//Anzahl auszuwertender Teile maximal 32
      L     "DB_Klappenfehler".Anzahl_Teile
      L     32
      >I    
      SPBN  m110
      L     32
      T     "DB_Klappenfehler".Anzahl_Teile
m110: NOP   0
//Zeiger fuer Ringspeicher
      L     "DB_Klappenfehler".ptr_stat
      L     1
      +I    
      T     "DB_Klappenfehler".ptr_stat
      O(    
      L     "DB_Klappenfehler".ptr_stat
      L     "DB_Klappenfehler".Anzahl_Teile
      >=I   
      )     
      O(    
      L     "DB_Klappenfehler".ptr_stat
      L     0
      <I    
      )     
      SPBN  m111
      L     0
      T     "DB_Klappenfehler".ptr_stat
m111: NOP   0
//Zeiger auf das Bit ohne Offset
      L     "DB_Klappenfehler".ptr_stat
      L     P#0.1
      *D    
      T     #ptr_bit
//Zeiger im ersten Bit-Array
      L     #ptr_bit
      L     P#12.0
      +D    
      T     #ptr_arr_kont
//Zeiger im zweiten Array
      L     #ptr_bit
      L     P#16.0
      +D    
      T     #ptr_arr_zh
//Zeiger im zweiten Array
      L     #ptr_bit
      L     P#20.0
      +D    
      T     #ptr_arr_zt
//Zeiger im Array fuer Hoehenwerte
      L     "DB_Klappenfehler".ptr_stat
      L     P#4.0
      *D    
      L     P#24.0
      +D    
      T     #ptr_arr_mw
 
//erstmal alle Bits ruecksetzen
      AUF   "DB_Klappenfehler"
      SET   
      R     DBX [#ptr_arr_kont]
      R     DBX [#ptr_arr_zh]
      R     DBX [#ptr_arr_zt]
//Konurfehler im Array merken
      U     "1P".Konturfehler
      S     DBX [#ptr_arr_kont]
//Teil zu tief im Array merken
      U     "1_Messtaster_max"
      S     DBX [#ptr_arr_zh]
//Teil zu hoch im Array merken
      U     "1_Messtaster_min"
      S     DBX [#ptr_arr_zt]
//Hoehenwert im Array merken
      L     "Daten1ST".St1_von_Pruefung.St1.Pruefung.Messwert
      AUF   "DB_Klappenfehler"
      T     DBD [#ptr_arr_mw]
//Schleife - alle Arrays durchgehen zur Auswertung
      L     0
      T     #z_loop
      T     #anz_kont
      T     #anz_zh
      T     #anz_zt
      L     0.000000e+000
      T     #hoehe_summe
mlp:  L     #z_loop
      L     P#0.1
      *D    
      L     P#12.0
      +D    
      T     #ptr_arr_kont
      AUF   "DB_Klappenfehler"
      U     DBX [#ptr_arr_kont]
      SPBN  m112
      L     #anz_kont
      L     1
      +I    
      T     #anz_kont
m112: L     #z_loop
      L     P#0.1
      *D    
      L     P#16.0
      +D    
      T     #ptr_arr_zh
      AUF   "DB_Klappenfehler"
      U     DBX [#ptr_arr_zh]
      SPBN  m113
      L     #anz_zh
      L     1
      +I    
      T     #anz_zh
m113: L     #z_loop
      L     P#0.1
      *D    
      L     P#20.0
      +D    
      T     #ptr_arr_zt
      AUF   "DB_Klappenfehler"
      U     DBX [#ptr_arr_zt]
      SPBN  m114
      L     #anz_zt
      L     1
      +I    
      T     #anz_zt
m114: L     #z_loop                     //für Hoehe Durchschnitt
      L     P#4.0
      *D    
      L     P#24.0
      +D    
      T     #ptr_arr_mw
      AUF   "DB_Klappenfehler"
      L     DBD [#ptr_arr_mw]
      L     #hoehe_summe
      +R    
      T     #hoehe_summe

      L     #z_loop
      L     1
      +I    
      T     #z_loop
      L     "DB_Klappenfehler".Anzahl_Teile
      <I    
      SPB   mlp
//Schleife Ende
      L     #anz_kont
      T     "DB_Klappenfehler".Anz_Kontur
      L     #anz_zh
      T     "DB_Klappenfehler".Anz_zu_hoch
      L     #anz_zt
      T     "DB_Klappenfehler".Anz_zu_tief
//Mittelwert Hoehe berechnen
      L     "DB_Klappenfehler".Anzahl_Teile
      ITD   
      DTR   
      T     #teiler
      L     #hoehe_summe
      L     #teiler
      /R    
      T     "DB_Klappenfehler".Hoehe_Schnitt
 
mend: NOP   0
 
Hallo,
das kann wie du schon angedeutet hast so nicht funktioneren. Variablen die im Temp-Bereich deklariert sind, sind immer nur einen Zyklus gültig. Daher hast du im ersten Netzwerk schon einen Zufallswert im Zähler stehen. Die Verwendung einens Symboltabellen-Zählers im FC musst du auch vermeiden. Du kannst allerdings einen Zähler als In-Out deklarieren und dann bei jedem Aufruf des FCs einen anderen Zähler außen dranhängen. Ich würd allerdings eher einen FB machen und einen IEC Zähler als Multiinstanz verwenden.

So Z.B.

Der FB füllt jetzt zwar von oben nach unten an, weiß nicht ob das ein Problem ist
Anhang anzeigen FB1_Zeitstempel.pdf
Anhang anzeigen DB1_Zeitstempel.pdf

Edit: Ich hab grad gesehen das ich den Überlaub vergessen habe einzuprogrammieren....

Und zur Info: Auf den IN/OUT Zeitstempel_Any gehört das erste Arrayfeld des Zeitstempel DBs, also Zeitstempel-DB.Zeitstempel[1]
 
Zuletzt bearbeitet:
Hallo!

Danke für die Antworten! :)

@plc_typ: SCL steht nicht zur Verfügung - nur FUP oder AWL.

@urlaub + TP-Inc: Vielen Dank für die Beispiele. Auch wenn ich bei beiden Programmen nicht ganz durchsehe, so waren in den Teilen, die ich denke verstanden zu haben, einige Denkanstöße dabei. :)

Mittlerweile hab' ich noch etwas an dem Programm gedreht (um nicht zu sagen nochmal neu angefangen) - da gab's doch noch einige Unzulänglichkeiten hinsichtlich der Zuverlässigkeit. Gleich der erste simulierte Fehler nach dem Upload auf die Test-CPU (315-2AF03) brachte die CPU in den Stopp - da war ich mit dem verwendeten Merkerbereich deutlich über's Ziel hinaus geschossen. Mehr als bis zum M255.7 kann diese alte 315-2DP ja nicht.

Zwischendrin ist mir noch eine Idee gekommen, wie es umzusetzen ginge - mit Datenbaustein und trotzdem ohne, dass ich mit Pointern o. Ä. arbeiten muss. Ich habe das Ganze jetzt mal als FB neuerstellt (siehe Anlagen) - und nutze als Speicher einfach nur die STAT-Variablen im Instanz-DB. Außerdem nehme ich nun keinen Zähler sondern addiere einfach zur bisherigen Fehleranzahl eine "1" dazu, wenn wieder ein Fehler auftritt. Ist jetzt vielleicht nicht die eleganteste Lösung - aber für mich sollte es reichen. Die Anzahl an aufgetretenen Fehlern sowie die Zeitstempel sehe ich, wenn ich den Instanz-DB zum jeweiligen Aufruf betrachte. Eigentlich bräuchte ich die beiden OUT-Variablen auch gar nicht.

Klappt hier im Test bisher ohne Probleme - bei zwei Aufrufen (d. h. simulierten Fehlerursachen) des FBs (siehe OB1). Ach ja: Die beiden IEC-FCs (FC 6 bzw. FC 8 aus der Simatic-Bibliothek) habe ich nur umbenannt, weil es die FC-Nummern 6 und 8 im Programm der SPS schon gibt und die FCs dort was Anderes machen.

Gibt es vielleicht noch mögliche Problem- oder Fehlerquellen im Programm? Ich will ja nicht, dass die SPS aufgrund eines Fehlers in meinem Programm irgendwelchen Unfug anstellt - oder in Stopp geht.

Besten Dank sagt Xaar.
 

Anhänge

  • 2016-08-14_Symbole.pdf
    5,3 KB · Aufrufe: 7
  • 2016-08-14_OB1.pdf
    6,7 KB · Aufrufe: 7
  • 2016-08-14_FB150.pdf
    15 KB · Aufrufe: 11
Zurück
Oben