Step 7 Mit Pointer in Ringregister schreiben

OK. Wenn die FB-Nummer direkt angegeben wird, darf das nicht in Anführungszeichen stehen, da es ja kein Symbol/Name ist.

Der Rest dürften dann Folgefehler sein. Bei mir sind das dann 32, wenn ich die Anführungszeichen benutzte (ohne das S7 ein Symbol dazu findet).
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Okay, egal.

Wie siehts jetzt mit Beitrag Nummer #59 aus? Kannst du mir verraten wie ich das anstelle dass der Zeiger zum "Nullen" automatisch alle 5 ms weiterspringt und nullt?
 
Egal ist 88.
Für wen machen wir das hier eigentlich? Ich dachte, Du wolltest was lernen.
:sm17:

Für mich ist es jedenfalls wesentlich besser, etwas als Quelle zu posten. Denn da ist auf jeden Fall alles Notwendige dabei.



Wie siehts jetzt mit Beitrag Nummer #59 aus? Kannst du mir verraten wie ich das anstelle dass der Zeiger zum "Nullen" automatisch alle 5 ms weiterspringt und nullt?
Als Quelle schon.

:p
 
Ich würde es gerne lernen, aber STEP 7 liegt mir nicht anscheinend, genau wie jegliches andere Programmieren. Respekt vor den Leuten die das können. Mein Spezialgebiet liegt eher in Mathematik und Physik...

Als Quelle schon.

:p

Das ist schön, ich würde die Quelle gerne auch sehen, allerdings weiss ich dann wieder nicht wie ich damit umgehe wenn sie beim umsetzen Fehler liefert... Darf ich sie bitte trotzdem sehen? :???:
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich würde es gerne lernen, ...
dann solltest Du vlt. noch einen Versuch starten, da es ja wahrscheinlich nur ein kleiner Fehler und nicht die gemeldeten 29 waren!



.. ich würde die Quelle gerne auch sehen, allerdings weiss ich dann wieder nicht wie ich damit umgehe wenn sie beim umsetzen Fehler liefert... Darf ich sie bitte trotzdem sehen? :???:
Ein Grund mehr, noch einen Versuch zu starten.
Aber bitte sehr. Ungefähr so (ist aber immer noch ungetestet, muss also nicht fehlerfrei sein!):
Code:
[FONT=Courier New]FUNCTION_BLOCK "Ereignisspeicher"
TITLE =
VERSION : 0.1


VAR_INPUT
  Speichern : BOOL ;	
  Reset : BOOL ;	
  Register : BLOCK_DB ;	
  DS_Laenge : INT ;	
  DS_Offset : INT ;	
  DS_Anzahl : INT ;	
  Reset_Zeit : TIME ;	
  Uhrzeit : STRUCT 	
   Aktuell_Stunden : BYTE ;	
   Aktuell_Minuten : BYTE ;	
   Aktuell_Sekunden : BYTE ;	
  END_STRUCT ;	
END_VAR

VAR
  Zeiger_Ringpuffer : INT ;	
  Ereigniszaehler : INT ;	
  Schleifenindex : INT ;	
  FM_Speichern : BOOL ;	
  FM_Reset : BOOL ;	
  Reset_Aktiv : BOOL ;	
  Next_DS : BOOL ;	
  Reset_Timer : "TON";	
END_VAR

VAR_TEMP
  Sicherung_AR1 : DWORD ;	
  Error : INT ;	
  Start_Reset_Timer : BOOL ;	
END_VAR


BEGIN

NETWORK
TITLE =

      U     #Speichern; // IN: BOOL
      FP    #FM_Speichern; // STATIC: BOOL
      SPBN  Neu; 

      AUF   #Register; // IN: BLOCK_DB

// Zeiger inkrementieren
      L     #Zeiger_Ringpuffer; // Zeiger für Ringpuffer (STATIC: INT)
      +     1; 
      T     #Zeiger_Ringpuffer; // Zeiger für Ringpuffer

// Zeiger auf Überlauf prüfen
      L     #DS_Anzahl; // maximale Anzahl an Datensätzen  (IN: INT,  Wert 10 über die Schnittstelle übergeben)
      L     #Zeiger_Ringpuffer; // Zeiger für Ringpuffer
      <=I   ; 
      SPBN  over; 
      L     0; 
