DLOG_STORE_FILE_CSV für Hochfrequente Daten

Begonnen von richard.barkoczy, 24. April 2020, 11:16:01

Vorheriges Thema - Nächstes Thema

0 Mitglieder und 2 Gäste betrachten dieses Thema.

richard.barkoczy

Hallo,

ich würde gerne einen LOG von hochfrequenten Daten machen, falls einen Event auftritt. Daten würde ich gerne mit 20KHz schreiben (20x in einer ms).
Bei einem Takt von 1ms würde ich einen Array mit 20 Werten von einem Sensor bekommen (oversampling). Diese Werte soll ich in einer Datei schreiben.

Ich versuche gerade die Funktion DLOG_STORE_FILE_CSV dafür anzupassen bin auf folgende Probleme/Lösungen gekommen.

Problem1:TRIG_M muss in einem Zyklus TRUE sein und im nächsten FALSE, damit Daten geloggt werden. Somit kann ich könnte ich max. jede 2ms loggen (be einem takt von 1ms).

Lösung1: Dafür habe ich die Idee geahabt eine FOR schleife zu machen, in der inerhalb einen Zyklus (1ms) TRIG_M alternierend geschaltet wird. Somit habe ich geschaft eine LOG frequenz von über 1KHz.

Beispiel1:
FOR idx := 1 TO idx_MAX DO
   IF idx = idx_MAX OR  idx = 1 THEN
      //do not trigger in the first and last round
      b_TRIGGER_M := FALSE;
   END_IF
   
   fb_DLOG_DT(X:=X, COLUMN:='Timestamp'); 
   
        fb_DLOG_REAL(X:=X, VALUE:= arr_VALUE1[idx], COLUMN:=COLUMN1, N:=2);

   fb_DLOG_REAL(X:=X, VALUE:= arr_VALUE2[idx], COLUMN:=COLUMN2, N:=2);
                  
   fb_DLOG_STORE_FILE_CSV(X:=X, SAVE_DATA:=save_data, ENABLE:=b_enable_log, TRIG_M:=b_TRIGGER_M, TRIG_T:=T#1H, SEP:=59,
        FILENAME:= 'TestFile#R.csv', DTI:=dt_Current, AUTO_CLOSE:= T#10MS, ERROR_C=>error_c, ERROR_T=>error_t);
   
   b_TRIGGER_M := NOT b_TRIGGER_M; //Alternate b_TRIGGER_M
   
END_FOR

Problem2: Bei der umsetzung von Lösung1 stöße bei einem zweiten Problem. Je nach Anzahl an variablen die ich zufüge (VALUE1, 2, usw.) oder je nach anzahl an LOGs pro takt (idx_MAX), wird der Buffer voll (error_c=2, error_t=6). Es sieht so aus das AUTO_CLOSE nicht Funktioniert, da die größe der währed 1min sich nicht ändern, erst nachdem der Name der Datei geändert wird. Wie kann hier der Buffer geleert werden?

Hat jemand eine Idee wie ich am besten hinkriege die Logs mit solcher auflösung zu speichern?
Ich benutze gerade OSCAT NETWORK 1.35

Schöne Grüße,
Richard

peewit

Hallo

Für das was du machen möchtest benötigst du eine hochperformante Steuerung
Was verwendest du denn überhaupt für eine ?

Ein Grundproblem ist das alles unter 1ms mal prinzipiell nicht vorgesehen ist
Das Problem mit TRIG_M - Positive Flanke ist real keines denn damit du so etwas machen kannst benötigst du so wieso eine Steuerung die weit unter ms arbeitet
du kannst auch theoretisch den datalog baustein einfach zweimal hintereinander aufrufen mit TRIG_M 0 / 1

Wenn du wirklich im 1ms takt loggen möchtest musst du sowieso einen task wählen der ein vielfaches schneller aufgerufen wird als 1ms

Was hinzukommt ist das der datenlogger beim daten speichern und beim schreiben des datenbuffers in eine Datei asynchron arbeitet
und diese vorgänge viele zyklen benötigen

bei den meisten steuerungen ist das Dateisystem relativ langsam angebunden sodass du mehr daten produzierst als überhaupt schnell genug gespeichert werden können


Das was du programmiert hast ist so nicht funktionsfähig

Für jeden Wert den du loggen willst benötigst du einen eigene Bausteininstant
du hast jedoch in deinem Code den  fb_DLOG_REAL zweimal drinnen mit der gleichen Instant
somit wird auch die anzahl der datenspalten korrekt erkannt

Auch das mit den beiden for schleifen kann ich nicht nach vollziehen

du solltest mal beginnen mit einen normalen sauberen programm das mal prinzipiell funktioniert und vorab mal nur alle 10 sekunden etwas loggt
er wenn das korrekt funktioniert solltest du an die optimierungen machen und die zeiten herabzusetzen
irgendwann wist du vermutlich merken das die sps die daten nicht schnell genug speichern kann und es zu fehlern dadurch kommt


schau dir doch mal die vorhandenen datalogg demo bausteine in (FUP geschrieben) an


Für das loggen in ms takt benötigst du wie gesagt eine hochperformante sps oder eine log-funktion innerhalb der steuerung
Hast du mal ausgerechnet wieviele bytes du pro sekunde im log-file produzierst ?


richard.barkoczy

#2
Hallo,

vielen Dank für die schnelle Antwort. Die Log-Funktion benötige ich für eine Maschine die hoch-frequent betrieben wird. Diese Funktion soll nur in bestimmten Szenarien aktiviert werden und soll nicht dauerhaft laufen.

Der Code der oben zu sehen ist, habe ich schnell angepasst um hier ins Forum zu posten. Da habe ich jetzt selber schon ein paar Fehler gesehen. Der original Code funktioniert, aber bei etwa mehr als 3 Logs pro ms bekomme ich Probleme.

Die Idee mit dem FOR Loop war um mehrere schritte in eine ms zu machen. Alternativ könnte ich auch mein Base time zu z.B. 100 Mikrosekunden senken. Würde das mehr helfen als ein FOR Loop zu machen? Aktuell benutze ich eine Steuerung von Beckhof CX5130.

Bei meinem Code konnte ich die gleiche Instanz von fb_DLOG_REAL ohne Probleme benutzen um verschiedene Spalten (COLUMN) zu schreiben. Gibt es Probleme die gleiche Instanz zu benutzen wenn COLUMN nicht gleich ist?

Das Demo Programm habe ich mir angeschaut und schaffe auch das ganze ohne Probleme zu betreiben mit Logs über 2ms. Um schnellere Logs zu machen musste ich viele Anpassungen machen aber kriege es nicht schneller als 3 logs pro ms.

Eine andere Idee wäre das ganze in einem WHILE LOOP zu setzen bis die variablen in der CSV geschrieben wurden oder der Buffer leer ist. Gibt es eine Variable die ich mir anschauen kann zu sehen ob die Werte in der CSV geschrieben wurden? Mach diesen Beispiel hier unten Sinn?


b_TRIGGER_M wird mittels einen Clock jede 0,1ms getriggert  => log in 10kHz

fb_DLOG_DT(X:=X, COLUMN:='Timestamp');
fb_DLOG_REAL(X:=X, VALUE:= arr_VALUE1, COLUMN:=COLUMN1, N:=2);
fb_DLOG_STORE_FILE_CSV(X:=X, SAVE_DATA:=save_data, ENABLE:=b_enable_log, TRIG_M:=b_TRIGGER_M, TRIG_T:=T#1H, SEP:=59,
        FILENAME:= 'TestFile#R.csv', DTI:=dt_Current, AUTO_CLOSE:= T#10MS, ERROR_C=>error_c, ERROR_T=>error_t);

b_VALUES_WRITTEN muss irgend woher gelesen werden um zu wissen ob Werte in der CSV geschrieben wurde. Woher weißt man ob die Werte in der CSV geschrieben sind ?

While NOT b_VALUES_WRITTEN DO
    //leave trigger at FALSE so last values are written to CSV
    b_TRIGGER_M := FALSE;

    fb_DLOG_DT(X:=X, COLUMN:='Timestamp');
   
    fb_DLOG_REAL(X:=X, VALUE:= arr_VALUE1, COLUMN:=COLUMN1, N:=2);

    fb_DLOG_STORE_FILE_CSV(X:=X, SAVE_DATA:=save_data, ENABLE:=b_enable_log, TRIG_M:=b_TRIGGER_M, TRIG_T:=T#1H, SEP:=59,
        FILENAME:= 'TestFile#R.csv', DTI:=dt_Current, AUTO_CLOSE:= T#10MS, ERROR_C=>error_c, ERROR_T=>error_t);
   
    b_VALUES_WRITTEN  muss hier aktualisiert werden
END_WHILE   
   




mattsches

Hallo Richard,

das Problem ist - wie von peewit schon erwähnt - dass das Schreiben ins Dateisystem zu langsam ist. Selbst wenn du den Baustein ausbremsen könntest, bis der Schreibvorgang abgeschlossen wurde (was ich gerade nicht weiß), dann hilft dir das nichts. Denn dann erreichst du die erforderliche Zykluszeit erst recht nicht.

Spontan sehe ich nur die Möglichkeit, für die wie du ja sagst begrenzte Zeit die Daten in Variablen, also den RAM zu schreiben. Das ist synchron möglich, setzt aber natürlich entsprechend Arbeitsspeicher voraus. Diese Puffervariablen könntest du dann im Anschluss ins Dateisystem schreiben.

Gruß,
mattsches