Step 7 Mit Pointer in Ringregister schreiben

Zuviel Werbung?
-> Hier kostenlos registrieren
Kann es sein das dein '#Reset_Aktiv' nicht korrekt zurückgesetzt wird?
Ich denke eher, es liegt hier dran, das da nicht geladen, sondern transferiert wird:
Code:
[FONT=Courier New]...
// Register ggf. resetten
...
// Zeiger Ringpuffer initialisieren
      [COLOR="#FF0000"]T     #Schleifenindex[/COLOR]             // als Schleifenindex speichern
      T     "Register".Zeiger_Ringpuffer    // als Zeiger für Ringpuffer speichern
...   
[/FONT][/QUOTE]Wofür ich dann wohl verantwortlich bin:
[QUOTE="hucki, post: 454980, member: 17699"]...
Ungefähr so (ist aber immer noch [COLOR="#FF0000"]ungetestet, muss also nicht fehlerfrei[/COLOR] sein!):
[CODE][FONT=Courier New]...
// Zeiger Ringpuffer initialiesieren
      [COLOR="#FF0000"]T     #Schleifenindex[/COLOR]; // als Schleifenindex speichern
      T     #Zeiger_Ringpuffer; // als Zeiger für Ringpuffer speichern

// Pointer erstellen
      L     "Register".Zeiger_Ringpuffer    // Zeiger für Ringpuffer
      L     #DS_Laenge                  // Datensatzlänge
      *I 
...[/FONT]
...
:oops:




Ich würde so im Nachhinein auf den "Register".Zeiger_Ringpuffer ganz verzichten und nur mit dem Schleifenindex arbeiten:
Code:
[FONT=Courier New]...
// Register ggf. resetten
...
// Pointer erstellen
      L     #Schleifenindex             // Schleifenindex laden
      L     #DS_Laenge                  // Datensatzlänge
      *I
...[/FONT]
 
Jap, jetzt läuft der Kasten! Mal sehen was ich jetzt noch tolles an den Bausteinen ändern kann! Vielen vielen Dank vorerst :s12:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
So, nachdem das jetzt geklärt ist hab ich jetzt eine Folgefrage:

Wie bewerkstelligt man das am einfachsten dass ich jetzt etliche Merker und Eingänge auf Flanken kontrolliere? D.h. dass ich gerne protokollieren würde wenn z.B. ein Förderband ausfällt, oder z.b. ein Hubtisch.

Beispielszenario:
Fällt das Förderband aus, so soll es die Zahl 6 (die ich vorher einem Förderband zugeordnet habe) in das Ringregister schreiben, natürlich mit zugehöriger Uhrzeit.
Fällt der Hubtisch aus, so soll es die Zahl 8 (...) in das Ringregister schreiben, natürlich mit zugehöriger Uhrzeit.

Setze ich das eher mit einem Datenfeld um, oder einem großen parametrierbaren Baustein, oder mit vielen kleinen Minibausteinen?


Kann ich das hier Fragen oder mache ich lieber einen anderen Thread dafür auf?
 
wobei hier db10.dbw0 die var ist welche in den fifo eingetragen wird
 

Anhänge

  • Zwischenablage04.gif
    Zwischenablage04.gif
    5,1 KB · Aufrufe: 18
Wie bewerkstelligt man das am einfachsten dass ich jetzt etliche Merker und Eingänge auf Flanken kontrolliere? D.h. dass ich gerne protokollieren würde wenn z.B. ein Förderband ausfällt, oder z.b. ein Hubtisch.
Juhu, ich darf mich wieder selbst zitieren:
1. Man gehe in die FAQ, weil Deine Frage gefühlte 10x im Monat gestellt wird und man deshalb gute Chancen hat, dort was zu finden.
2. Man öffne den Thread, der so ziemlich zu Deiner Frage passt, wie A... auf Eimer.
3. Man lese, versuche zu verstehen und probiere dann selbst.
:sm5:
:ROFLMAO: :ROFLMAO: :ROFLMAO:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Jap, jetzt läuft der Kasten! Mal sehen was ich jetzt noch tolles an den Bausteinen ändern kann!
Na ja, wenn ich Dein Konstrukt so sehe, wäre ich damit alles Andere als zufrieden, da z.B. immer noch globale Angaben innerhalb des FBs verwendet werden.
Folgende Baustellen gäbe es aus meiner Sicht mindestens, bevor ich mich anderen Bausteinen zugewendet hätte:


