# CSV-Datei auf SD-Karte schreiben bei einer Wago PFC200



## Etty (13 April 2017)

Hallo zusammen,

für mein Projekt soll ich Daten vom CANbus in regelmäßigen abständen auf eine SD-Karte schreiben mithilfe einer Wago 750-8203. Leider habe ich das Problem das mit meinem Code der Schreibvorgang extrem lange dauert, denn wenn möglich soll ich alle 10ms einmal die Daten loggen, doch bei mir wird höchstens jede Sekunde einmal in die Datei geschrieben.
Das Projekt muss ich in Codesys 3 schreiben, daher kann ich "WAGO_Datalogger_02.lib" nicht verwenden, da diese library wohl nur in Codesys 2 funktioniert.
Ich habe das "FileUtilitiesExample.package" aus dem Codesys Store als Template verwendet, der Code sieht in etwa wie folgt aus:


CASE istate OF0: FileOpen(...)​IF FileOpen.xDone THEN​istate:=1;​END_IF​1:FileWrite(...)​IF FileWrite.xDone THENistate:=2;​END_IF​2: FileClose(...)IF FileClose.xDone THEN​istate:=3;​END_IF​3: xError := FALSE;​END_CASE

Der Code wird auch im Tempo meines Timerbausteins wiederholend ausgeführt, doch bis die Daten letztendlich in der CSV Datei gespeichert sind dauert es wesentlich länger und man kann auch nicht einsehen, wann Linux den schreibvorgang beendet hat. 
Gibt es also eine Möglichkeit den Code zu ändern oder eine bessere Variante den Schreibvorgang umzusetzen? 
Denn selbst in der Beschreibung der "WAGO_Datalogger_02.lib" heißt es: "speichert Eintraege [...] in einem Intervall von min. einer Sekunde in eine CSV-Datei"

Vielen Dank für jegliche Lösungsansätze.

Etty


----------



## oliver.tonn (13 April 2017)

Den Datenlogger soll es für e!Cockpit laut WAGO so ab KW35 geben, wie in diesem Thread nachzulesen ist.
Die Schreibvorgänge werden immer mit einer relativ niedriegen Priorität ausgeführt und dauern relativ lange. Was Du machen könntest ist Dir zwei Arrays anzulegen. In das eine Array schreibst Du die CAN-Daten, sobald dieses voll ist kopierst Du den Inhalt mit memcpy (Dies geht relativ schnell) in das andere Array. Anschließend schreibst Du den Inhalt des zweiten Arrays in eine Datei. Damit solltest Du genügend Zeit gewinnen, damit das zeitlich klappt.

Gruß

Oliver


----------



## .:WAGO::0100146:. (13 April 2017)

Hallo Etty,

in e!COCKPIT kannst du die Bibliothek WagoAppDatalogger verwenden um Daten auf der SD-Karte zu schreiben, allerdings, wie du schon gesagt hast, nur mit minimal 1 Sekunde.
Wenn du alle 10ms Daten schreiben möchtest würde ich dir empfehlen Daten zu sammeln und diese dann als Block zyklisch zu schreiben.


----------



## oliver.tonn (13 April 2017)

Mein Reden.

Von irgendwas mit Internetzugang gesendet


----------



## Etty (13 April 2017)

Danke für die schnelle Antwort Oliver.Tonn,

leider darf ich e!cockpit nicht für mein Projekt benutzen sondern muss dieses in Codesys 3 schreiben (Vorgabe meines Profs). Mit mehreren Arrays das ganze zu lösen ist auf jeden fall eine gute Idee, nur löst sich dadurch noch nicht mein Problem der Datenmenge und der schreibverzögerung, wenn man z.B. 30 Minuten lang alle 10ms Daten loggen will sind das 180 000 Schreibvorgänge. 
Dafür bräuchte man erstmal eine Menge Arrays um die Daten zu behalten bis sie geschrieben sind und das Schreiben selber würde c.a. 50 Stunden dauern...
Klingt wohl so als ob das schreiben auf eine SD-Karte nicht für solche Zwecke ausgelegt ist.

Etty


----------



## oliver.tonn (13 April 2017)

Nö, dauert es nicht. Du darfst nicht den Fehler machen und das ganze linear rechnen. Wenn 10Bytes schreiben 1 Sekunde dauert, dauern 1000 Bytes nicht 100 Sekunden.
Und Du sollst ja auch nicht den ganzen Log in ein Array schreiben, sondern immer nur einen Teil, diesen dann in ein anderes kopieren und wegschreiben und im ersten weiterloggen. Man kann an eine Datei doch auch Daten anhängen.


----------



## Etty (13 April 2017)

