Step 7 In AWL Date and Time mit Pointer im DB speichern.

tommylik

Level-2
Beiträge
115
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

Vor einiger Zeit habt Ihr mir in diesem Beitrag: https://www.sps-forum.de/simatic/87219-sfc1-austauschen-gegen-direktes-auslesen.html
geholfen mit SCL über ein Einangssignal 20 Zeiten (Date_andTime) in einem DB ab zu speichern.

Für eine Arbeits Erleichterung bräuchte ich fast das gleiche aber in AWL.

Dieses Mal habe ich mehrere Eingangssignale, die das abspeichern der Zeit in einem DB, anstossen sollen.
Der Global DB soll nun 100 Werte aufnehmen können und dann soll es wieder von vorne beginnen.
Die Zeit wird aus dem DB1 entnommen ab DBB20.

Ich habe genug erfahrung in KOP und FUP und alles was zu einer Inbetriebnahme gehört,
aber AWL und SCL da hört es leider bei mir auf.

Wer von Euch wäre bereit mir zu helfen.

Vielen Dank im voraus.

Mfg Tommylik












 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Harald,

Vielen Dank für deine Antwort und für den Link. (Schäm in Grund und Boden)
Ich habe leider nur in Google gesucht und mit den falschen Wörtern.

Nochmals Danke ich melde mich wenn es funktioniert.

Mfg Tommylik
 
Hallo Harald,

Ich habe eine fast funktionierende abgespeckte Variante erstellt. Habe aber das Problem das der DB
in dem die Zeiten gespeichert werden, nur einmal koplett beschrieben wird. Der Indexzähler funktioniert
aber einwandfrei, es werden nur keine neuen Zeiten abgespeichert.

Ich denke ich habe etwas falsch gemacht aber ich weiß nicht wo.

Dann hätte ich noch 2 Fragen als erstes wie muss ich den FC10 abändern wenn ich das Date_and_Time schon in einem DB griffbereit habe.
Ich brauch mir im OB1 die Zeit nicht verfügbar machen. Dadurch brauche ich auch den DB1 nicht.

Und als zweites, ist es ein großer Aufwand den Code zu ändern, wenn der Schreibanstoss mit der P-Flanke anstatt am EN-Eingang über ein Input Signal geht.

Vielen Dank nochmal für deine Hilfe und Mühe.

Mfg Tommylik
 

Anhänge

  • Logbuch.zip
    4,8 MB · Aufrufe: 35
Zuletzt bearbeitet:
Hallo Tommylik

Ich habe eine fast funktionierende abgespeckte Variante erstellt. Habe aber das Problem das der DB
in dem die Zeiten gespeichert werden, nur einmal koplett beschrieben wird. Der Indexzähler funktioniert
aber einwandfrei, es werden nur keine neuen Zeiten abgespeichert.
Komisch, Dein hochgeladener FC10 funktioniert korrekt, da werden auch nach "DB voll" weitere Zeiten gespeichert: in Zeiten[18] - Zeiten[19] - Zeiten[0] - Zeiten[1] - ...
Sieht Dein getester FC anders aus?


wie muss ich den FC10 abändern wenn ich das Date_and_Time schon in einem DB griffbereit habe.
Schreib einfach im Netzwerk 1 an den SFC20 anstatt "DB1".OB1_DATE_TIME Deinen "griffbereiten" Date_and_Time (z.B. "MeinAndererDB".Mein_Date_Time)


ist es ein großer Aufwand den Code zu ändern, wenn der Schreibanstoss mit der P-Flanke anstatt am EN-Eingang über ein Input Signal geht.
Ist kein großer Aufwand:
- füge im FC einen Bool-Eingang hinzu
- frage den Eingang im ersten Netzwerk ab und verlasse den FC wenn der Eingang nicht True ist (also genau wie das was Du in meinem verlinkten Beispiel abgespeckt hast)
- falls Du denn FC in KOP aufrufen willst, dann sorge dafür daß ENO sinnvoll gesetzt wird

Code:
VAR_INPUT
  REQ : BOOL ; //LogEintrag erstellen bei True
END_VAR

BEGIN
NETWORK
TITLE =Jetzt Log-Eintrag erstellen?

      UN    #REQ;
      SAVE  ;      //BIE/ENO setzen
      BEB   ;

...

NETWORK
TITLE =BIE/ENO setzen
      SET   ;
      SAVE  ;

Harald
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Harald,

