String mit Timer in CSV Datei schreiben.

umpalumpa

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

ich habe ein Problem dabei, einen Sting, in den ich fortlaufend die Werte meiner analogen Eingangsklemmen schreiben lasse (Wert1;Wert2;Wert3;...;$r) in eine CSV Datei zu speichern.
Ich möchte, dass alle 5 Sekunden der String sozusagen 'eingefrohren' per filePuts in die CSV geschrieben wird, aber leider werden bei mir immer noch viel zu viele Werte in die Datei geschrieben.
Habe vorher im Forum schon ein paar nützliche Sachen gefunden, aber hier komme ich leider nicht weiter.
Könnte mir da jemand auf die Sprünge helfen?


Anbei mal der Teil des Codes:

Code:
 3: (* Konvertiere PLC Datenzeile in CSV Format und schreibe eine Zeile + Timer am Ende *)
        startNewRow := TRUE;
        fbFileOpen( bExecute := FALSE, bError => bError, nErrID => nErrID, hFile => hFile );
        IF NOT fbFileOpen.bBusy THEN
            IF NOT fbFileOpen.bError THEN
                IF CSVstop THEN step :=10; ELSE                                                                           (*CSVstop wird durch einen Cursor in der VISU aktiviert, zum Anhalten der Aufzeichnung *)
                          sCSVLine := '';
                          sCSVField :=STRING_TO_CSVFIELD( STRING_FUER_CSV , FALSE );
                          sCSVLine := sCSVField;
    IF RIGHT( sCSVLine, 10 ) = '$r$n' THEN
                   sCSVLine := REPLACE( sCSVLine, '$L', 10, LEN( sCSVLine ) - 1 );
                     END_IF
                              fbFilePuts( bExecute := FALSE );
                              fbFilePuts( sNetId := sNetId, hFile := hFile, sLine := sCSVLine, bExecute := TRUE );
                                  fbFilePuts( bExecute := FALSE );
            (*  startNewRowTON(IN := startNewRow, PT :=Aufzeichnungsintervall );
                             startNewRow := NOT startNewRowTON.Q;                                                           *)
                                     IF startNewRowTON.Q THEN
                                                       step := 4;
                                       END_IF
                END_IF
            ELSE(* Fehler: Datei nicht gefunden? *)
                step := 100;
            END_IF
        END_IF


4: (* Kleine Verzögerung, damit Werte nicht kontinuierlich geschrieben werden *)
                IF CSVstop THEN step :=10; ELSE
                                     startNewRow := FALSE;
                    IF NOT Fortsetzen THEN                                                         (*Fortsetzen ist der Ausgang eines TONOF mit Ausschaltverzögerung 10ms, weil sich sonst der Ausgang von startNewRowTON nicht resettet hat)
                             step := 3;
                             END_IF
                END_IF

Gruß,

Lars
 
Deine Schrittkette bleibt bei Schritt 3, bis der startNewRowTON abgelaufen ist. Solange wird in jedem SPS-Zyklus eine Zeile in die Datei geschrieben, sofern der vorangegangene fbFilePutS-Befehl abgeschlossen ist.
Ausserdem legst Du Dir mit dem bedingten Aufruf des startNewRowTON die Karten.
Also:
Schritt 3: Nur einmal mit fbFilePutS schreiben und sofort weiter nach Schritt 4
Schritt 4: Abfrage auf NOT fbFilePutS.bBusy und NOT fbFilePutS.bError so wie Du das schon beim fbFileOpen machst, dann weiter nach Schritt 5
Schritt 5: Warten auf startNewRowTON.Q, weiter nach Schritt x
Den startNewRowTON aus der CASE-Verzweigung rausnehmen und in jedem SPS-Zyklus aufrufen:
startNewRowTON(In:=Schritt=5,Pt:=Aufzeichnungsintervall)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo StructuredTrash,

danke für die schnelle Antwort. Ich hab nun die Schritte so angepasst, wie du es empfohlen hast, aber ich weiß nicht genau, warum ich den startNewRowTON aus der CASE-Verzweigung rausnehmen soll, bzw. wo der stattdessen reingesetzt werden muss. An sich läuft der in meinem MAIN-Programm(CFC) mit.
Nun sieht das ganze so aus, aber er schließt nun nicht einmal mehr die CSV Datei, also kommt er bei Schritt 10 nicht an oder? :

