Arrays in TwinCAT verbinden

TechB

Level-1
Beiträge
29
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,

ich suche jetzt schon länger nach einer Möglichkeit Arrays in Twincat miteinander zu verbinden. Entweder mir fehlen die richtigen Schlagworte, oder es geht einfach nicht was ich mir nicht vorstellen kann.

Ich möchte beispielsweise die Arrays

str1 : ARRAY[0..5] OF STRING := ['0','1','2','3'];
str2 : ARRAY[0..5] OF STRING := ['4','5','6','7'];

in ein drittes zweidimensionales Array einfügen

str3 : ARRAY[0..10,0..5] OF STRING;

sodass am Ende in str3 an den ersten zwei Positionen

str3[0] ['0','1','2','3']
str3[1] ['4','5','6','7']

steht.

Wie kann ich ein Array in ein zweidimensionales Array einfügen? Geht das nur über eine Schleife?

Der Sinn davon ist, Messwerte mit immer der gleichen Anzahl an einträgen in ein Array zu schreiben um dieses nach Beenden des Messvorgangs in eine .csv Datei zu schreiben.

vielen Dank
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

vielen Dank für den Tipp. Das hat super funktioniert! :)

Ich hätte noch eine Frage bezüglich des Schreibens von Daten in .csv Dateien. Wirklich viel gibts dazu im Netz ja nicht.

Ich habe Messwerte bestehend aus Zeitstempel und 8 Messwerten. Ich schreibe diese in .csv Dateien. Das funktioniert soweit auch, allerdings dauert das Schreiben
suuper lange. Ich schreibe zunächst alle Messdaten in einen Puffer (zweidimensionales Array) auf und schreibe die dann am Stück raus. Wenn ich sie in kleineren Segmenten geschrieben habe, hat es noch länger gedauert.

Zum schreiben nutze ich die "FB_CSVMemBufferWriter" Funktion und die Funktionsbausteine fbOpen/fbPuts/fbClose. Ich habe mich stark an dem Beispielprogramm von Beckhoff orientiert.
(CSVExample) Das schreiben von 40.000 Werten dauert mehrere Minuten und die Datei ist am Ende nur 1,6 Mbyte groß.

Das kanns ja irgendwie nicht sein.

Was ist eine effizientere Methode die Daten zu schreiben?
 
was genau dauert mehrere Minuten?
Die Sequenz fbOpen, fbPut und fbClose? Klar, Dateihandling ist nicht in Echtzeit zu realisieren aber mehrere Minuten sind zu lang.

fbOpen mit welchen Attributen?
Welcher der drei Bausteine verbraucht denn die Zeit? Und auf was schreibst du? HDD, USB,... sonst was spezielles?

Guga
 
Meines Wissens kannst du mit FB_CSVMemBufferWriter nur einen Datensatz pro Zyklus schreiben. Mit FB_FileWrite kannst du größere Datenmengen pro Zyklus schreiben. Jedoch müsstest du dir die csv-Struktur komplett selbst zusammensetzen.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Meines Wissens kannst du mit FB_CSVMemBufferWriter nur einen Datensatz pro Zyklus schreiben. Mit FB_FileWrite kannst du größere Datenmengen pro Zyklus schreiben. Jedoch müsstest du dir die csv-Struktur komplett selbst zusammensetzen.
FB_FileWrite mag (deutlich) schneller sein, habe die FBs praktisch nie benutzt, aber, je nach Zykluszeit und/oder Datenmenge, wird auch er mehr als einen Zyklus benötigen, außerdem schreibt FB_CSVMemBufferWriter nicht in eine Datei, sondern lediglich in einen Buffer und den muss man dann in eine Datei schreiben. Wenn der TE das natürlich Zeilenweise macht kann das ewig dauern.
 
Zuletzt bearbeitet:
Erstmal vielen Dank für die zahlreichen Antworten!

was genau dauert mehrere Minuten?
Die Sequenz fbOpen, fbPut und fbClose? Klar, Dateihandling ist nicht in Echtzeit zu realisieren aber mehrere Minuten sind zu lang.

fbOpen mit welchen Attributen?
Welcher der drei Bausteine verbraucht denn die Zeit? Und auf was schreibst du? HDD, USB,... sonst was spezielles?

Guga

Das es bei 1 ms Zykluszeit nicht in Echtzeit geht ist korrekt. Deshalb schreibe ich die Messdaten ja auch während des Messens in einen Puffer und schreibe den dann nach Abschluss des Messvorgangs in die Datei. Das mache ich aber nur, weil es so lange dauert. Ansonsten könnte man auch währendessen schonmal "Zwischenspeichern".

Ich schreibe auf eine ganz normale HDD. Ich geh davon aus, dass der fbPuts so lange braucht. Ich öffne und schließe die Datei ja nur je einmal und dazwischen wird der komplette Puffer über eine Schleife rausgespeichert. So wird es im Beispielprogramm gemacht. Die Attribite sind wie folgt :

fbFileOpen( sNetId := sNetId,sPathName := fPath, nMode := FOPEN_MODEAPPEND OR FOPEN_MODEPLUS,
ePath := PATH_GENERIC, bExecute := TRUE );


Was genau meinst du damit, die Daten für .csv "selbst zusammenzusetzten" ?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Das klingt sehr gut.

Ich habe gerade mal gestoppt. Ich schreibe zunächst pro Zyklus einen String mit '1;2;3;4;5;6;7;8;9;$N' in ein String-Array mit insgesamt 10000 Einträgen.
Das dauert mit 1ms Zyklustakt logischerweise 10 Sekunden.