Komisch, Dein hochgeladener FC10 funktioniert korrekt, da werden auch nach "DB voll" weitere Zeiten gespeichert: in Zeiten[18] - Zeiten[19] - Zeiten[0] - Zeiten[1] - ...
Sieht Dein getester FC anders aus?

Ich habe den gleichen FC wie du.
Wie schaust du dir diese Zeiten Online an? Variablentabelle? Im DB10 ist es ja nicht möglich.

Var.JPG

So sieht das bei mir aus und seit einer halben Stunde sehe ich keinen Unterschied. Wie Festgefroren.

Ist kein großer Aufwand:
- füge im FC einen Bool-Eingang hinzu
- frage den Eingang im ersten Netzwerk ab und verlasse den FC wenn der Eingang nicht True ist (also genau wie das was Du in meinem verlinkten Beispiel abgespeckt hast)
- falls Du denn FC in KOP aufrufen willst, dann sorge dafür daß ENO sinnvoll gesetzt wird

Die Änderungen habe ich eingebracht. Funktioniert.

Jetzt habe ich noch die Frage ob ich den FC ohne weiteres in einem FB mehrmals aufrufen könnte. Als Multiinstanz.
Ich möchte nicht für jeden Typ einen FC anlegen. Es reicht schon das ich für jeden Typ einen DB
anlegen muss.

Vielen Dank für deine großartige Hilfe und Mühe.

Mfg Tommylik
 
Wie schaust du dir diese Zeiten Online an? Variablentabelle? Im DB10 ist es ja nicht möglich.
Einen DATE_AND_TIME kann man nicht im DB beobachten, man muß ihn in einer Variablentabelle beobachten.
Dazu ist es vorteilhaft, wenn man sich in der Step7-Hilfe mal den Aufbau des Datentyps DATE_AND_TIME anschaut.
In den ersten 4 Bytes liegt das Datum und die Stunde der Uhrzeit (jeweils im BCD-Format), da wird beim kurzen Test höchstwahrscheinlich immer das selbe drinstehen. Die letzten 4 Bytes enthalten Minuten, Sekunden und Millisekunden (im BCD-Format) - wenn Du diese 4 Bytes beobachtest, dann wirst Du die Unterschiede der Zeitstempel sehen. Außerdem könntest Du beim Beobachten die Werte im DB auf 0 schreiben (*) und würdest dann deutlich sehen, daß die Werte wieder überschrieben werden. Weil die DATE_AND_TIME-Komponenten im BCD-Format sind, ist ein Anzeigeformat als "ZEIT" relativ sinnfrei - wähle da mal besser "HEX"

(*) in der Variablenbeobachtungstabelle (VAT) den Cursor in die Zeile setzen und Strg+0 drücken (oder Rechtsmausklick ...)

Vorteilhaft zum Beobachten ist außerdem, wenn Du beim Aufruf des FC10 noch den 1s-Taktmerker M0.5 mit verknüpfst, dann brauchst Du nur M10.0 auf 1 setzen und der FC schreibt jede Sekunde einen neuen Eintrag.

Variablentabelle
Code:
DB10.DBW 0   | "Logbuch_TVL_NIO".LastIndex       | DEZ | 0
             |                                   |     |
DB10.DBD 2   | (  erste 4 Bytes von Zeiten[0] )  | HEX | DW#17092710
DB10.DBD 6   | ( letzte 4 Bytes von Zeiten[0] )  | HEX | DW#03561234
DB10.DBD 14  | ( letzte 4 Bytes von Zeiten[1] )  | HEX | DW#00000000
DB10.DBD 22  | ( letzte 4 Bytes von Zeiten[2] )  | HEX | DW#00000000
             |                                   |     |
DB10.DBD 142 | ( letzte 4 Bytes von Zeiten[17] ) | HEX | DW#00000000
DB10.DBD 150 | ( letzte 4 Bytes von Zeiten[18] ) | HEX | DW#00000000
DB10.DBD 158 | ( letzte 4 Bytes von Zeiten[19] ) | HEX | DW#00000000


Jetzt habe ich noch die Frage ob ich den FC ohne weiteres in einem FB mehrmals aufrufen könnte.
Ja klar. Siehe nochmals das von mir oben in #2 verlinkte Beispiel. Da wird der FC auch mehrmals aufgerufen - für jedes Ereignis ein eigener Aufruf.

Harald
 
Hallo Harald,

Vielen Dank für deine Hilfe und für die wertvollen Informationen.

Ich habe noch etwas nachgedacht über deine Antwort

