Arrays in TwinCAT verbinden

Zuviel Werbung?
-> Hier kostenlos registrieren
Das sieht soweit gut aus, aber was soll das Konstrukt mit dem count?
Das scheint ja alles in einem FB abzulaufen, könntest Du den Quellcode mal komplett hier reinstellen, ich habe den Verdacht, da hakt es woanders.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Das "count-Konstrukt" ist nur eine sehr rudimentäre Art das Speichern der Daten auf ca. 1s zu beschränken. TwinCAT ist noch Neuland für mich und das erschien mir als eine schnelle, einfache Methode.

Semikolon oder kleines/großes "N" ist nicht das Problem.

Hier der Code des Funktionsbausteins:
Code:
CASE STATE OF 
    
0: 
    IF bOPEN THEN
    hFile        := 0;
    allWritten := FALSE;
    fbFileOpen(  bExecute := FALSE  );
    fbFileOpen(     sNetId := '', sPathName := fPath, nMode := FOPEN_MODEAPPEND OR FOPEN_MODEPLUS,
                    ePath := PATH_GENERIC, bExecute := TRUE );
    state := 1;
    END_IF

1:
    fbFileOpen( bExecute := FALSE, bError => bError, nErrID => nErrID, hFile => hFile );
        IF NOT fbFileOpen.bBusy THEN
            IF NOT fbFileOpen.bError THEN
                state := 2;
                
            ELSE
                state := 100;
            END_IF
        END_IF

2:    

    IF bHead THEN
        fbFileWrite(bExecute:=FALSE);
        fbFileWrite(sNetID := '',pWriteBuff := ADR(HEADER),cbWriteLen:= SIZEOF(HEADER),bExecute := TRUE,hFile := hFile );
        state := 3;
    ELSE
        fbFileWrite(bExecute:=FALSE);
        fbFileWrite(sNetID := '',pWriteBuff := ADR(DATA),cbWriteLen:= SIZEOF(DATA),bExecute := TRUE,hFile := hFile );
        state := 3;
    END_IF

3:    
        
    fbFileWrite( bExecute := FALSE, bError => bError, nErrID => nErrID );
    IF NOT fbFileWrite.bBusy THEN
            IF NOT fbFileWrite.bError THEN                
                state := 10;                        
            END_IF
    END_IF
                
10:    
         
        fbFileClose( bExecute := FALSE );
        fbFileClose( sNetId := '', hFile := hFile, bExecute := TRUE );
        state := 11;                    
        
11:
    
        fbFileClose( bExecute := FALSE, bError => bError, nErrID => nErrID );
        IF ( NOT fbFileClose.bBusy ) THEN
            hFile := 0;
            state := 100;
        END_IF
        
100: 
        IF ( hFile <> 0 ) THEN
            state := 10; 
        ELSE
            bBusy := FALSE;
            state := 0;    
            allWritten := TRUE;
            
        END_IF

END_CASE
 
Dein Data ist bestimmt länger als der eigentliche String. Also ist das, was im CSV vor dem 2. Zeitstempel steht, der Rest, der eigentlich hinter dem Zeilenumbruch des ersten Array-Feldes undefiniert rumwabert...

EDIT: du könntest den Zeilenumbruch vor den Zeitstempel setzen. Dein Datenstring endet dann mit einem Semicolon, dahinter stehen dann die undefinierten Bytes aus dem Array und der Array-Overhead von Twincat. Dann hat deine CSV als letzte Spalte dann diese Bytes. Ist zwar nicht ganz sauber, aber sollte gehen
Gruß
Holger
 
Zuletzt bearbeitet:
Vielen Dank für den Tipp. Das ist tatsächlich das Problem. Ich habe die Stringlänge manuell auf genau die Anzahl an Zeichen reduziert und es funktioniert.

Allerdings wird später ja die Stringlänge ständig variieren. Das Array muss aber ja von einer festen Länge sein.

Wie kann man das Lösen, dass die Übrigen Zeichen nicht mitgeschrieben werden?
 
Das ginge nur, wenn du jeden String einzeln in das File schreibst und vorher die Länge ermittelst. Das wird aber wohl in deinem Fall zu lange dauern.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ok das habe ich grundlegend verstanden und umgesetzt. Kann auch Daten rausschreiben allerdings funktioniert das mit der Schleife so nicht. Wie kann ich ihm bei MEMCPY denn sagen, dass er es hinten dranhängen soll? Ich habe das Gefühl, dass er das überschreiben weil ich pro Schleifendurchlauf nur einen Wert geschrieben bekomme.