Offensichtlich warst Du nicht mal in der Lage, aus einem STRUCT, das 3 BYTES enthält, 3 einzelne BYTES an der Schnittstelle zu machen. Da muss man nur den STRUCT-"Käfig" entfernen und schon kannst Du Deine Stunde, Minute und Sekunde separat übergeben.

Den Zeiger für den Ringspeicher außerhalb des FBs zu speichern (wie Du es jetzt machst) halte ich auch für sinnvoll. Trotzdem sollte auch er nicht global verwendet werden, sondern ebenfalls über die Schnittstelle übergeben werden. In diesem Fall würde man IN_OUT benötigen, da erst der alte Wert gelesen werden soll (IN-Part), dann verändert wird und der neue Wert dann wieder gespeichert werden soll (OUT-Part).

Wenn der Zeiger für den Ringspeicher außerhalb des FBs gespeichert wird, sollte das auch für die aktuelle Ereignisnummer gelten.

Wenn der Ringspeicher mit Nullen resettet wird, würde ich auch noch den Zeiger für den Ringspeicher und die Ereignisnummer resetten.
Durch Ersteres könnte man auch schon nach dem Reset des ersten Datensatzes dort im nächsten Zyklus sofort wieder ein neues Ereignis eintragen, während die nachfolgenden Datensätze weiter genullt werden.

Wie früher schon mal erwähnt, sind die 5ms nicht gerade weit von der Zykluszeit entfernt. Ich würde deshalb einfach jeden Zyklus einen Datensatz resetten. Dadurch könnte man sich den ganzen Timeraufwand sparen.

Ich würde wissen wollen, ob das Resetten noch aktiv ist und einen entsprechenden Ausgang am FB erstellen.

Das doppelte Öffnen des DBs bzw. Sichern des AR1 ist in meinen Augen auch "unschön".



Ich hab' das mal für Dich zur Ansicht umgesetzt (immer noch ungetestet ):
Code:
[FONT=Courier New]FUNCTION_BLOCK "Ereignisspeicher"
TITLE =
AUTHOR : Hucki
VERSION : 0.1


VAR_INPUT
  Speichern : BOOL ;	
  Reset_Start : BOOL ;	
  Aktuell_Stunden : BYTE ;	
  Aktuell_Minuten : BYTE ;	
  Aktuell_Sekunden : BYTE ;	
  Speicher_DB : BLOCK_DB ;	
  DS_Anzahl : INT ;	
  DS_Laenge : INT ;	
  DS_Offset : INT ;	
END_VAR

VAR_OUTPUT
  Reset_Aktiv : BOOL ;	
END_VAR

VAR_IN_OUT
  Zeiger_Ringspeicher : INT ;	
  Ereigniszaehler : INT ;	
END_VAR

VAR
  Zeiger_DS_Reset : INT ;	
  FM_Speichern : BOOL ;	
  FM_Reset : BOOL ;	
END_VAR

VAR_TEMP
  Sicherung_AR1 : DWORD ;	
END_VAR


BEGIN

NETWORK
TITLE =

      UN    #Speichern; // Wenn Baustein nichts im DB speichern soll
      UN    #Reset_Start; // und nicht das Resetten des DBs beginnen soll
      UN    #Reset_Aktiv; // und auch nicht beim Resetten des DBs ist
      BEB   ; // dann Baustein gleich beenden, weil er nix zu tun hat



// #### ALLGEMEIN ####################################################################################
// AR1 sichern 
      TAR1  ; // Adress-Register 1 in Akku1 laden
      T     #Sicherung_AR1; // und temporär sichern 

// Datenbaustein
      AUF   #Speicher_DB; // Speicher-DB öffnen



//#### DS SPEICHERN ##################################################################################
      U     #Speichern; // Schließer-Eingang #Speichern
      FP    #FM_Speichern; // auf positive Flanke (0->1) prüfen
      SPBN  ResS; // wenn keine Flanke, zum Beginn der RESET-Routine springen