Schreib einfach im Netzwerk 1 an den SFC20 anstatt "DB1".OB1_DATE_TIME Deinen "griffbereiten" Date_and_Time (z.B. "MeinAndererDB".Mein_Date_Time)

und habe den FC "Add_Log" so erweitert das ich den Date_and_Time als Input übergeben kann. Ich bin dabei über diesen Thread gestolpert.

https://www.sps-forum.de/simatic/45556-indirekte-versorgung-fc1-add-dt-time.html#post335117

Mein Problem ist jetzt das mein Ringpuffer nicht mehr funktioniert. Es wird einmal etwas in den DB eingetragen und dann passiert nichts mehr.
Der Index steht immer auf -1. Was habe ich falsch gemacht?

Vielen Dank für deine Hilfe und Mühe

Mfg Tommylik
 

Anhänge

  • Logbuch_3.zip
    4,8 MB · Aufrufe: 16
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Tommylik,

bitte poste Deinen Programmcode hier leserlich als AWL-Code oder als Anhang in Form einer txt-Datei mit AWL-Code (*) Es ist nicht sehr hilfreich, wenn Du hier die paar Programmzeilen als mehrere Megabyte großes Step7-Projekt hochlädst. Da muß man (bzw. ich) unbedingt einen PC mit Step7 zur Verfügung haben, die Datei umständlich downloaden und entpacken und Step7 starten, nur um Deinen Programmcode ansehen zu können.

(Hast Du Dich eigentlich noch nicht gewundert, warum die zip-Datei so riesig ist und was da für Dich unauffällig/unsichtbar vielleicht noch alles in der Datei enthalten ist?)

(*) den AWL-Code eines ganzen Bausteins oder mehrerer Bausteine kann man mit dem KOP/AWL/FUP-Editor erzeugen via "Datei > Quelle generieren" und dann die Quelle öffnen und den Text der Quelle in eine Textdatei kopieren.


habe den FC "Add_Log" so erweitert das ich den Date_and_Time als Input übergeben kann. [...]
Mein Problem ist jetzt das mein Ringpuffer nicht mehr funktioniert. Es wird einmal etwas in den DB eingetragen und dann passiert nichts mehr.
Der Index steht immer auf -1. Was habe ich falsch gemacht?
Du hast nun auch den Index über die FC-Schnittstelle als Input übergeben.
Wenn man in einem FC den Wert einer als Übergabeparameter übergebenen Variable ändern will (lesen + ändern + zurückschreiben!), dann muß die Variable als VAR_IN_OUT übergeben werden und nicht als VAR_IN. Auf einen Input zurückschreiben funktioniert nicht. (Alternative: die Variable per Pointer übergeben)

Harald
 
Dein FC mit den neuen Übergabeparametern und aufgeräumt könnte nun so aussehen:
Code:
FUNCTION "Add_Log_2" : VOID
TITLE =Zeitstempel in ein Ringpuffer-Logbuch schreiben
VERSION : 0.1

VAR_INPUT
  REQ : BOOL ;                 //bei TRUE Logbuch-Eintrag erstellen
  TimeStamp : DATE_AND_TIME ;  //Zeitstempel für den Logbuch-Eintrag
  LogDB : BLOCK_DB ;           //DB mit dem Logbuch-Ringpuffer
END_VAR
VAR_IN_OUT
  LastIndex : INT ;            //Index des zuletzt beschriebenen Arrayplatzes
END_VAR
VAR_TEMP
  DB_No : INT ;
  tmpTS : DATE_AND_TIME ;
END_VAR
BEGIN
NETWORK
TITLE =BIE/ENO auf True setzen
//der FC-ENO soll immer True sein
      SET   ;
      SAVE  ;
NETWORK
TITLE =Jetzt neuen Logbuch-Eintrag erstellen?

      UN    #REQ;
      BEB   ;
NETWORK
TITLE =Logbucheintrag erstellen/ausfüllen - Zeitstempel kopieren
//DATE_AND_TIME (DT) wird bei FC als 6-Byte-POINTER übergeben und kann nicht 
//direkt weitergereicht werden. Deshalb von IN nach TEMP umkopieren.