Trotzdem wird meine Datei in einer Sekunde 100 Mbyte groß es sind allerdings nur ca. 120 Einträge drin?!

Zudem scheint es mir so, als müsste ich bei dem String trotzdem angeben wie lang er ist. Mache ich das nicht, dann intepretiert Twincat nicht alle Zeichen. Setzte ich den String allerdings einfach auf maximal Länge (255) dann schreibe ich natürlich bei MEMCPY wieder Murks wenn ich per SIZEOF die Länge des Strings bestimme.
 
Du musst Dir schon merken, wie voll der Puffer ist. Und die tatsächliche Länge des Strings nicht mit SIZEOF, sondern mit LEN ermitteln.
Etwa so:
Code:
VAR
   TextBuffer:ARRAY[0..200000] OF BYTE;
   BufferPos:UDINT;
END_VAR

BufferPos:=0;

// Und dann in einer Schleife
MEMCPY(
   destAddr:=ADR(TextBuffer[BufferPos]),
   srcAddr:=ADR(StringToWrite),
   n:=LEN(StringToWrite));
BufferPos:=BufferPos+LEN(StringToWrite);

// Beim Schreiben in die Datei dann BufferPos als Grösse angeben
 
Danke für eure Antworten.

Ich habe den Code jetzt nochmal neu geschrieben und die Methode mit dem Byte-Puffer umgesetzt. Funktioniert auch jetzt soweit.

Mein Problem ist jetzt, dass das Abspeichern ja nicht in Echtzeit funktioniert und ich vermute, dass mir dadurch am Ende Messwerte flöten gehen. Deswegen habe ich überlegt, während des Messens alle Werte in einen großen Puffer zu schreiben und diesen nach dem Messvorgang in einem Rutsch zeitunkritisch rauszuschreiben. Zum Testen habe ich das Programm mal 60 Sekunden laufen lassen und in jedem Zyklus eine Messreihe mit ca. 50 Werten bzw. 255 Zeichen (Mehr gehen leider nicht in einen String) in den Puffer. Das Speichern am Ende funktioniert, und ich habe am Ende 60.000 Messreihen in der -csv-Datei.

Erhöhe ich nun aber die Messzeit auf sagen wir 90 Sekunden, so werden am Ende gar keine Werte in die .csv geschrieben. Wie kann das sein? Variablen laufen meiner Meinung nach nicht über.

Hier der Main() Code. Die Variable allWritten wird am Ende des FBs zum Schreiben auf TRUE gesetzt, sobald die Datei erfolgreich geschlossen ist. Vorher werden also eigentlich auch keine Variablen gelöscht. DATA_SAVE ist als ARRAY[0..1000000000] OF BYTE definiert.

Code:
fbGetSystemTime(timeLoDW=>fileTime.dwLowDateTime, timeHiDW=>fileTime.dwHighDateTime );
sTime :=SYSTEMTIME_TO_STRING( FILETIME_TO_SYSTEMTIME( fileTime ) );    
strTime := Right(sTime,9);

// count SPS cylces
count := count +1;        


IF firstRun THEN    
    
    strLen := INT_TO_UINT(LEN(strHeader));
        
    MEMCPY(ADR(DATA_SAVE),ADR(strHeader),strLen);
    
    SaveCSV(    DATA:= DATA_SAVE, 
                dSize:=strLen,
                fPath := strPath);
                
    IF SaveCSV.allWritten THEN 
        MEMSET(ADR(DATA_SAVE),0,SIZEOF(DATA_SAVE));
        firstRun := FALSE;
        DATA_pos  := 0;
        DATA_size  := 0;
    END_IF
END_IF


IF  NOT firstRun THEN
        
  
    strSave := CONCAT(strTime,strMess);
    strLen := INT_TO_UINT(LEN(strSave));
    
 
    MEMCPY(ADR(DATA_SAVE[DATA_pos]),ADR(strSave),strLen);
    DATA_pos := DATA_pos + strLen;
    DATA_size := DATA_size + strLen;
    
 
    IF count = tMeasure THEN
        bWrite := TRUE;
        count := 0;
    END_IF
END_IF
    


IF bWrite THEN    
    
    SaveCSV(    DATA    := DATA_SAVE, 
                dSize    := DATA_size,
                fPath     := strPath);
    
   
    IF SaveCSV.allWritten THEN
        MEMSET(ADR(DATA_SAVE),0,SIZEOF(DATA_SAVE));
        bWrite := FALSE;
        DATA_size := 0;
        DATA_pos := 0;
    END_IF
END_IF
 
Zurück
Oben