Code:
3: (* Konvertiere PLC Dateinzeile in CSV Format und schreibe eine Zeile + Timer am Ende *)
        startNewRow := TRUE;
        fbFileOpen( bExecute := FALSE, bError => bError, nErrID => nErrID, hFile => hFile );
        IF NOT fbFileOpen.bBusy THEN
            IF NOT fbFileOpen.bError THEN
                IF CSVstop THEN step :=10; ELSE
                          sCSVLine := '';
                          sCSVField :=STRING_TO_CSVFIELD( STRING_FUER_CSV , FALSE );
                          sCSVLine := sCSVField;
    IF RIGHT( sCSVLine, 10 ) = '$r$n' THEN
                   sCSVLine := REPLACE( sCSVLine, '$L', 10, LEN( sCSVLine ) - 1 );
                     END_IF
                              fbFilePuts( bExecute := FALSE );
                              fbFilePuts( sNetId := sNetId, hFile := hFile, sLine := sCSVLine, bExecute := TRUE );
                                                                 (*IF startNewRowTON.Q THEN
                                                                         step := 4;
                                                          END_IF *)
                                   step:=4;
                END_IF
            ELSE(* Fehler: Datei nicht gefunden? *)
                step := 100;
            END_IF
        END_IF

 4: (* Warte bis filePuts fertig, dann abbrechen *)
                 IF NOT NOT fbFilePutS.bBusy THEN
                      IF NOT fbFilePutS.bError THEN
                           fbFilePuts( sNetId := sNetId, hFile := hFile, bExecute :=FALSE );
                           IF CSVstop THEN step :=10; ELSE
                           step := 5;
                           END_IF
                      END_IF
                END_IF
 5: (* Kehre nach Ablauf des Timers zurück zu Step 3, bis die Aufnahme abgebrochen wird *)
      IF NOT CSVstop THEN
  IF  startNewRowTON.Q THEN
                                     startNewRow := FALSE;
                             step := 3;
           END_IF
           ELSE step := 10;
      END_IF
 
Er kommt auf jeden Fall bis zu Schritt 4. Der Codeausschnitt kommt aus einem FB, den ich von Anfang an mitlaufen lasse. Kann man das so nicht machen?

Kompletter FB:

Code:
FUNCTION_BLOCK CSV_SCHREIBER_FB
VAR_INPUT
 wert:BOOL:=1;
END_VAR
VAR_OUTPUT
END_VAR
VAR
    sNetId            : T_AmsNetId := '';  
    sFileName    : T_MaxString := 'D:/';(* CSV Speicherort *)
    sCSVLine        : T_MaxString := '';
    sCSVField        : T_MaxString := '';
    bBusy            : BOOL;
    bError            : BOOL;
    nErrId            : UDINT;
    hFile            : UINT        := 0
    step            : DWORD     := 0;
    fbFileOpen    : FB_FileOpen;
    fbFileClose    : FB_FileClose;
    fbFilePuts        : FB_FilePuts;
    String2: STRING(255) :='Kopfzeile';          (* Kopfzeile für CSV Datei*)
END_VAR
-----------------------------------------------------------------------------------------------------------

IF wert THEN
CASE step OF
    0:(* Warte auf Steigende Flanke an bWrite ( Cursor 1 betätigen) *)
        IF bWrite THEN
            bWrite         := FALSE;
            bBusy         := TRUE;
            bError         := FALSE;
            CSVstop    :=FALSE;
            nErrId          := 0;
            hFile            := 0;
            step             := 1;
        END_IF

    1:(* Öffnet oder erstellt source Datei *)
        fbFileOpen(  bExecute := FALSE  );
        fbFileOpen(     sNetId := sNetId, sPathName := sFileName, nMode := FOPEN_MODEWRITE,           (* Öffnet Datei oder überschreibt sie, wenn sie bereits vorhanden ist! *)
                        ePath := PATH_GENERIC, bExecute := TRUE );
        step := 2;

    2:(* Warte bis fbFileOpen not busy / Kopfzeile einfügen *)
        fbFileOpen( bExecute := FALSE, bError => bError, nErrID => nErrID, hFile => hFile );
        IF NOT fbFileOpen.bBusy THEN
            IF NOT fbFileOpen.bError THEN
                          sCSVLine := '';
                          sCSVField := STRING_TO_CSVFIELD( String2, FALSE );
                          sCSVLine := sCSVField;
                              fbFilePuts( bExecute := FALSE );
                              fbFilePuts( sNetId := sNetId, hFile := hFile, sLine := sCSVLine, bExecute := TRUE );
                                        step := 3;
            ELSE(* Fehler: Datei nicht gefunden? *)
                step := 100;
            END_IF
        END_IF
 3: (* Konvertiere PLC Dateinzeile in CSV Format und schreibe eine Zeile + Timer am Ende *)
        startNewRow := TRUE;
        fbFileOpen( bExecute := FALSE, bError => bError, nErrID => nErrID, hFile => hFile );
        IF NOT fbFileOpen.bBusy THEN
            IF NOT fbFileOpen.bError THEN
                IF CSVstop THEN step :=10; ELSE
                          sCSVLine := '';
                          sCSVField :=STRING_TO_CSVFIELD( STRING_FUER_CSV , FALSE );
                          sCSVLine := sCSVField;
   
                              fbFilePuts( bExecute := FALSE );
                              fbFilePuts( sNetId := sNetId, hFile := hFile, sLine := sCSVLine, bExecute := TRUE );
                                                              
                                   step:=4;
                END_IF
            ELSE(* Fehler: Datei nicht gefunden? *)
                step := 100;
            END_IF
        END_IF

 4: (* Warte bis filePuts fertig, dann abbrechen *)
                 IF NOT  fbFilePuts.bBusy THEN
                      IF NOT fbFilePuts.bError THEN
                           fbFilePuts( sNetId := sNetId, hFile := hFile, bExecute :=FALSE );
                           IF CSVstop THEN step :=10; ELSE
                           step := 5;
                           END_IF
                      END_IF
                END_IF
 5: (* Kehre nach Ablauf des Timers zurück zu Step 3, bis die Aufnahme abgebrochen wird *)
      IF NOT CSVstop THEN
  IF  startNewRowTON.Q THEN
                                     startNewRow := FALSE;
                             step := 3;
           END_IF
           ELSE step := 10;
      END_IF
 

    10:    (* Schließe fertige CSV Datei *)
        fbFileClose( bExecute := FALSE );
        fbFileClose( sNetId := sNetId, hFile := hFile, bExecute := TRUE );
        step := 11;

    11:(* Warten bis fbFileClose not busy *)
        fbFileClose( bExecute := FALSE, bError => bError, nErrID => nErrID );
        IF ( NOT fbFileClose.bBusy ) THEN
            CSVstop := FALSE;
            hFile := 0;
            step := 100;
            Schreibebestaetigung := TRUE;
        END_IF

    100: (* Fehler oder fertige Aufzeichnung *)
        IF ( hFile <> 0 ) THEN
            step := 10; (* Nochmal schließen *)
        ELSE
            bBusy := FALSE;
            step := 0;    (* Fertig -> zu Anfangszustand zurückkehren *)
        END_IF

