Problem mit: FB_CSVMemBufferWriter

naheliegend

Level-1
Beiträge
87
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi,

mein Anliegen ist für euch bestimmt eine Kleinigkeit.

Was ich haben möchte:

Daten von der Klemme -> Berechnungen -> ins .csv File schreiben -> Excel/Matlab Auswertung

Problem ist es, die berechneten Daten in ein .csv File zu schreiben.

Wenn ich: FB_CSVMemBufferWriter ( https://infosys.beckhoff.de/index.p...PlcLibUtilities_FB_CSVMemBufferWriter.htm&id= )
verwenden möchte, dann brauche ich die Daten in Byteform?
(pValue: Optional: Adresse eines externen Bytepuffers in dem sich das neue Datenfeld befindet. (...) )

Wie bekomme ich denn REALs oder LREALs in BYTEs ? Oder verwende ich den ganzen Baustein falsch?

Und: pBuffer: Adresse (Pointer) auf die Zielpuffervariable muss dann wahrscheinlich auch ein BYTE Array sein, oder?

Viele Grüße
 
csv ist ebenfalls ein textbasiertes format.
Das heißt Du kannst jede beliebige Zahl - zum String konvertiert - verwenden. Strings sind ja eine aneinanderreihung von Bytes.
In dem Membuffer legst Du den formatierten String also ab. Formatiert heißt: Spaltenteilungen fügst Du nach jedem Wert als Komma oder Semikolon ein. Das Ende einer Zeile wird mit CRLF abgeschlossen. Nullbytes werden in der Regel von auswertenden Programmen ignoriert. Schöner ist's, nullbytes vorher zu entfernen.

Mit dem FB_Formatstring könntest Du zum Beispiel mehrere Werte mit Trennzeichen aneinanderreihen, mit einem Zeilenende versehen und in den Bytepuffer schreiben.

IMHO wäre also erstmal wichtig, die Struktur festzulegen, in der die Auswertung die Daten erwartet. Anschließend machst Du Dir Gedanken, wie die Daten in der SPS genauso formatiert werden und als letztes schreibst Du das dann auf den Datenträger.

Ich hab mal die Suche bemüht:
Beckhoff -> Array of LREAL in CSV exportieren
Zu Langsames erstellen einer .csv Datei und deren Export

Jeweils mit Codebeispielen.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
An sich ist mir das Format egal, solange ich es später in Excel und Matlab auslesen kann.

Mein Problem ist aber, dass ich REAL Werte aus der Klemme in einem Array erhalte. Wie schreibe ich diese denn zu einem sogenannten BytePuffer zusammen?

Der BytePuffer ist dann irgendwie: ARRAY [0..1000] OF BYTE ... jetzt sind meine REAL Werte aber 0,1 oder so, brauchen also mehr als 1 Byte. Mit dem cbValue sage ich ihm, dass mein BytePuffer nach 3 Byte mit Simikolon separieren soll und das ganze dann in den dataBuffer schreiben soll vom Typ ? Auch ARRAY [0..1000] OF BYTE ?
 
Messwerte von Start bis Ende der Messung nach Excel exportieren

Beim FB_Formatstring kannst Du Formatierungsoptionen vorsehen. Damit kann dann ein Real-Wert zum Beispiel auf eine Nachkommastelle gekürzt werden.
Willst Du Dich unbedingt auf eine feste Länge der zum String umgewandelten Real-Werte einlassen? Kann der Bereich vor demKoma sicher nicht zweistellig werden?
IMHO besser ist es, den Bytepuffer groß genug für den WorstCase zu machen und bei Schreibvorgang ins File jeweils die aktuelle Länge zu bestimmen (LEN() ).

In den nunmehr 3 verlinkten Threads findest Du jede Menge Tipps auf vielen Niveauebenen und weitere Verlinkungen zu hilfreichen Quellen. Ich schlage vor, Du ackerst das mal eben durch.

Edit: Ja klar sind Real-Werte wie zum Beispiel 0,1 3 Byte lang, 10,1 schon 4Byte. Das stellst Du dann ja fest, wenn Du mit Len die Länge bestimmst. Die Länge des Bytepuffers benötigst Du ja ohnehin am Schreibbaustein. Dabei ist es ungünstig, immer den kompletten Puffer zu schreiben, da dessen (gültige) Länge jeweils unterschiedlich ist.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren

Danke.

Was ich noch nicht 100% verstehe ist folgendes:

Code:
3:(* Convert one PLC record to CSV format *)
        fbWriter.eCmd := eEnumCmd_First;(* Write first field value *)
       
    FOR nRow := 1 TO 10000 BY 1 DO


        str_Power:=LREAL_TO_STRING(gvl.Power[nRow]);   //LREAL WERT ZU STRING VERWANDELN
                sCSVField := STRING_TO_CSVFIELD( str_Power, FALSE );(* TODO: Get field value from your application *) // STRING IN CSVFIELD VERWANDELN

                (* Add new field to the record buffer *)
                fbWriter(     pBuffer := ADR( sCSVLine ), cbBuffer := SIZEOF( sCSVLine ), putValue := sCSVField, pValue := 0, cbValue := 0,
                            bCRLF := TRUE);(* 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... *)

Also gvl.Power ist ein Array [0..10000] OF LREAL , also ein Vektor. Jetzt wird zunächst jede Reihe einzeln durchgegangen. D.h. , dass jeder Wert einzeln abgefrühstückt wird. Der Wert wird in einem String verwandelt und dann in ein CSV Field Format verpackt.

Dann wird dieses CSVField-Format (Wo ja nur Informationen über ein LREAL Wert drin stehen) in ein CSV Feld geschrieben und mit dem bCRLF Befehl beendet. D.H. man erzeugt für jeden einzelnen Wert einen neues Datensatz? Das ist doch übertrieben, da es doch ausreicht für jeden Wert ein Datenfeld zu generieren... ?

Das wird dann für den ganzen gvl.Power array wiederholt, sodass man am Ende alle Werte in einer csv Datei stehen hat?
 
Ungetestet, aber in der Form:
Code:
csvString := '';

FOR i:=1 TO 19 DO
   csvString := CONCAT(csvString, REAL_TO_STRING(realArray[i]);
   csvString := CONCAT(csvString, ';');
END_FOR

csvString := CONCAT(csvString, REAL_TO_STRING(realArray[20]);
csvString := CONCAT(csvString, '$N'); //LineFeed

//Schrittkette zum schreiben der Datei:
IF bSaveCsv THEN
   //Step 1: Datei öffnen
   fbFileOpen(sPathName:='C:\Temp\Test.csv', nMode:=FOPEN_MODEAPPEND);
   //Step 2: Zeile schreiben
   fbFilePuts(hFile:=fbFileOpen.hFile, sLine:=csvString);
   //Step 3: Datei schließen
   fbFileClose(hFile:=fbFileOpen.hFile);

   bSaveCsv := FALSE;
END_IF

Dabei ist natürlich auf die maximale STRING Länge von 255 Zeichen zu achten.
Bei 1000 REAL Werten müsste man die Schreibfunktion dann ca. 50 mal ausführen und danach erst ein LineFeed $N hinzufügen.
 
... Dann wird dieses CSVField-Format (Wo ja nur Informationen über ein LREAL Wert drin stehen) in ein CSV Feld geschrieben und mit dem bCRLF Befehl beendet. D.H. man erzeugt für jeden einzelnen Wert einen neues Datensatz? Das ist doch übertrieben, da es doch ausreicht für jeden Wert ein Datenfeld zu generieren... ? ...
D.h. Du hast den Tipp ...
... IMHO wäre also erstmal wichtig, die Struktur festzulegen, in der die Auswertung die Daten erwartet. Anschließend machst Du Dir Gedanken, wie die Daten in der SPS genauso formatiert werden und als letztes schreibst Du das dann auf den Datenträger. ...
... übersprungen?!?
Eine ExcelTabelle, die aus nur 1 Spalte besteht, dürfte genauso übertrieben (um nicht zu sagen: überflüssig) sein, wie eine, die nur aus 1 Zeile besteht.
Du könntest ja auch erstmal überlegen, wie die ExcelTabelle aussehen soll und in Excel ein paar TestDaten eingeben und den Krempel aus Excel im CSV-Format exportieren - dann kannst Du Dir mal die CSV-Datei ansehen und hast ein Beispiel, was die SPS ausgeben könnte/sollte.
Ruhig mal das Pferd von hinten aufzäumen! ;o)
Gruss, Heinileini
 
Ne, ich habe nur keine Ahnung, wie man mit den Befehlen zum Beispiel mehrere LREAL mit Semikolon getrennt in eine csv Datei schreibt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Man schreibt ja mehrere Datenfelder nebeneinander, getrennt mit Semikolon. Ein Datenfeld ist für mich ein einzelner Wert aus der Klemme. Zeilenweise werden dann diese Datensätze, bestehend aus mehren Datenfeldern geschrieben? Ist das so korrekt? Demnach würde ich gerne so etwas haben wollen:

Messung1;Wert1.1;Wert1.2;Wert1.3;...Wert1.n ;
Messung2;Wert2.1;Wert2.2;Wert2.3;...Wert2.n ;
Messung2;Wert3.1;Wert3.2;Wert3.3;...Wert3.n ;
..................
Messung m ; ............Wert m.n ;


Mein Problem ist, dass ich nicht weiß, wie ich die einzelnen Datenfelder erzeuge, bzw sage, dass ein Wert ein Datenfeld ist und er die dann im Semikolon trennen soll.
Das Datensätze untereinanderschreiben bekomme ich bereits hin, aber nur für einzelne Werte...
 
Zuletzt bearbeitet:
Zurück
Oben