Twincat 3 Messwerte in 2,5 kHz mitloggen

morris

Level-1
Beiträge
18
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
Ich habe einen Sensor der gibt mir sein Messwert mit einer Frequenz von 2,5 Khz ( T =0,4 ms) .
Die Beckhoff SPS kann problemlos mithalten, indem ich die Zykluszeit ( jetzt auf 0,1 ms pro Zyklus)heruntersetze und ich kann jeden Messwert zwischenspeichern.

Nun möchte ich die Messwerte auf die Festplatte (der SPS) mitloggen und zwar möglichst jeden.
Momentan habe mit FB_CSVMemBufferWriter und FB_FilePuts aus dem CSV Beispiel geschafft, mit ca. 1kHz die daten mitzuloggen, d.h. "nur" fast jeden dritten Wert schaffe ich zu loggen.
Ich gehe davon aus , dass durch das zeilenweise Schreiben der Schreibevorgang so lange dauert.

Nun meine Frage:
Welche Möglichkeiten habe ich, dass ich jeden Messwert Mitloggen kann in 2,5 kHz?
kann ich mehrere "zeilen" auf einmal schreiben, d.h. wenn ich mir ein array[0..100] bastel mit 100 werten, kann dieses dann in weniger als 100 Zyklen( >40 ms) auf die Festplatte geschrieben werden, damit danach die nächsten 100 Werte ohne Verlust angehängt werden können ?!
gehts eventuell mit einer Textdate Schneller ( fb_filewrite, probiere ich jetzt aus)?

Die dauer des Loggens beträgt später max 20 Sec.

3:(* Convert one PLC record to CSV format *)
sCSVLine := '';
fbWriter.eCmd := eEnumCmd_First;(* Write first field value *)
IF nRow <= MAX_CSV_ROWS THEN

FOR nColumn := 0 TO MAX_CSV_COLUMNS BY 1 DO
database[nRow,1]:= UDINT_TO_STRING(nRow); // Testweise die Spaltennummer ( von 0 .. 100)
database[nRow,2]:= UDINT_TO_STRING(udtime); // Hier steht der SPS Zyklus drinnen ( im main wird i +1 hochgezählt), in der CSV Datein steht dann 10,20,30,40
// da bei 0,1 ms nur in jedem 10 Zykluszeit dert Messwert gespichert wird ( => nur ca 1kHz )
database[nRow,3]:= UDINT_TO_STRING(udarray[nRow]); // AUch ein Array wird zeilenweise geschrieben => verluste

sCSVField := STRING_TO_CSVFIELD( database[ nRow, nColumn ], FALSE );(* TODO: Get field value from your application *)

(* Add new field to the record buffer *)
fbWriter( pBuffer := ADR( sCSVLine ), cbBuffer := SIZEOF( sCSVLine ) - 1, putValue := sCSVField, pValue := 0, cbValue := 0,
bCRLF := ( nColumn = MAX_CSV_COLUMNS ) );(* bCRLF == TRUE => Write CRLF after the last field value *)
IF fbWriter.bOk THEN
fbWriter.eCmd := eEnumCmd_Next;(* Write next field value *)
ELSE(* Error *)
step := 100;
RETURN;
END_IF

END_FOR(* FOR nColumn := 0... *)

(* FB_FilePuts adds allready CR (carriage return) to the written line.
We have to replace the $R$L characters with $L character to avoid double CR. *)
IF RIGHT( sCSVLine, 2 ) = '$R$L' THEN
sCSVLine := REPLACE( sCSVLine, '$L', 2, LEN( sCSVLine ) - 1 );
END_IF

nRow := nRow + 1;(* Increment number of created records (rows) *)
step := 4;(* Write record to the file *)

ELSE(* All rows written => Close file *)
step := 10;
END_IF

4: (* Write single text line *)
fbFilePuts( bExecute := FALSE );
fbFilePuts( sNetId := sNetId, hFile := hFile, sLine := sCSVLine, bExecute := TRUE );
step := 5;

5:(* Wait until write not busy *)
fbFilePuts( bExecute := FALSE, bError => bError, nErrID => nErrID );
IF NOT fbFilePuts.bBusy THEN
IF NOT fbFilePuts.bError THEN
step := 3;(* Write next record *)
ELSE(* Error *)
step := 100;
END_IF
END_IF

10: (* Close source file *)

MFG

Morris



CSV Beispiel : [url]https://infosys.beckhoff.com/index.php?content=../content/1031/tcplclibutilities/html/TcPlcLibUtilities_CSV_Sample.htm&id= [/URL]
 
Hey morris,

die einzige möglichkeit die ich gerade so sehe ist, das du die Werte wie du es beschreibst sammelst und dann gesammelt wegschreibst.

Ich meine das der FB_FileWrite max. einen T_MaxString pro aufruf wegschreiben kann.

Wie lang sind deine Zeilen? und wie lange möchtest du die Werte mit schreiben?

Eine doofe frage noch worfür brauchst du soviele Werte?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hey, Danke für die Antwort
Bin gerade auch auf die "einfache" diee gekommen es mit FB_FileWrite zu probieren, da hier wie du sagtest "mehr" übertragen werden kann.
probiere das gerade aus und melde mich dann.