Aber wenn ich in einem Array die Daten logge (Arrays sind ja nicht länger als 1000 Einträge wie ich das in Codesys sehe) und dann diese 1000er Blöcke in das zweite Array kopiere werden diese ja nicht schnell genug auf die SD Karte geschrieben, sodass sich Daten Aufstauen. Und ich nutze den Mode "Append" um die einzelnen Zeilen des Arrays auf die SD-Karte zu schreiben. Oder gibt es evtl. eine Möglichkeit nicht nur einzelne Zeilen auf die SD-Karte zu schreiben sondern direkt das ganze Array?

Etty


----------



## oliver.tonn (13 April 2017)

Wo hast Du denn die Infos mit der 1000 her? Das halte ich für ein Gerücht. Wie viele Bytes fallen denn pro 10ms an?


----------



## Etty (13 April 2017)

Codesys zeigt mir im eingeloggten Zustand immer nur 1000 Werte an, auch wenn ich ein größeres Array definiert habe. Oder wie groß können Arrays werden? 
Eine array-Zeile ist z.B. :"35;0.5;23.99;0.01;1.99;1.0;11;19.0;0;DT#2017-04-13-09:18:04", szSize hat den Wert "61" falls das weiterhilft. Ich weiß leider nicht wie genau ich herausfinden kann wieviele Bytes so eine String lang ist. 

Etty


----------



## oliver.tonn (13 April 2017)

Laenge := LEN(StringVar);


----------



## Etty (13 April 2017)

Dann ist das schon "szSize" aus dem Template, also bei mir z.b. "61". Kann sich dieser wert ändern falls der CANbus größere Werte ausgibt oder mein "Arraycounter" (Erste Zahl des Strings, im bsp. ist es "35") ansteigt? 

Etty


----------



## oliver.tonn (13 April 2017)

Die Zahl gibt nicht die Gesamtgröße des Strings an, sondern den von einem String tatsächlich benötigten Platz. Die Funktion zählt bis zum ersten Auftreten von 00hex, was als Stringende interpretiert wird. Also um Deine Frage zu beantworten, ja, sie kann sich ändern.


----------



## Etty (13 April 2017)

Danke für die Infos Oliver,

Es ist ja wie ich bisher Gelesen habe nur möglich Strings mit einer maximallänge von 255 zu schreiben. Da sollte ich wohl nicht mehr als zwei bis drei Zeilen auf einmal schreiben.
Kann ich also ein Array mit mehr als 1000 Einträgen erstellen? leider finde ich auch darauf keine Antwort über Google.

Etty


----------



## oliver.tonn (13 April 2017)

Strings können länger sein, nur die Standard Stringfunktionen unterstützen nur Strings bis 255 Zeichen, allerdings gibt es neue Funktionen für längere Strings. Ich weiß jedoch nicht ob es diese auch im reinen Codesys gibt.


----------



## Etty (13 April 2017)

Danke für die Hinweise Oliver,

dann werde ich mal die Maximalgrenzen eines Strings zum schreiben in eine Datei austesten um die Anzahl der schreibbefehle zu verringern.

Etty


----------



## oliver.tonn (13 April 2017)

Bezüglich der Anzeige von Arrays schau mal bei den Optionen nach, kann sein das die Anzahl der angezeigten Arrayeinträge begrenzt werden kann.


----------



## Etty (13 April 2017)

Habe mal ein wenig die Strings optimiert und schreibe jeweils 3 array-Zeilen in einen String, doch leider scheint dieser maximal ein 255er String zu sein. Deklarationen wie String(1023) verändern nicht die Länge des Strings zum schreiben, es wird der Rest nach 255 einfach abgeschnitten. Damit sind zumindest Datenlogs alle 100ms möglich.
Aber es scheint so, als ob Codesys Arrays wirklich nur 999 Zeilen lang sind, habe meine Arrays auf 10 000 Einträge verlängert doch in meiner CSV-Datei stehen trotzdem nur 999 Werte.

Etty


----------



## oliver.tonn (13 April 2017)

Wie ermittelst Du denn die Länge zum Wegschreiben?

Von irgendwas mit Internetzugang gesendet


----------



## Etty (13 April 2017)

Falls du die Länge des Strings meinst den ich weg schreibe, diese Länge ermittel ich gar nicht. Ich habe zur Sicherheit nur 3 Zeilen meines arrays in einen String geschrieben, da meine Zeilen ja im schnitt 60-70 Zeichen lang sind. 
Ansonsten habe ich zwei Arrays mit jeweils 10 000 Einträgen erstellt und array1 wird in array2 kopiert wenn array1 voll ist. 
array2 wird dann auf die SD-Karte geschrieben und array1 wieder von der ersten Zeile an überschrieben.
Da jeder neue Array Eintrag einen Counter hochzählen lässt sieht man schnell wie viele Einträge am Ende in der CSV-Datei stehen.
Letztendlich habe ich beide Arrays wieder auf 1000 Einträge reduziert, da es keinen unterschied macht wenn man diese größer deklariert.

Etty


----------