Anschließend übergebe ich das Array dem Funktionsbaustein zum Speichern.

Dieser Öffnet die Datei, Speichert die Daten Zeile für Zeile in eine .csv-Datei und schließt sie dann.

Ich habe das ganze jetzt mit FB_WriteFile umgeschrieben und mir die Strings entsprechend zusammengestückelt. Das Einlesen hinterher klappt auch problemlos.

Allerdings dauert das Schreiben unglaubliche 22! Sekunden. Dateigröße danach 800 kB.

Wie kann das so lange dauern?
 
Wenn Du Zeile für Zeile schreibst, brauchst Du für jede Zeile mindestens einen Zyklus für den Start des Kommandos und einen weiteren zur Abfrage der Erledigt-Meldung. 10000 * 2 ms = 20000 ms

Wenn es schneller gehen soll, die Strings nicht in ein Array of String, sondern dicht gepackt in ein Array of Byte schreiben, etwa so: 1,2,3,4,$R,$N,5,6,7,8,$R$N usw.
Dann die Datei im Binärmodus öffnen und den Bytepuffer in einem Rutsch schreiben.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Okay da hatte ich wohl einen klaren Denkfehler. Vielen Dank für euern Input!

Ich habe die Strings jetzt in der Form '1;2;3;4;5;6;$N' zusammengestellt und in ein eindimensionales Array geschrieben. Ich schreibe immer 1000 Werte in ein Array und schreibe das dann auf einmal in die csv. Das geht jetzt deeeeutlich schneller. Es werden ca. 60.000 Werte / Sekunde geschrieben (17MB). Natürlich nicht in Echtzeit.

Jetz habe ich noch ein Problem mit der Erstellung eines Zeitstempels. Ich nutze die Funktion "fbGetSystemTime" und wandle die mit "SYSTEMTIME_TO_STRING" um und per "Right()" hole ich mir nur alles ab Minuten abwärts. Grundlegend funktioniert das, allerdings bekomme ich nur im ersten Eintrag einen korrekten Wert und in allen anderen des Arrays Murks. Siehe Anhang. Der Zeitstempel wird mit CONCAT an den eingentlich zu schreibenden Wert in der Form strSave := CONCAT(strTime,strMessung); angefügt und dann in das Array geschrieben.

Akuell ist es noch ein Test und die 1000 Werte werden in jedem Zyklus per Schleife zusammengefügt. Die Systemzeit wird zu Beginn jedes Zyklus gemessen, was bedeutet, dass je 1000 Werte den gleichen Zeitstempel bekommen.

Weiß jemand was der Grund für das fehlerhafte Schreiben der Zeitstempel sein könnte? Gibt es eine elegantere Methode sich einen Zeitstempel zu erzeugen? Datum, Jahr etc. sind nicht notwendig.

Vielen Dank
 

Anhänge

  • CSV_Test.jpg
    CSV_Test.jpg
    195,5 KB · Aufrufe: 15
Hier die Stelle im Code. Wenn der Wert nicht korrekt wäre, dann sollte es ja nie funktionieren oder?

rows := 1000;
strSave, strMess und sTime vom Typ STRING [150]
DATA_SAVE vom Typ ARRAY[0..1000] OF STRING [150]

Code:
[CODE]fbGetSystemTime(timeLoDW=>fileTime.dwLowDateTime, timeHiDW=>fileTime.dwHighDateTime );
sTime :=SYSTEMTIME_TO_STRING( FILETIME_TO_SYSTEMTIME( fileTime ) );
strTime := Right(sTime,9);
    
FOR i := 0 TO rows BY 1 DO

strSave := CONCAT(strTime,strMess);
DATA_SAVE[i] := strSave;

END_FOR
[/CODE]
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Was mir auf Anhieb auffällt ist, dass in jeder Zeile eigentlich immer das Gleiche stehen müsste, da strMess kein Array ist und somit bei jedem Schleifendurchlauf das Selbe drinsteht.
Du solltest es mal damit versuchen, dass Du vor dem Schreiben in DATA_SAVE diesen mit MEMSET(ADR(DATA_SAVE), 0, SIZEOF(DATA_SAVE)) löscht, nicht das da Müll drin stand.
 
Ja das immer dieselben Werte drin stehen ist korrekt und auch so gewollt, da noch keine realen Messdaten vorliegen. Das ist auch in dem zuvor angehängtem Bild zu erkennen.
Ändern sollte sich nur bei jedem Schleifendurchlauf die Systemzeit.

Ich habe probiert den Speicher wie beschrieben vorher zu löschen, allerdings treten weiterhin kryptische Zeichen auf. Nur der allererste Wert in der csv ist am Ende korrekt.
 
Ja das immer dieselben Werte drin stehen ist korrekt und auch so gewollt, da noch keine realen Messdaten vorliegen. Das ist auch in dem zuvor angehängtem Bild zu erkennen.
Genau da komm ich ins Schleudern, weswegen ich auch müsste schrieb. In Zeile 9, Spalte E ist auf einmal ein anderer Wert, wo kommt der her?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Das ist nur ein Fehler, weil Excel mal wieder dachte, dass der Wert doch ein Datum wäre. Den habe ich dann nur händisch geändert. Steht schon in jeder Zeile dasselbe. Sorry für die Verwirrung.
 
Der Anhang zeigt den ersten Durchlauf, nach Befüllung des Arrays. Die Werte im Array sehen okay aus. Keine Auffälligkeiten meiner Meinung nach.
 

Anhänge

  • CSV_FirstRun.jpg
    CSV_FirstRun.jpg
    111 KB · Aufrufe: 15
Zurück
Oben