// Ereigniszähler inkrementiern
      L     #Ereigniszaehler; // Ereigniszähler laden
      +     1; // um 1 erhöhen und 
      T     #Ereigniszaehler; // wieder speichern

// Pointer erstellen
      L     #Zeiger_Ringspeicher; // Zeiger für Ringspeicher laden
      L     #DS_Laenge; // Datensatzlänge laden
      *I    ; // miteinander multiplizieren
      L     #DS_Offset; // Startadresse des Datenfeldes laden
      +I    ; // hinzu addieren
      SLD   3; // berechneten Wert auf die Byteadresse schieben
      LAR1  ; // und ins Adressregister 1 schreiben

// Daten eintragen
      L     #Ereigniszaehler; // Ereigniszähler laden
      T     DBW [AR1,P#0.0]; // und im aktuellen Datensatz an WORD 0 sichern

      L     #Aktuell_Stunden; // Aktuelle Stunde laden
      T     DBB [AR1,P#4.0]; // und im aktuellen Datensatz an BYTE 4 sichern

      L     #Aktuell_Minuten; // Aktuelle Minute laden
      T     DBB [AR1,P#5.0]; // und im aktuellen Datensatz an BYTE 5 sichern

      L     #Aktuell_Sekunden; // Aktuelle Sekunde laden
      T     DBB [AR1,P#6.0]; // und im aktuellen Datensatz an BYTE 6 sichern

// Zeiger inkrementieren
      L     #Zeiger_Ringspeicher; // Zeiger für Ringspeicher laden
      +     1; // um 1 erhöhen
      T     #Zeiger_Ringspeicher; // und wieder speichern

// Zeiger auf Überlauf prüfen
      L     #Zeiger_Ringspeicher; // Zeiger für Ringspeicher laden
      L     #DS_Anzahl; // maximale Anzahl an Datensätzen laden
      >I    ; // auf Überschreitung prüfen
      SPBN  ResS; // wenn nicht überschritten, zum Beginn der RESET-Routine springen
      L     0; // Wert 0 laden
      T     #Zeiger_Ringspeicher; // und Zeiger für Ringpuffer auf 0 resetten



//#### DS RESETTEN ###################################################################################
// RESET starten
ResS: U     #Reset_Start; // Öffner-Eingang #Reset_Start
      FN    #FM_Reset; // auf negative Flanke (1->0) prüfen
      S     #Reset_Aktiv; // und ggf. Reset aktivieren

// RESET aktiviert?
      U     #Reset_Aktiv; // Reset aktiv?
      SPBN  Ende; // Nein, dann zum Ende springen

// Bei RESET-Beginn Zeiger_Ringpuffer und Ereigniszähler zurücksetzen
      L     #Zeiger_DS_Reset; // Reset-Zeiger laden
      L     0; // Wert 0 laden
      ==I   ; // auf Gleichheit prüfen
      SPBN  PoiR; // wenn nicht 0 zum Erstellen des Pointers springen
      T     #Zeiger_Ringspeicher; // Zeiger für Ringspeicher auf 0 resetten
      T     #Ereigniszaehler; // Ereigniszähler auf 0 resetten

// Pointer Löschschleife erstellen
PoiR: L     #Zeiger_DS_Reset; // Reset-Zeiger laden
      L     #DS_Laenge; // Datensatzlänge laden
      *I    ; // miteinander multiplizieren
      L     #DS_Offset; // Startadresse des Datenfeldes
      +I    ; // hinzu addieren
      SLD   3; // berechneten Wert auf die Byteadresse schieben
      LAR1  ; // und ins Adressregister 1 schreiben

// Daten eintragen
      L     0; // Wert 0 laden
      T     DBD [AR1,P#0.0]; // ins (1.) DWORD 0 eintragen

      L     0; // Wert 0 laden
      T     DBD [AR1,P#4.0]; // ins (2.) DWORD 4 eintragen

// Zeiger erhöhen
      L     #Zeiger_DS_Reset; // Reset-Zeiger laden,
      +     1; // um 1 erhöhen
      T     #Zeiger_DS_Reset; // und wieder speichern

// Zeiger auf Überlauf prüfen
      L     #Zeiger_DS_Reset; // Reset-Zeiger laden,
      L     #DS_Anzahl; // Max. Anzahl an Datensätzen laden
      >I    ; // auf Überschreitung prüfen
      SPBN  Ende; // wenn noch nicht überschritten zum Ende springen
      R     #Reset_Aktiv; // RESET deaktivieren
      L     0; // Wert 0 laden
      T     #Zeiger_DS_Reset; // Reset-Zeiger auf 0 resetten



//#### ALLGEMEIN ####################################################################################
// AR1 wiederherstellen                            
Ende: L     #Sicherung_AR1; // Gesicherten Wert laden
      LAR1  ; // und ins Adress-Register 1 zurückschreiben


END_FUNCTION_BLOCK[/FONT]
und der entsprechende Aufruf des FBs:





Und von der Sache her ist das Resetten ja die gleiche Funktion wie das Speichern, nur das halt alles Nullwerte gespeichert werden. Man könnte also theoretisch den FB auch auf die Speicher-Funktion begrenzen (vlt. noch etwas anpassen) und dann für den Reset einen 2. Aufruf des FBs mit anderen Übergabewerten an der Schnittstelle benutzen.
 
Okay, vielen Dank soweit, sieht wirklich feiner aus. Ganz großen respekt vor deinem (eurer allen) Wissen!

Funktioniert auch sehr gut, nur das resetten will nicht... aber vielleicht liegts ja an mir :oops:
 
für das reseten solltest du dir mal sfc21 anschauen.
Code:
      L     0
      T     #BVal_FILL
      CALL  SFC   21
       BVAL   :=#BVal_FILL
       RET_VAL:=#RET_VAL
       BLK    :=P#DB3.DBX 0.0 BYTE 200
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
ich würde schon gerne den geschriebenen code benutzen, nur funzt er bei mir net komplett, ich weiss zum beispiel nicht was ich im OB1, wo ich den baustein calle, bei #Reset_Aktiv angeben soll.
ich glaube ich könnte dort einen ausgang anlegen, weiss aber nicht ob ich den wirklich belegen muss. glaube ja net...

aber leider bin ich nicht gut genug um den fehler zu finden...
 
... das sieht für mich so aus, als würde es sich bei "Reset aktiv" um eine Rückmeldung des Bausteins selbst handeln, die so lange TRUE ist, wie die von "Reset Start" angeforderte Aktion läuft bzw. der "Reset Start" angesteuert ist. Das kannst du ggf. als Verriegelung für irgend etwas (oder auch einfach nur als Info) benutzen - mußt es aber nicht ... (Vorteil von FB's).

Gruß
Larry
 
Funktioniert auch sehr gut, nur das resetten will nicht... aber vielleicht liegts ja an mir :oops:
Nein liegt nicht an Dir, sondern an mir. :oops:
Ist im Allgemeinen keine so gute Idee, die Flankenbildung zu überspringen, wenn das zu prüfende Signal negativ ist. Wie soll S7 dann die Flanke erkennen? (Hab' das erst mal nur auskommentiert.) Außerdem sollte man die max. Datensätze auch auf Gleichheit prüfen, sonst greift man am Ende auf einen Datensatz zu, den's nicht mehr gibt und die CPU geht auf STOP.


Also nochmal korrigiert (und getestet :)):
Code:
[FONT=Courier New]FUNCTION_BLOCK "Ereignisspeicher"
TITLE =
AUTHOR : Hucki
VERSION : 0.1


VAR_INPUT
  Speichern : BOOL ;    
  Reset_Start : BOOL ;    
  Aktuell_Stunden : BYTE ;    
  Aktuell_Minuten : BYTE ;    
  Aktuell_Sekunden : BYTE ;    
  Speicher_DB : BLOCK_DB ;    
  DS_Anzahl : INT ;    
  DS_Laenge : INT ;    
  DS_Offset : INT ;    
END_VAR

VAR_OUTPUT
  Reset_Aktiv : BOOL ;    
END_VAR

VAR_IN_OUT
  Zeiger_Ringspeicher : INT ;    
  Ereigniszaehler : INT ;    
END_VAR

VAR
  Zeiger_DS_Reset : INT ;    
  FM_Speichern : BOOL ;    
  FM_Reset : BOOL ;    
END_VAR

VAR_TEMP
  Sicherung_AR1 : DWORD ;    
END_VAR


BEGIN

NETWORK
TITLE =

      NOP   0; // Leerbefehl (nachfolgenden Kommentare nicht in Netzwerkkommentar einfügen)
//      UN    #Speichern                  // Wenn Baustein nichts im DB speichern soll
//      UN    #Reset_Start                // und nicht das Resetten des DBs beginnen soll
//      UN    #Reset_Aktiv                // und auch nicht beim Resetten des DBs ist
//      BEB                               // dann Baustein gleich beenden, weil er nix zu tun hat


// #### ALLGEMEIN ####################################################################################
// AR1 sichern 
      TAR1  ; // Adress-Register 1 in Akku1 laden
      T     #Sicherung_AR1; // und temporär sichern 

// Datenbaustein
      AUF   #Speicher_DB; // Speicher-DB öffnen



//#### DS SPEICHERN ##################################################################################
      U     #Speichern; // Schließer-Eingang #Speichern
      FP    #FM_Speichern; // auf positive Flanke (0->1) prüfen
      SPBN  ResS; // wenn keine Flanke, zum Beginn der RESET-Routine springen

// Ereigniszähler inkrementiern
      L     #Ereigniszaehler; // Ereigniszähler laden
      +     1; // um 1 erhöhen und 
      T     #Ereigniszaehler; // wieder speichern

// Pointer erstellen
      L     #Zeiger_Ringspeicher; // Zeiger für Ringspeicher laden
      L     #DS_Laenge; // Datensatzlänge laden
      *I    ; // miteinander multiplizieren
      L     #DS_Offset; // Startadresse des Datenfeldes laden
      +I    ; // hinzu addieren
      SLD   3; // berechneten Wert auf die Byteadresse schieben
      LAR1  ; // und ins Adressregister 1 schreiben

// Daten eintragen
      L     #Ereigniszaehler; // Ereigniszähler laden
      T     DBW [AR1,P#0.0]; // und im aktuellen Datensatz an WORD 0 sichern

      L     #Aktuell_Stunden; // Aktuelle Stunde laden
      T     DBB [AR1,P#4.0]; // und im aktuellen Datensatz an BYTE 4 sichern

      L     #Aktuell_Minuten; // Aktuelle Minute laden
      T     DBB [AR1,P#5.0]; // und im aktuellen Datensatz an BYTE 5 sichern

      L     #Aktuell_Sekunden; // Aktuelle Sekunde laden
      T     DBB [AR1,P#6.0]; // und im aktuellen Datensatz an BYTE 6 sichern

// Zeiger inkrementieren
      L     #Zeiger_Ringspeicher; // Zeiger für Ringspeicher laden
      +     1; // um 1 erhöhen
      T     #Zeiger_Ringspeicher; // und wieder speichern

// Zeiger auf Überlauf prüfen
      L     #Zeiger_Ringspeicher; // Zeiger für Ringspeicher laden
      L     #DS_Anzahl; // maximale Anzahl an Datensätzen laden
      >=I   ; // auf Überschreitung prüfen
      SPBN  ResS; // wenn nicht überschritten, zum Beginn der RESET-Routine springen
      L     0; // Wert 0 laden
      T     #Zeiger_Ringspeicher; // und Zeiger für Ringpuffer auf 0 resetten



//#### DS RESETTEN ###################################################################################
// RESET starten
ResS: U     #Reset_Start; // Öffner-Eingang #Reset_Start
      FN    #FM_Reset; // auf negative Flanke (1->0) prüfen
      S     #Reset_Aktiv; // und ggf. Reset aktivieren

// RESET aktiviert?
      U     #Reset_Aktiv; // Reset aktiv?
      SPBN  Ende; // Nein, dann zum Ende springen

// Bei RESET-Begin Zeiger_Ringpuffer und Ereigniszähler zurücksetzen
      L     #Zeiger_DS_Reset; // Reset-Zeiger laden
      L     0; // Wert 0 laden
      ==I   ; // auf Gleichheit prüfen
      SPBN  PoiR; // wenn nicht 0 zum Erstellen des Pointers springen
      T     #Zeiger_Ringspeicher; // Zeiger für Ringspeicher auf 0 resetten
      T     #Ereigniszaehler; // Ereigniszähler auf 0 resetten

// Pointer Löschschleife erstellen
PoiR: L     #Zeiger_DS_Reset; // Reset-Zeiger laden
      L     #DS_Laenge; // Datensatzlänge laden
      *I    ; // miteinander multiplizieren
      L     #DS_Offset; // Startadresse des Datenfeldes
      +I    ; // hinzu addieren
      SLD   3; // berechneten Wert auf die Byteadresse schieben
      LAR1  ; // und ins Adressregister 1 schreiben

// Daten eintragen
      L     L#0; // Wert 0 laden
      T     DBD [AR1,P#0.0]; // ins (1.) DWORD 0 eintragen
      T     DBD [AR1,P#4.0]; // ins (2.) DWORD 4 eintragen

// Zeiger erhöhen
      L     #Zeiger_DS_Reset; // Reset-Zeiger laden,
      +     1; // um 1 erhöhen
      T     #Zeiger_DS_Reset; // und wieder speichern

// Zeiger auf Überlauf prüfen
      L     #Zeiger_DS_Reset; // Reset-Zeiger laden,
      L     #DS_Anzahl; // Max. Anzahl an Datensätzen laden
      >=I   ; // auf Überschreitung prüfen
      SPBN  Ende; // wenn noch nicht überschritten zum Ende springen
      R     #Reset_Aktiv; // RESET deaktivieren
      L     0; // Wert 0 laden
      T     #Zeiger_DS_Reset; // Reset-Zeiger auf 0 resetten


//#### ALLGEMEIN ####################################################################################
// AR1 wiederherstellen                            
Ende: L     #Sicherung_AR1; // Gesicherten Wert laden
      LAR1  ; // und ins Adress-Register 1 zurückschreiben


END_FUNCTION_BLOCK[/FONT]
 
Zuviel Werbung?
-> Hier kostenlos registrieren
ersetze im code.
solange reset_start = 1 ist wird der db genullt. es reicht also eine pos_flanke am reset_start.


Code:
//#### DS RESETTEN ###################################################################################

U Reset_Start
SPBN ende

L DS_Laenge
L DS_Anzahl
*I
T #Anzahl_Bytes //temp

L DBNO
T #Ziel_DB //temp

      LAR1  P##ZANY                     //temp typ: any //zeiger ins adressregister laden
      L     W#16#10                     //SyntaxID.
      T     LB [AR1,P#0.0]
      L     W#16#2                      //Typ BYTE
      T     LB [AR1,P#1.0]
      L     #Anzahl_Bytes               //Anzahl Bytes
      T     LW [AR1,P#2.0]
      L     #Ziel_DB                   //Quell-DB
      T     LW [AR1,P#4.0]
      L     #DS_Offset              //Anfangsadresse
      SLD   3
      T     LD [AR1,P#6.0]
      L     B#16#84                     //Speicherbereich (hier DB)
      T     LB [AR1,P#6.0]

      L     0
      T     #BVal_FILL //temp typ:byte
      CALL  SFC   21
       BVAL   :=#BVal_FILL
       RET_VAL:=#RET_VAL
       BLK    :=#ZANY
ende: NOP 0
 
Zuletzt bearbeitet:
ich weiss zum beispiel nicht was ich im OB1, wo ich den baustein calle, bei #Reset_Aktiv angeben soll.
ich glaube ich könnte dort einen ausgang anlegen, weiss aber nicht ob ich den wirklich belegen muss. glaube ja net...
... das sieht für mich so aus, als würde es sich bei "Reset aktiv" um eine Rückmeldung des Bausteins selbst handeln, die so lange TRUE ist, wie die von "Reset Start" angeforderte Aktion läuft bzw. der "Reset Start" angesteuert ist. Das kannst du ggf. als Verriegelung für irgend etwas (oder auch einfach nur als Info) benutzen - mußt es aber nicht ... (Vorteil von FB's).
Es ist genau so, wie Larry es heraus gelesen hat:
Ich würde wissen wollen, ob das Resetten noch aktiv ist und einen entsprechenden Ausgang am FB erstellen.
Und zwar deshalb:
Wie früher schon mal erwähnt, sind die 5ms nicht gerade weit von der Zykluszeit entfernt. Ich würde deshalb einfach jeden Zyklus einen Datensatz resetten. Dadurch könnte man sich den ganzen Timeraufwand sparen.
Ich hab' das mal mit 2000 Datensätzen/Zyklen getestet. Die Simulation ist dann ca. 20 Sekunden "beschäftigt". Ich weiß nicht, ob das in der Realität mit den 5ms-Timern noch funzt oder die Dauer sich dann nur noch zusätzlich verlängert.

Da sind natürlich Volkers Variante oder die Loop-Version, die das in einem Zyklus erledigen, schon eleganter.
Aber das war ja nicht mehr gewollt:
PLANÄNDERUNG
...
Wenn die FN vom E 124.2 kommt soll eine Schleife Anfangen im Eintrag [0] den Wert Null für alles zu schreiben. Alle 5 ms soll der Zeiger dann weiterspringen im Eintrag [1] , [2] usw... wieder auf Null zurücksetzen.

Wenn ich das mal so überdenke soll die Schleife also 2000 mal springen alle 5ms , d.h. 10 sek.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich hab' das mal mit 2000 Datensätzen/Zyklen getestet. Die Simulation ist dann ca. 20 Sekunden "beschäftigt". Ich weiß nicht, ob das in der Realität mit den 5ms-Timern noch funzt oder die Dauer sich dann nur noch zusätzlich verlängert.
Bei mir braucht sie CPU 15,4s, stelle ich allerdings auf 1ms braucht die CPU nur 7,3s.

Da sind natürlich Volkers Variante oder die Loop-Version, die das in einem Zyklus erledigen, schon eleganter.
Aber das war ja nicht mehr gewollt

Was heisst "nicht mehr gewollt"? Eher nicht gebraucht! Aber es würde sich bestimmt lohnen zu sehen mit dem Loop, oder gab es da schon eine Variante :oops: ?
 
Bei mir braucht sie CPU 15,4s, stelle ich allerdings auf 1ms braucht die CPU nur 7,3s.
Hätte jetzt nicht gedacht, dass meine Simu so viel langsamer ist."Chef, ich brauch' einen neuen Laptop!"
Was heisst "nicht mehr gewollt"? Eher nicht gebraucht! Aber es würde sich bestimmt lohnen zu sehen mit dem Loop, oder gab es da schon eine Variante :oops: ?
:confused:Liest Du Deinen Thread auch? So speziell von Post #41 bis #58? Also bei den Standardeinstellungen dieses Forums fast 2 Seiten!Nur weil man seine Vorstellung vom Programm erst mal nur runter getippt und noch nicht getestet hat, heißt das ja nicht, dass man sie nicht noch lauffähig bekommt. Aber warum soll man da weiter Arbeit reinstecken, wenn der TE neue Anforderungen erstellt?
 
Hätte jetzt nicht gedacht, dass meine Simu so viel langsamer ist."Chef, ich brauch' einen neuen Laptop!"

Einfach bestellen und die Rechnung hinknallen :s9:


Liest Du Deinen Thread auch? So speziell von Post #41 bis #58? Also bei den Standardeinstellungen dieses Forums fast 2 Seiten!Nur weil man seine Vorstellung vom Programm erst mal nur runter getippt und noch nicht getestet hat, heißt das ja nicht, dass man sie nicht noch lauffähig bekommt. Aber warum soll man da weiter Arbeit reinstecken, wenn der TE neue Anforderungen erstellt?

Ja du hast Recht! Aber es ist wirklich net leicht für mich hier immer alles direkt zu verstehen :oops:
Und wenn ich Änderungen vorgeschrieben bekomme freut mich das auch net wirklich, ich habe noch wichtigere Dinge zu tun als mir neben der normalen Arbeit noch SPS-programmieren anzulernen. Alles Mist!
Obwohl ich ja zugeben muss dass es langsam anfängt mir Spaß zu machen, ihr erklärt das immer so schön und freundlich wenn man was nicht versteht. Ich habe hier zwar ein Buch liegen über SPS-programmieren, aber das hilft nicht wirklich gut.

Und ich habe beschlossen den FB jetzt so zu lassen wie er ist, denn er funktioniert super!
 
Zuviel Werbung?
-> Hier kostenlos registrieren
noch was zum ablöschen der daten falls du meine methode verwenden solltest
das ablöschen der daten erfolgt byteweise. das kann man noch auf dword ändern.
beispiel irgendeine alte 315er L DBB 5,4 ys (microsekunden) T DBB 4,8 ys
L DBD 8,5 ys T DBB 8,1 ys
dword dauert also in etwa doppelt so lange da du aber dann direkt 4 byte überträgst kommst du insgesamt auf ca die halbe zeit.

das gleiche gilt natürlich auch bei ablöschen der daten bei der anderen methode

Code:
//#### DS RESETTEN ###################################################################################

U Reset_Start
SPBN ende

L DS_Laenge
L DS_Anzahl
*I
[COLOR=#ff0000][B]L 4[/B]
/I[/COLOR]
T #Anzahl_Bytes //temp

L DBNO
T #Ziel_DB //temp

      LAR1  P##ZANY                     //temp typ: any //zeiger ins adressregister laden
      L     W#16#10                     //SyntaxID.
      T     LB [AR1,P#0.0]
      L     W#16#[B][COLOR=#ff0000]6[/COLOR][/B]                      //Typ [COLOR=#ff0000]DWORD[/COLOR]
      T     LB [AR1,P#1.0]
      L     #Anzahl_Bytes               //Anzahl Bytes
      T     LW [AR1,P#2.0]
      L     #Ziel_DB                   //Quell-DB
      T     LW [AR1,P#4.0]
      L     #DS_Offset              //Anfangsadresse
      SLD   3
      T     LD [AR1,P#6.0]
      L     B#16#84                     //Speicherbereich (hier DB)
      T     LB [AR1,P#6.0]

      L     [COLOR=#ff0000]L#0[/COLOR]
      T     #BVal_FILL //temp typ:dword
      CALL  SFC   21
       BVAL   :=#BVal_FILL
       RET_VAL:=#RET_VAL
       BLK    :=#ZANY
ende: NOP 0
 
Zuletzt bearbeitet:
Data Logger

Hallo alle zusammen,

dieses Forum brachte mich schon häufig auf gute Ansätze und Lösungen. Mit diesem Beitrag möchte ich mich bei euch allen bedanken.

Ich weiß der letzte Beitrag ist jetzt schon wieder zwei Monate her, aber vielleicht dient mein Beitrag dem nächsten Besucher, der eine Lösung zur Event Dokumentation benötigt. Denn das, was der Themen Starter hier eigentlich machen wollte, ist nach meinem Empfinden das, was ein Data Logger macht.

Das angehängte Projekt zeigt meinen Data Logger (FB60) der folgendes bietet:

- beobachten von 10 Eingängen auf steigende und (wahlweise) fallende Flanke mit darauf folgendem Eintrag in den aktuellen DB
- Insgesamt lassen sich maximal 999 unterschiedliche Events simultan überwachen bzw. loggen
- Jeder Eintrag (Log) hat folgenden Aufbau:
1. ID in INT (0-999 für gegangenes Ereignis, 1000-1999 für gekommenes Ereignis)
2. Date_YMD
3. Time_HMS (durch milisekunden genaues loggen, Zyklus genau!)
4. Data_INT (frei belegbare Zusatzinfo in INT, zum Beispiel Position einer Achse oder Stromaufnahme oder oder oder :)

- Der nächste Eintrag erfolgt immer unter dem letzten Eintrag -> Kein verschieben der geloggten Daten!
- Ist der aktuelle DB voll, wird automatisch der nächste DB erst gelöscht, dann der Log eingetragen
- Im ersten DB wird der aktuell beschriebene DB und Zeile angezeigt
- Anzahl an Events und der DB's frei wählbar

So, das war es von mir! Viel Spaß damit!
 

Anhänge

  • Logv1_1.zip
    302,7 KB · Aufrufe: 13
Zurück
Oben