Array bei Datenwechsel speichern in Ringpuffer

Wiedenn?

Level-1
Beiträge
18
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, ich muß Daten (8 Strings und das Datum) in einem DB ablegen und dieser soll als Ringpuffer dienen. Wenn sich einer der Strings ändert sollen alle wieder neu im DB abgelegt werden. Hatte mir ein Array mit den Daten vorgestellt im DB, wobei dieser 1000x im DB vorhanden. Wie kann man das am einfachsten lösen unter Step 7.V5.4 CPU 414?

Lese die Strings von einer Kamera ein. Lege dann das Datum und Zeit der Steuerung dazu.
 
Zuletzt bearbeitet:
Ich habe nicht ganz verstanden wer die Strings ändert? Schreibt da die VISU rein oder wie.

Wenn du die Daten dann im Array umsortieren willst dann mach das mit ner Schleife und nem eleganten Pointer.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hast du einen konkreten Vorschlag wie es zu realisieren wäre? Bin nämlich mit Pointern nicht gerade der Held.
Es sollen die neuen Daten in Array 0 eingetragen werden nachdem alle anderen +1 verschoben wurden (Daten aus Array0 in 1, aus 1 in 2 usw. bis 1000 - Ringpuffer).
Nochmal zur Info- habe schon einen DB in dem die Strings liegen. Wenn diese sich ändern will ich die neuen werte in einem anderen DB welcher als Ringpuffer dient sichern.
So stelle ich mir den neuen DB vor:
http://www.sps-forum.de/attachment.php?attachmentid=9992&stc=1&d=1268947094
 

Anhänge

  • DB_Kamera.gif
    DB_Kamera.gif
    6,6 KB · Aufrufe: 99
Zuletzt bearbeitet:
Ich habe mal so etwas ähnliches programmiert, ich habe es auch gerade wiedergefunden.

Also ich hatte damal auch ein Array indem eine Structur bestehend aus Datum, Uhrzeit, 3 Realwerten und einem Integer enthalten war. Das waren dann 20 Byte. Im DB waren 100 Felder die ich über den Parameter #ANZ übergebe.

Sobald der Code hier durchlaufen wird, werden die Felder im Array aufgerückt. Vorher DB aufschlagen, ist klar.;)

Code:
      L     #ANZ                        // maximale Anzahl Datensätze
      L     1
      -I    
      L     20
      *I    
      L     20                          // 20 Byte abziehen
      -I    
      T     #Adresse                    // Startadresse berechnen (vorletzter Datensatz)
      L     #ANZ
      L     1
      -I    