Zeilenlänge: 255 Zeichen düften reichen, also 1 String
Loggdauer : bis ca 30 s
Wöfür : Muss die höhe eines Messobjektes mit Hilfe eines Lasertriangulationssensor ausmessen.

MFG
Morris
 
So die Gute Nachrricht ist, es funktioniert mit einem Array of String [0..100] und FB_FileWrite.
Hier braucht die SPS nur ca 3,1 ms für 100 werte und die Stringgröße spielt keine Rolle für die Zeit.
Code:
-----------
udarray     :ARRAY[0..100] OF STRING;
-------------
    fbWrite(
    sNetId:= sNetId, 
    hFile:= hFile, 
    pWriteBuff:= ADR(udarray), 
    cbWriteLen:= SIZEOF(udarray), 
    bExecute:= TRUE);

Mein problem jetzt :
DIe Textdatei beinhaltete krüptische zeichen und dann meinen Wert :

¶ ÝŠ´ë5¶í5¶üì5¶,À4¢ìì5¶ìì5¶-Ñ'¢L3b‡,À4¢@í5¶@í5¶í5¶7K(¢L3b‡ 63411

Äê5¶ Q

¶ ÝŠ´ë5¶í5¶üì5¶,À4¢ìì5¶ìì5¶-Ñ'¢L3b‡,À4¢@í5¶@í5¶í5¶7K(¢L3b‡ 63412

Äê5¶ Q

¶ ÝŠ´ë5¶í5¶üì5¶,À4¢ìì5¶ìì5¶-Ñ'¢L3b‡,À4¢@í5¶@í5¶í5¶7K(¢L3b‡ 63413

Liegt glaube ich daran, dass ich nicht alle Zeichen vom String brauche ( zur Zeit),aber möchte trotzdem nicht weniger als die Standart 80 Zeichen vom String schreiben
Wie kann ich nur meine "richtigen eingetragenen Werte" im String übermittlen ?

MFG
Morris
 
Hey wie erstellst du deine Datei?

Wie willst du die Datei denn auswerten? macht eine CSV-Datei sinn?

schließt du die Datei nach dem du fertig bist mit dem auszeichnen wieder?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Die Datei öffne und schließe ich wie in dem CSV- Beispiel, habe lediglich den Case 3: ersetzt durch den aufruf von fbWrite : FB_FileWrite (siehe letzten Beitrag) und case 4: und 5: angepasst.
zum AUswerten möchte ich sie später wieder Zeilenweise einlesen, deswegen soll ja in jeder zeile auhc nur der Wert stehen und nicht noch irgendwelche Sonderzeichen.
Habe den Wert ( uint) in String convertiert und dann %N angehängt, damit eine neue Zeile in der Textdatei entsteht. ( in einer CSV Datei sind die gleichen SOnderzeichen enthalten)

ja zum Ende wird die "normal" geschlossen und im Array of String stehen auch nur die richtigen Werte.
Wenn ich mein Array auf eine Zeichenanzahl von z.B. 20 Begrenze ( sarray :ARRAY[0..100] OF STRING(20);) sind danach weniger sonderzeichen vorhanden, muss also irgendwie and der konvertierung liegen, bzw. weil ich ja die Startadresse und die Größe übergebe
Code:
    fbWrite(
    sNetId:= sNetId, 
    hFile:= hFile, 
[B]    pWriteBuff:= ADR(udarray), 
    cbWriteLen:= SIZEOF(udarray),[/B] 
    bExecute:= TRUE);
und jedes Element des arrays Standartmäßig 80 bytes hat ( oder halt 20 wenn ich es begrenze) wird ja versucht "alles" in die Textdatei zu schreiben
obwohl z.b. nur in den ersten 10 Bytes von jedem Element etwas drinnen steht.

also muss ich irgendwie die String Elemente mit Leerzeichen oder sowas füllen damit später meine Textdatei/CSV-Datei erkennt das die leer sind.
 
FB_FileWrite schreibt nicht 101 einzelne Strings, sondern den gesamten durch das Stringarray belegten Speicherplatz, also auch die Stringheader und die unbeschriebenen Bytes zwischen den Strings.

Du müsstest
- entweder die Array-Strings zu nur einem String zusammenfassen (z.B. mit CONCAT) und diesen an FB_FileWrite übergeben (pWriteBuff:= ADR(WriteString) + 2)
- oder alle Strings auf die gleiche Länge mit Füllzeichen/Leerzeichen auffüllen und das Array exakt so groß als Array of Byte deklarieren und die Strings ohne die Stringheader-Bytes in das Array kopieren.

Harald
 
Danke Harald,

genau sowas dachte ich mir.
da bei 100 Messwerten der String relativ schnell voll wäre und ich dann mehrere einzelne Schreibvorgänge benötigen würde, versuche ich deine 2te Möglichkeit anzuwenden.

Mit Freundlichen Grüßen

Morris
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo, Morris!
Du solltest 2 Tasks anlegen. Eine mit 400ns. Diese Task ruft dann ein Programm auf, welches einfach nur deine Daten in ein Array schreibt. Diese Task mit Prio 0.
Eine weitere Task mit 40ms ruft dann ein Programm auf, was sich um das um das schreiben der Strings in eine Datei kümmert. Prio 1.
Damit solltest Du Deine Timing Probleme im Griff haben.
 
Zurück
Oben