//Pointer auf IN-Aktualparameter TimeStamp erstellen
      L     P##TimeStamp;      // Adresse IN.TimeStamp
      LAR1  ;
      L     W [AR1,P#0.0];     // POINTER.DB_Nr
      T     #DB_No;
      L     D [AR1,P#2.0];     // POINTER.Bereichsadresse
      LAR1  ;                  // AR1: Adresse des IN-DT
      LAR2  P##tmpTS;          // AR2: Adresse des TEMP-DT

//DATE_AND_TIME (8 Byte) von IN.TimeStamp nach TEMP.tmpTS kopieren
      AUF   DB [#DB_No];
      L     D [AR1,P#0.0];
      T     LD [AR2,P#0.0];
      L     D [AR1,P#4.0];
      T     LD [AR2,P#4.0];

NETWORK
TITLE =Logbuch-Eintrag in Logbuch kopieren

//Schreibzeiger auf nächsten Eintrag im Logbuch-Array stellen
      L     #LastIndex;        //Index des zuletzt geschriebenen Eintrags
      +     1;                 //nächster Eintrag
      L     20;                //Anzahl Einträge im Logbuch-Array
      MOD   ;                  //Ringpuffer: Array-Ende mit Array-Anfang verbinden
      T     #LastIndex;        //neuer Wert des Schreibzeigers merken (0..19)

//Zielpointer:
      L     #LastIndex;        //Schreibzeiger jetzt (0..19)
      L     8;                 //Größe eines Logbucheintrags in Bytes
      *I    ;                  //--> Anzahl Bytes vom Anfang des Arrays
      SLD   3;                 //wandeln in Bitadresse --> P#x.0
      L     P#DBX 2.0;         //Anfangsadresse des Logbuch-Arrays im DB (+2.0)
      +D    ;                  //dazu --> Anfangsadresse des Eintrags im DB
      LAR2  ;                  //in AR2 (als Zielpointer) laden
      AUF   #LogDB;            //und Logbuch-DB öffnen

//Quellpointer:
      LAR1  P##tmpTS;

//TimeStamp in Logbuch kopieren (8 Bytes) von Adresse in AR1 nach Adresse in DBNO+AR2
      L     LD [AR1,P#0.0];    //von tmpTS Bytes 1..4
      T     DBD [AR2,P#0.0];   //in Logbuch-Array
      L     LD [AR1,P#4.0];    //von tmpTS Bytes 5..8
      T     DBD [AR2,P#4.0];   //in Logbuch-Array
END_FUNCTION

Harald
 
Hallo Harald,

Vielen Dank für deine tolle Unterstützung und Zeit. Sorry das ich dir die Arbeit erschwert habe. Kommt nicht mehr vor.

Programm habe ich getestet funktioniert bestens. Super Arbeit von dir.

Ich habe jetzt nun gesehen wie man einen Pointer erstellt. Mir fehlt aber immer noch der sogenannte Ahaa-Efekt
das ich sagen könnte ich weiß wirklich was da passiert.

Code:
//Zielpointer:
      L     #LastIndex;        //Schreibzeiger jetzt (0..19)
      L     8;                 //Größe eines Logbucheintrags in Bytes
      *I    ;                  //--> Anzahl Bytes vom Anfang des Arrays
      SLD   3;                 //wandeln in Bitadresse --> P#x.0
      L     P#DBX 2.0;         //Anfangsadresse des Logbuch-Arrays im DB (+2.0)
      +D    ;                  //dazu --> Anfangsadresse des Eintrags im DB
      LAR2  ;                  //in AR2 (als Zielpointer) laden
      AUF   #LogDB;            //und Logbuch-DB öffnen

Mein großes Problem ist der Schiebebefehl.

Diesen Thread habe ich mir schon angeschaut. Pointer Zeiger FIFO LIFO

Speziell das hier.
Wie genau wird aus der 30 > p#30.0 und warum ist es p#30.4 wenn ich eine 4 dazu lade und nicht p#34.0

Code:
Nun wollen wir auch noch die [COLOR=indigo][B]Bitadresse fexibel gestalten[/B][/COLOR].
Code:  
  L     30
  SLD   3
  LAR1                    // im ar1 steht p#30.0
  L     4
  +AR1                    // die 4 wird zum ar1 hinzuaddiert. im ar1 steht jetzt p#30.4
  U     E [AR1,P#0.0]     // fragt e30.4 ab
  L     EW [AR1,P#0.0]    [COLOR=red]// das würde die cpu in stop bringen, da es das ew30.4 nicht gibt.[/COLOR]
[COLOR=red]           // nur bei bitoperationen darf die bitadresse <>0 sein.[/COLOR]

Vielen Dank nochmal für alles.

Mfg Tommylik
 
Zurück
Oben