anf:  T     #temp_int
      L     #Adresse
      ITD   
      SLD   3
      LAR1  
      L     DBD [AR1,P#0.0]             // Datensatz (20Byte)
      T     DBD [AR1,P#20.0]            // umkopieren
      L     DBD [AR1,P#4.0]
      T     DBD [AR1,P#24.0]
      L     DBD [AR1,P#8.0]
      T     DBD [AR1,P#28.0]
      L     DBD [AR1,P#12.0]
      T     DBD [AR1,P#32.0]
      L     DBD [AR1,P#16.0]
      T     DBD [AR1,P#36.0]
      L     #Adresse                    // neue Adresse berechnen
      L     20
      -I    
      T     #Adresse
      L     #temp_int
      LOOP  anf                         // Sprung zum Schleifenanfang
 
Ach ja, bei meiner Variante wird mit Integer gearbeitet, d.h. es funktioniert nur bis zur Adresse 32676. Wenn mehr Bytes im DB geschaufelt werden sollen dann DINT.

Bei dir ist jeder Datensatz 18 Byte lang und du hast 999 Datensätze.

Eine ander Variante währe so ein dynamischer Blockmove.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das wäre aber wohl nicht sehr effektiv und würde im schlimmsten Fall die SPS in den Zyklustot treiben, also die Zykluszeit extrem hochschrauben. Besser ist es einen Datensatz-Zeiger auf das aktuelle Array (0-999) zu haben. Wenn ein neuer String kommt, dann wird er inkl. Uhrzeit etc. an die Position geschrieben, auf welche der Datensatz-Zeiger weist, danach wird der Datensatz-Zeiger um 1 erhöht. Ist man bei 999 angekommen, wird der Zeiger beim nächsten Erhöhen nicht auf 1000 sondern auf 0 gesetzt. Somit hat man einen netten Ringpuffer, in welchem nicht die Daten alle komplett umhergeschoben werden, sondern nur ein Zeiger. Am günstigsten wäre für dich, das Ganze in SCL zu programmieren, da kann man mit Arrays und einem Index völlig problemlos umgehen. Wenn du das nicht hast, sieh dir zuerst mal unser FAQ und dort das Thema Pointer und indirekte Adressierung an. Auch die Suche im Forum sollte eine ganze Menge zu Tage fördern.
 
Ja klar nen Zeiger weiter zu zähler und bei Maximum wieder auf Anfang zu springen geht natürlich auch. Ist wesendlich einfacher zu programmieren und treibt die Zykluszeit nicht in die Höhe.
Das tut meine Variante aber auch nicht wesendlich, das geht rubbeldiekatz. Dann hat die CPU auch mal was zu tun.

Wenn die Daten in einer Visualisierung in richtiger Reihenfollge angezeigt werden sollen oder wenn man sie aus irgend einem anderen Grund sortiert in der CPU braucht, dann muß man schaufeln.

SCL ist natürlich eine schöne Sache, gerade bei Arrays
 
viele kB umschaufeln?!

Vielleicht sollte sich Wiedenn? erst mal klarmachen, was er wirklich will bzw. was gefordert (?) ist.
Die Aussage Ringpuffer schließt Datensätze umschaufeln aus. Wieso benutzt Wiedenn? das Wort Ringpuffer?
Oder soll es doch kein Ringpuffer sein, sondern ein ganz ordinärer Queue (FIFO)?
icon5.gif

Wikipedia - Warteschlange & Ringpuffer

Bei 1000 Datensätzen in einer SPS (ganz gleich welcher Größe) verschwende ich nicht einen Gedanken an umschaufeln.
Ein Ringpuffer (wie von Ralle in #6 beschrieben) ist da die erste Wahl und sollte eigentlich zwingend sein.

..., das geht rubbeldiekatz. Dann hat die CPU auch mal was zu tun.
Jaaaa, wenn bei Wiedenn? die CPU tatsächlich nur die eine einzige Aufgabe hat, 1000 Datensätze zu sammeln, dann
könnte man diese Aussage eventuell gerade noch gelten lassen.
(@Tetrade: hast Du mal berechnet oder überschlagen, wie lange Dein "rubbeldiekatz" real dauern wird? :rolleyes:)

Wenn seine CPU aber "nebenbei" auch noch einen Prozess steuern soll, wo vielleicht auch Positionieraufgaben an
Lichtschranken zu erfüllen sind, dann gehen solche extrem schwankenden Zykluszeiten überhaupt nicht.
Also wirklich: 64kB (oder mehr) in einem Zyklus umzuschaufeln, das ist abartig.
icon13.gif


Außerdem reicht die schwammige Aussage "8 Strings und das Datum" für eine fundierte Antwort nicht aus. Das muß
sehr genau betrachtet werden, weil in allen CPU 414, die ich kenne, Datenbausteine maximal 64kB groß sein können.
Ich vermute, in 64kB passen die 1000 Datensätze von Wiedenn? garnicht rein.
icon4.gif


EDIT:
Ich sehe gerade in der angehängten Grafik in #3, daß es garnicht 8 Strings, sondern 1 STRING[8] ist,
doch auch bei knapp 18kB finde ich das umschaufeln "unmöglich".
Btw: es sind auch nicht 1000 Datensätze, sondern "nur" 999. :cool:

Gruß
Harald
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn mal jemand auf die Idee kommt seine kompletten Speicherbereich
über eine indirekten Bereichsübergreifenden Adressierung um zu kopieren.
Hier mal eine Berechnung für 1000 DBD-Variablen.


Code:
L     DBD [AR1,P#0.0]  5,5µs           
T     DBD [AR2,P#0.0]  5,0µs

zusammen 10,5µs bei 1000 Variablen sind das 10,5ms, Cpu ist eine 315er.
Daten sind allerdings aus einer Operationliste von 2006 und die CPU's
sind jetzt auch wieder schneller.

Warum gibt es eigentlich keine Operationslisten mehr für die neueren
CPU's die letzte ist von 2006, möchte da Siemens was verheimlichen?
 
Hallo Hellmut,

das muß aber eine ziemlich langsame CPU sein, von der Du die Ausführungszeiten angegeben hast.
Wiedenn? will hier sogar 17982 Byte umspeichern, also rund 4496 DWords. Dafür würde Deine CPU
alleine für das reine L+T ca. 47,2ms brauchen. Dazu kommen noch die Befehle der Schleife, die
erfahrungsgemäß ein vielfaches dieser reinen Kopierzeit benötigen. (!)

Gerne verweise ich hier auf einen von mir auf einer CPU 315-2PN/DP (315-2EH13) durchgeführten
Benchmark auf 315-2PN/DP: 5758 Byte umspeichern
(in dem Thread ging es auch um das Umspeichern in einem Array)

Für die 17982 Bytes als DWord in einer Schleife umspeichern würde die 315-2PN/DP-CPU hochgerechnet
ca. 27,2ms brauchen, umspeichern mit SFC20 würde ca. 8,4ms dauern.
Umspeichern mit SFC20 geht aber nur von hinten nach vorne (neuester Wert kommt dann nach hinten
ins Array) oder wie 4L damals vorgeschlagen hatte, könnte man ja zweimal mit SFC20 kopieren.

Wiedenn? will seine Aufgabe mit einer CPU 414 lösen, die sicher um einiges schneller ist.
Die könnte das höchstwahrscheinlich in einer akzeptablen Zeit schaffen. Allerdings halte ich das
Umspeichern von 17982 Byte, nur um 18 Byte dem Puffer zuzufügen, nach wie vor für "unelegant".
Da müssten bei mir schon zwingende Gründe vorliegen, sowas zu machen.
In den meisten meiner Projekte sind stark schwankende Zykluszeiten Gift für den Prozess.

Leider habe ich zur Zeit keine 400-er CPU zum Testen zur Verfügung. Die realen Ausführungszeiten
der Kopier-Aktion auf einer 400-er CPU würden mich schon interessieren.

Gruß
Harald
 
Hallo Haralld,
die zeiten habe ich aus der Operationsliste von 2001 errechnet, in wie fern
das der Realität entspricht kann ich nicht sagen. Da stand dann so ähnlich
drin das die Grundoperation für das Laden eines Doppelwortes ca. 4,2µs + der
Zeit für die indirekte Adressierung von noch mal ca. 4,1µs dazu kommen.

Das blöde ist ja bei Siemens das im Downloadbereich direkt nur diese Alte
Operationsliste steht, das hat mir aber keine Ruhe gelassen ich hab dann
in einen FAQ für die neuen V3 CPU's einen Verweis auf die neue Operations-
liste gefunden.
Anhang anzeigen s7300_operation_list_V3.pdf

hier brauchen die neuen CPU's der V3 baureihe nur noch für das Laden
eines Doppelwortes 0,12µs und für den Transferbefehl 0,11µs dazu kommen
noch einmal 0,33µs pro indirekte Adressierung das wären bei 1000 Variablen
ca. 890µs, also doch um einiges schneller.

Der SFC20 Block Move braucht bei einer 315er ca. 10µs für den aufruf und
0,035µs/Byte das wären dann ca 150µs.

gruß helmut
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Lösung gefunden hoffe ich

Hallo, erstmal vielen Dank für die rege Beteiligung und die Hilfe. Habe es jetzt so gelöst das ich mir einen Zählwert erstelle der das nächste Array zeigt und nehme die Jeweilige Startadresse und kopiere dann meinen Bereich über Lade Tranferiere (Pointer). Schreibe immer ins nächste Fach und bei 1000 wird der zurückgestellt und er fängt von vorne an. Als Ringpuffer würde das wirklich zu CPUzeit lastig.
Muß morgen mal probieren ob es so geht wie ich mirs nun vorstelle.
icon7.gif
 
Schön das du eine Lösung hast. Bitte denke daran das dein Array aus deinem Beispiel nur 999 und nicht 1000 Felder hat.
 
Zurück
Oben