over: T     #Zeiger_Ringpuffer; // Zeiger für Ringpuffer


// Ereigniszähler inkrementiern
      L     #Ereigniszaehler; // Ereigniszähler  (STATIC: INT)
      +     1; 
      T     #Ereigniszaehler; // Ereigniszähler

// AR1 sichern                            
      TAR1  ; // AR1 in Akku1 laden
      T     #Sicherung_AR1; // und im Temp sichern (im Forum so gelernt :), TEMP: DWORD )

// Pointer erstellen
      L     #Zeiger_Ringpuffer; // Zeiger für Ringpuffer
      L     #DS_Laenge; // Datensatzlänge (IN: INT,  Wert 8 über die Schnittstelle übergeben)
      *I    ; 
      L     #DS_Offset; // Startadresse des Datenfeldes (IN: INT,  Wert 10 über die Schnittstelle übergeben)
      +I    ; 
      SLD   3; // berechneten Wert auf die Byteadresse schieben
      LAR1  ; // und ins Adressregister 1 schreiben

// Daten eintragen
      L     #Ereigniszaehler; // Ereigniszähler
      T     DBW [AR1,P#0.0]; // und wieder sichern

      L     #Uhrzeit.Aktuell_Stunden; // Aktuelle Stunde (IN: STRUCT.Byte, könnte man auch getrennt übergeben) laden
      T     DBB [AR1,P#4.0]; // und in Ringpuffer sichern

      L     #Uhrzeit.Aktuell_Minuten; // Aktuelle Minute (IN: STRUCT.Byte, könnte man auch getrennt übergeben) laden
      T     DBB [AR1,P#5.0]; // und in Ringpuffer sichern

      L     #Uhrzeit.Aktuell_Sekunden; // Aktuelle Sekunde (IN: STRUCT.Byte, könnte man auch getrennt übergeben) laden
      T     DBB [AR1,P#6.0]; // und in Ringpuffer sichern

// AR1 wiederherstellen                            
      L     #Sicherung_AR1; // Gesicherten Wert laden
      LAR1  ; // und ins AR1 zurückschreiben




// Register ggf. resetten
Neu:  U     #Reset; // Öffner-Taster
      FN    #FM_Reset; // deswegen negative Flanke
      S     #Reset_Aktiv; // Reset aktivieren
      S     #Next_DS; 

      U     #Next_DS; // Nächsten Datensatz schreiben?
      SPBN  ende; // Nein, dann zum Ende springen

      AUF   #Register; // IN: BLOCK_DB

// AR1 sichern                            
      TAR1  ; // AR1 in Akku1 laden
      T     #Sicherung_AR1; // und im Temp sichern

// Zeiger Ringpuffer initialiesieren
      T     #Schleifenindex; // als Schleifenindex speichern
      T     #Zeiger_Ringpuffer; // als Zeiger für Ringpuffer speichern

// Pointer erstellen
      L     #Zeiger_Ringpuffer; // Zeiger für Ringpuffer
      L     #DS_Laenge; // Datensatzlänge
      *I    ; 
      L     #DS_Offset; // Startadresse des Datenfelde
      +I    ; 
      SLD   3; // berechneten Wert auf die Byteadresse schieben
      LAR1  ; // und ins Adressregister 1 schreiben

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

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

// Zeiger erhöhen
      L     #Schleifenindex; // Schleifenzähler laden,
      +     1; // um 1 erhöhen
      T     #Schleifenindex; // und wieder speichern
      L     #DS_Anzahl; // Max. Anzahl an Datensätzen laden
      >I    ; // Wenn überschritten,
      SPBN  ARWH;
      R     #Reset_Aktiv; // RESET deaktivieren
      L     0; // Schleifenindex auf Null zurückstellen
      T     #Schleifenindex;

// AR1 wiederherstellen                            
ARWH: L     #Sicherung_AR1; // Gesicherten Wert laden
      LAR1  ; // und ins AR1 zurückschreiben

ende: NOP   0;

// Startbedingungen Reset-Timer
      U     #Reset_Aktiv; 
      UN    #Next_DS; // Nach nächstem Datensatz schreiben
      =     #Start_Reset_Timer; // Timer neu starten

// RESET-Timer (Timer sollten möglichst nie übersprungen werden!)
      CALL #Reset_Timer (// Timer aufrufen
           IN                       := #Start_Reset_Timer,
           PT                       := #Reset_Zeit,
           Q                        := #Next_DS);


END_FUNCTION_BLOCK[/FONT]
Ach ja, könnte sein, dass Du erst noch den SFB4 von den "System Function Blocks" aus der Standardbibliothek in Dein Projekt einfügen musst! Sonst findet S7 wahrscheinlich den "TON" nicht (was dann wieder als Fehler beim Übersetzen gemeldet wird).
 
So, das übersetzen hat geklappt (hab soger die aufgetretenen Fehler behoben YEAH!!!), jetzt muss ich nur noch wissen was ich hier -> Oh shit.jpg in die fehlenden Felder eintragen muss ...

Die Uhrzeit an letzter Stelle ist mir ja klar, aber wie schreibe ich das? Es verlangt ja ein STRUCT. Schreib ich da STRUCT; temp_akt_h (DB1.DBB12) ; temp_akt_m (DB1.DBB13); temp_akt_s () ; END_STRUCT; ???
 
Zuletzt bearbeitet:
Nein, sondern in Deinem DB1 legst Du vor dem Byte 12 ein STRUCT an, schneidest die 3 folgenden Bytes aus und fügst sie innerhalb des STRUCT wieder ein. Jetzt kannst Du zum Einen auf alle 3 Bytes als Einheit und zum anderen auf die 3 Bytes einzeln wie bisher zugreifen. Kann höchstens sein, dass Du beim Symbolnamen der Bytes noch den Namen des STRUCT mit eintragen mußt.
Du kannst aber auch die Schnittstelle des FBs so ändern, das Du die 3 Bytes einzeln übergibst.

Außerdem könntest Du Dir noch überlegen, den Timer mit den 5ms wegzulassen und halt jeden Zyklus um 1 höher zählen zu lassen. Das dürfte fast auf's Gleiche rauskommen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ganz übersehen, sorry :oops::
.. jetzt muss ich nur noch wissen was ich hier -> Anhang anzeigen 21369 in die fehlenden Felder eintragen muss ...
Den Aufruf des SFB4 kannst Du wieder löschen. Da ging es nur darum, das der in die Bausteinliste und in die Symbolliste eingetragen wird, damit Du den SFB in der Quelle benutzen kannst.

Offset ist die Verschiebung zwischen 1.Byte des DB und dem 1.Byte der Datensätze (DS), bei Dir also 10 (Byte).
DS_Anzahl wolltest Du zuletzt 2000 haben, oder?
Reset_Zeit sind Deine gewünschten T#5ms für die Reset-Aktion.
Uhrzeit ist die Übergabe Deiner 3 Bytes der aktuellen Uhrzeit zusammengefasst als STRUCT.

Bis auf die RESET_ZEIT konnte man das alles bei dem Aufruf des FBs auf dem Bild im Post #55 sehen:

 
Guten Morgen,

ich hab jetzt das Uhrzeit-STRUCT wieder rausgenommen und lade es wieder einzeln rein. Soweit alles gut!

Jetzt möchte ich allerdings den "Zeiger_Ringpuffer" nicht in meinem FB105 laden, sondern in meinem DB3 "Register" auf der zweiten Stelle -> DB3.DB2.jpg .
Ich weiss nicht wie ich euch das erklären soll, aber ich hoffe ihr versteht was ich meine.
Weiteres Problem:
Wenn ich den Baustein übertrage und beobachte funktioniert er und schreibt einen Eintrag nach dem anderen. Sobald ich allerdings einmal auf Reset drücke, schreibt er danach beim drücken immer nur noch auf der ersten Stelle und springt nicht mehr weiter. Außerdem wird die Reset-Funktion nicht mehr angehalten irgendwie...
 
Jetzt möchte ich allerdings den "Zeiger_Ringpuffer" nicht in meinem FB105 laden, sondern in meinem DB3 "Register" auf der zweiten Stelle -> Anhang anzeigen 21386 .
Ich weiss nicht wie ich euch das erklären soll, aber ich hoffe ihr versteht was ich meine.

Das hab ich hinbekommen :-D naja, war ja auch net so schwer!


Allerdings läuft alles gut bis ich Reset drücke, dann wird der erste Eintrag genullt und das wars. Drücke ich wieder auf meinen Taster um einen Eintrag zu schreiben, überschreibt es immer nur den ersten Eintrag wieder...

Warum nur? Das soll nicht sein, ich will ja alle 5ms, vom ersten Eintrag an, Einträge löschen und wenn er bei Eintrag 2000 angekommen ist soll das Resetten stoppen bis es wieder betätigt wird...
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
ohne das ich jetzt mal alles lese.
wie sollte der puffer denn aussehen?
du schreibst einen neuen datensatz und alle anderen sollen 1 nach unten geschoben werden?
wenn dem so ist lad dir den baustein von meiner hp wie ich bereits im beitrag 2 geschrieben habe.http://www.sps-forum.de/simatic/64849-mit-pointer-ringregister-schreiben.html#post454248

in dem paket ist ein fifo für datenblöcke der ganau das oben beschriebene macht.

EDIT:
habe den baustein mal als awl-quelle angehängt
 

Anhänge

  • Zwischenablage04.gif
    Zwischenablage04.gif
    4,1 KB · Aufrufe: 9
  • Zwischenablage03.gif
    Zwischenablage03.gif
    6,2 KB · Aufrufe: 9
  • filo.AWL.txt
    4,3 KB · Aufrufe: 27
Zuletzt bearbeitet:
Danke dir, aber das hilft mir leider nicht weiter. Ich bin absoluter SPS-neuling und fange so nach und nach erst an Zusammenhänge zu verstehen. Wenn da, wie in deinen Bausteinen, allgemeine Sachen stehen, kann ich diese noch nicht mit anderen Verknüpfen und weiss somit nicht was sie bedeuten... Tut mir leid. Ich brauche Eure Unterstützung wirklich genau für meinen Code, denn da weiss ich wenigstens halbwegs warum manche Sachen so geschrieben werden...
 
Allerdings läuft alles gut bis ich Reset drücke, dann wird der erste Eintrag genullt und das wars. Drücke ich wieder auf meinen Taster um einen Eintrag zu schreiben, überschreibt es immer nur den ersten Eintrag wieder...
Warum nur? Das soll nicht sein, ich will ja alle 5ms, vom ersten Eintrag an, Einträge löschen und wenn er bei Eintrag 2000 angekommen ist soll das Resetten stoppen bis es wieder betätigt wird...

Bitte zurück zu diesem Problem oder ich muss die CPU :sw13:
 
Ja, es tut mir leid, aber SPS liegt mir anscheinend wirklich nicht... Und ich verstehe Volkers Lösung auch nicht. Er hat da als Beispiel doch einen FILO und ich brauche einen FiFo. Der Funktioniert ja auch ganz gut, bis auf die Reset-Funktion... Und die bekomme ich nicht gebacken, aufgrund dessen weil ich Anfänger bin!
 
Vielleicht wirst du einfach mal den Code Posten müssen oder wenigstens den stand
bekanntgeben mit den du gerade arbeitest, ansonsten wird es schwer mit der Hilfe.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielleicht wirst du einfach mal den Code Posten müssen oder wenigstens den stand
bekanntgeben mit den du gerade arbeitest, ansonsten wird es schwer mit der Hilfe.

Aber sicher doch...

Code:
      U     #Speichern                  // IN: BOOL
      FP    #FM_Speichern               // STATIC: BOOL
      SPBN  Neu


      L     "Uhrzeit".Aktuell_Stunden
      T     #Temp_akt_h

      L     "Uhrzeit".Aktuell_Minuten
      T     #Temp_akt_m

      L     "Uhrzeit".Aktuell_Sekunden
      T     #Temp_akt_s





      AUF   #Register                   // IN: BLOCK_DB

// Zeiger inkrementieren
      L     "Register".Zeiger_Ringpuffer    // Zeiger für Ringpuffer (STATIC: INT)
      +     1
      T     "Register".Zeiger_Ringpuffer    // Zeiger für Ringpuffer

// Zeiger auf Überlauf prüfen
      L     #DS_Anzahl                  // maximale Anzahl an Datensätzen  (IN: INT,  Wert 10 über die Schnittstelle übergeben)
      L     "Register".Zeiger_Ringpuffer    // Zeiger für Ringpuffer
      <=I   
      SPBN  over
      L     0
over: T     "Register".Zeiger_Ringpuffer    // Zeiger für Ringpuffer


// Ereigniszähler inkrementiern
      L     #Ereigniszaehler            // Ereigniszähler  (STATIC: INT)
      +     1
      T     #Ereigniszaehler            // Ereigniszähler

// AR1 sichern                            
      TAR1                              // AR1 in Akku1 laden
      T     #Sicherung_AR1              // und im Temp sichern (TEMP: DWORD )

// Pointer erstellen
      L     "Register".Zeiger_Ringpuffer    // Zeiger für Ringpuffer
      L     #DS_Laenge                  // Datensatzlänge (IN: INT,  Wert 8 über die Schnittstelle übergeben)
      *I    
      L     #DS_Offset                  // Startadresse des Datenfeldes (IN: INT,  Wert 10 über die Schnittstelle übergeben)
      +I    
      SLD   3                           // berechneten Wert auf die Byteadresse schieben
      LAR1                              // und ins Adressregister 1 schreiben

// Daten eintragen
      L     #Ereigniszaehler            // Ereigniszähler
      T     DBW [AR1,P#0.0]             // und wieder sichern

      L     #Temp_akt_h                 // Aktuelle Stunde 
      T     DBB [AR1,P#4.0]             // und in Ringpuffer sichern

      L     #Temp_akt_m                 // Aktuelle Minute 
      T     DBB [AR1,P#5.0]             // und in Ringpuffer sichern

      L     #Temp_akt_s                 // Aktuelle Sekunde 
      T     DBB [AR1,P#6.0]             // und in Ringpuffer sichern

// AR1 wiederherstellen                            
      L     #Sicherung_AR1              // Gesicherten Wert laden
      LAR1                              // und ins AR1 zurückschreiben




// Register ggf. resetten
Neu:  U     #Reset                      // Öffner-Taster
      FN    #FM_Reset                   // deswegen negative Flanke
      S     #Reset_Aktiv                // Reset aktivieren
      S     #Next_DS

      U     #Next_DS                    // Nächsten Datensatz schreiben?
      SPBN  ende                        // Nein, dann zum Ende springen

      AUF   #Register                   // IN: BLOCK_DB

// AR1 sichern                            
      TAR1                              // AR1 in Akku1 laden
      T     #Sicherung_AR1              // und im Temp sichern

// Zeiger Ringpuffer initialisieren
      T     #Schleifenindex             // als Schleifenindex speichern
      T     "Register".Zeiger_Ringpuffer    // als Zeiger für Ringpuffer speichern

// Pointer erstellen
      L     "Register".Zeiger_Ringpuffer    // Zeiger für Ringpuffer
      L     #DS_Laenge                  // Datensatzlänge
      *I    
      L     #DS_Offset                  // Startadresse des Datenfelde
      +I    
      SLD   3                           // berechneten Wert auf die Byteadresse schieben
      LAR1                              // und ins Adressregister 1 schreiben

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

      L     0                           // Wert 0
      T     DBD [AR1,P#4.0]             // ins 2. DWORD eintragen

// Zeiger erhöhen
      L     #Schleifenindex             // Schleifenzähler laden,
      +     1                           // um 1 erhöhen
      T     #Schleifenindex             // und wieder speichern
      L     #DS_Anzahl                  // Max. Anzahl an Datensätzen laden
      >I                                // Wenn überschritten,
      SPBN  ARWH
      R     #Reset_Aktiv                // RESET deaktivieren
      L     0                           // Schleifenindex auf Null zurückstellen
      T     #Schleifenindex

// AR1 wiederherstellen                            
ARWH: L     #Sicherung_AR1              // Gesicherten Wert laden
      LAR1                              // und ins AR1 zurückschreiben

ende: NOP   0

// Startbedingungen Reset-Timer
      U     #Reset_Aktiv
      UN    #Next_DS                    // Nach nächstem Datensatz schreiben
      =     #Start_Reset_Timer          // Timer neu starten

// RESET-Timer (Timer sollten möglichst nie übersprungen werden!)
      CALL  #Reset_Timer                // Timer aufrufen
       IN:=#Start_Reset_Timer
       PT:=#Reset_Zeit
       Q :=#Next_DS
       ET:=
 
Zurück
Oben