END_CASE;
END_IF
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Er kommt auf jeden Fall bis zu Schritt 4. Der Codeausschnitt kommt aus einem FB, den ich von Anfang an mitlaufen lasse. Kann man das so nicht machen?

Doch, das kann man so machen. Aber dann wäre es auch sinnvoll, den startNewRowTON ebenfalls im FB zu deklarieren und dort aufzurufen.
Wenn der FB nur bis Schritt 4 kommt, wird der fbFilePuts für die Wertezeile (gestartet in Schritt 3) nicht beendet. Das dürfte daran liegen, dass Du nach dem Schreiben der Kopfzeile (gestartet in Schritt 2) nicht auf fbFilePuts.bBusy/bError abfragst. Stattdessen rufst Du in Schritt 3 noch einmal fbFileOpen auf und fragst auf fbFileOpen.bBusy/bError ab, was jedoch überflüssig ist.
 
Ach, da hab ich mich ein bisschen unverständlich ausgedrückt. Eigentlich wollte ich sagen, dass er durch Schritt 4 noch durchläuft, also das Schritt 5 wird noch aufgerufen. Aber du hast Recht, das sollte eigentlich fbFilePuts.bBusy/bError sein.
Habe ich nun soweit auch geändert und auch startNewRow und startNewRowTON im FB deklariert, aber er hängt sich immer noch bei Schritt 5 auf.

Code:
3: (* Konvertiere PLC Dateinzeile in CSV Format und schreibe eine Zeile + Timer am Ende *)

        startNewRow := TRUE;
        startNewRowTON(In:=startNewRow,Pt:=Aufzeichnungsintervall);
        fbFilePuts( bExecute := FALSE );
        IF NOT fbFilePuts.bBusy THEN
            IF NOT fbFilePuts.bError THEN
                IF CSVstop THEN step :=10; ELSE
                          sCSVLine := '';
                          sCSVField :=STRING_TO_CSVFIELD( STRING_FUER_CSV , FALSE );
                          sCSVLine := sCSVField;

                              fbFilePuts( bExecute := FALSE );
                              fbFilePuts( sNetId := sNetId, hFile := hFile, sLine := sCSVLine, bExecute := TRUE );
                                   step:=4;
                END_IF
            ELSE(* Fehler: Datei nicht gefunden? *)
                step := 100;
            END_IF
        END_IF

startNewRow setzte ich dabei immer am Ende von Schritt 5 wieder auf FALSE (startNewRowTON.Q zurücksetzen).
Ich habe wahrscheinlich das TON falsch eingebracht, kann das sein? Wenn ich das nämlich in Schritt 3 einbaue, hängt der FB schon in Schritt 3 fest.
 
Ich habe wahrscheinlich das TON falsch eingebracht, kann das sein? Wenn ich das nämlich in Schritt 3 einbaue, hängt der FB schon in Schritt 3 fest.
Ja, wenn der TON nur in Schritt 3, d. h. nur für einen SPS-Programmzyklus aufgerufen wird, kann er ja nicht weiterlaufen.
Setze den Aufruf "startNewRowTON(In:=startNewRow,Pt:=Aufzeichnungsintervall)" am besten hinter den CASE OF-Block, damit er in jedem SPS-Zyklus aufgerufen wird.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn ich den Aufruf direkt hinter CASE OF setzte, bekomme ich 2 Fehler. Einmal, dass er eine ganze Zahl oder Symbolische Konstante erwartet und noch einen 'ZAHL, ELSE oder END_CASE erwartet' :/
 
Zurück
Oben