TwinCAT 3 FB_FileGets

morris

Level-1
Beiträge
18
Reaktionspunkte
1
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,
ich möchte aus einer .txt Datei etwas einlesen und in ein Array of String Speichern.
Das Beispiel von Backhoff "fbFileCopy" klappt wunderbar, nur hier wird Byteweise gelesen und die Datei halt kopiert.
( http://infosys.beckhoff.de/index.ph...tem/html/tcplclibsys_fb_filegets.htm&id=23774)

Ich versuche es mit fb_FileGets , habe den Code dementsprechend umgeschrieben, es gibt auch keinen Fehler aber den String der aus sLine kommt kann ich nicht zwischenspeichern.

Code:
PROGRAM MAIN

VAR
    bSchreiben : BOOL ;
    bLesen: BOOL;
    Lesen : BOOL;
    bLesenBusy,bLesenError : BOOL;
    nLesenErrorID : UDINT ;
    
    DateiLesen : fbRead;
END_VAR

VAR_INPUT
END_VAR
---------------------
DateiLesen(
    sSrcNetId:= '', 
    sSrcPathName:= 'C:\Users\10469310\Documents\2.txt', 
    bExecute:= bLesen, 
    tTimeOut:=T#2S , 
    bBusy=>bLesenBusy , 
    bError=> bLesenError, 
    nErrId=> nLesenErrorID);
umgeschriebener fbFileCopy :
Code:
FUNCTION_BLOCK fbRead
VAR_INPUT
        sSrcNetId                       : T_AmsNetId;(* TwinCAT network address of the source file *)
        sSrcPathName            : T_MaxString;(* Source file path and name *)
      //  sDestNetId              : T_AmsNetId;(* TwinCAT network address of the destination file *)
      //  sDestPathName           : T_MaxString; (* Destination file path and name *)
        bExecute                        : BOOL; (* Rising edge start fb execution *)
        tTimeOut                        : TIME := DEFAULT_ADS_TIMEOUT;(* Max. ADS timeout time *)
END_VAR
VAR_OUTPUT
        bBusy                   :BOOL;(* TRUE => File copy execution in progress, FALSE => File copy execution idle *)
 bError                  :BOOL;(* TRUE => Error, FALSE => No error *)
 nErrId                  :UDINT;(* Error code *)
END_VAR
VAR
        fbFileOpen              :FB_FileOpen;
        fbFileClose             :FB_FileClose;
        fbFileRead              :FB_FileRead;
        fbFileWrite             :FB_FileWrite;
        fbFileGets                : FB_FileGets;

        hSrcFile                        :UINT   := 0;(* File handle of the source file *)
 hDestFile                       :UINT   := 0;(* File handle of the destination file *)

        Step                    :DWORD;
        RisingEdge              :R_TRIG;

        buffRead                        :ARRAY[1..1000] OF BYTE;(* Buffer *)
 cbReadLength            :UDINT := 0;
 // ab hier
 strBuffer : STRING ;
 bEOF        : BOOL;
  zeile        : ARRAY[0..40] OF STRING;
 
    i: INT;
END_VAR
-----------------------------------------------------------
RisingEdge(CLK:=bExecute);

CASE Step OF
        0:      (* Idle state *)
         IF RisingEdge.Q THEN
                        bBusy := TRUE;
                        bError:= FALSE;
                        nErrId:=0;
                        Step := 1;
                     
                        hSrcFile:=0;
                        i:= 0;
                        
                END_IF

        1:      (* Open source file *)
         fbFileOpen( bExecute := FALSE );
                fbFileOpen( sNetId := sSrcNetId, sPathName := sSrcPathName,
                        nMode := FOPEN_MODEREAD OR FOPEN_MODETEXT,// Textmodus für FB_FileGets // 
                        ePath := PATH_GENERIC, tTimeout := tTimeOut, bExecute := TRUE );
                Step := Step + 1;
        2:
                fbFileOpen( bExecute := FALSE );
                IF NOT fbFileOpen.bBusy THEN
                        IF fbFileOpen.bError THEN
                                nErrId := fbFileOpen.nErrId;
                                bError := TRUE;
                                Step := 50;
                        ELSE
                                hSrcFile := fbFileOpen.hFile;
                                Step := Step + 1;
                                //
                                
                        END_IF
                END_IF

      

        3:      (* Read data from source file *)
   
                        // Buffer zurücksetzten
                        fbFileGets(bExecute := FALSE);
                        
                        fbFileGets(    sNetId:= sSrcNetId,     hFile:= hSrcFile, 
                                    bExecute:= TRUE, tTimeout:= tTimeOut , 
                                    sLine=> strBuffer, 
                                    bEOF=> bEOF);
                Step := Step + 1;
        4:
                fbFileGets( bExecute:= FALSE );
                IF NOT fbFileGets.bBusy THEN
                        IF fbFileGets.bError THEN
                                nErrId := fbFileGets.nErrId;
                                bError := TRUE;
                                Step := 50;
                        ELSE
                            fbFileGets(sLine => zeile[i]);
                            zeile[i] :=  strBuffer ;
                                i := i +1 ;
                                Step := Step + 1;
                        END_IF
                END_IF

        5:
                                
                IF fbFileGets.bEOF THEN (* Check if the EOF flag ist set *)
                    Step := 50;    (* Cleanup: close the destination and source files *)
                ELSE
                    Step := 3; (* Repeat reading/writing *)
                END_IF
    
   
     

        40: (* Close source file *)
         fbFileClose( bExecute := FALSE );
                fbFileClose( sNetId:=sSrcNetId, hFile:=hSrcFile, bExecute:=TRUE, tTimeout:=tTimeOut );
                Step := Step + 1;
        41:
                fbFileClose( bExecute := FALSE );
                IF NOT fbFileClose.bBusy THEN
                        IF fbFileClose.bError THEN
                                nErrId := fbFileClose.nErrId;
                                bError := TRUE;
                        END_IF
                        Step := 50;
                        hSrcFile := 0;
                END_IF

        50: (* Error or ready => Cleanup *)
         IF ( hSrcFile <> 0 ) THEN
                        Step := 40; (* Close the  file*)
      
         ELSE
                        Step := 0;      (* Ready *)
                        bBusy := FALSE;
         END_IF

END_CASE

Im Anhang ist ein Screenshot, hier sieht man das in sLine der Wert/Stiring "2999 0 str.." steht aber dass dieser nicht in die Variable strBuffer geschrieben wird.
Was mache ich Falsch ?

Vielen Dank im Vorraus
Anhang: Screenshot, Twincat3 Projekt
 

Anhänge

  • fbFileGets.png
    fbFileGets.png
    8,2 KB · Aufrufe: 19
  • spsforum.zip
    178,7 KB · Aufrufe: 10
Code:
        3:      (* Read data from source file *)
   
                        // Buffer zurücksetzten
                        fbFileGets(bExecute := FALSE);
                        
                        fbFileGets(    sNetId:= sSrcNetId,     hFile:= hSrcFile, 
                                    bExecute:= TRUE, tTimeout:= tTimeOut , 
                                    sLine=> strBuffer, (* MIT DIESEM AUFRUF WIRD DAS LESEN GESTARTET, DA STEHT DER ZU LESENDE STRING NOCH GAR NICHT IN SLINE DRIN *)
                                    bEOF=> bEOF);
                Step := Step + 1;
        4:
                fbFileGets( bExecute:= FALSE );
                IF NOT fbFileGets.bBusy THEN
                        IF fbFileGets.bError THEN
                                nErrId := fbFileGets.nErrId;
                                bError := TRUE;
                                Step := 50;
                        ELSE
(* ERST HIER KANNST DU SICHER SEIN, DASS SLINE DEN GELESENEN STRING ENTHÄLT *)
                            fbFileGets(sLine => zeile[i]);
(* STATT FBFILEGETS NOCHMAL AUFZURUFEN, KANNST DU AUCH EINFACH zeile[i]:=fbFileGets.sLine; SCHREIBEN *)
(* STRBUFFER BRAUCHST DU DANN GAR NICHT MEHR
                            zeile[i] :=  strBuffer ;
*)                                i := i +1 ;
                                Step := Step + 1;
                        END_IF
                END_IF
 
Hallo,
bei mir klappt der Zeilenvorschub nicht automatisch.

Hat jemand eine Ahnung woran es liegen könnte?

Danke und Gruß


Code:
FOR i := 0 TO 4 BY 1 DO    
      
    CASE ListOfAxisFileStates[i] OF
           0:
            NewData := 0;
            OpenFile[i](sNetId := '192.168.178.24.1.1',
            sPathName := ListOfAxisFiles[i], 
            nMode := FOPEN_MODETEXT OR FOPEN_MODEREAD,
            bExecute := TRUE,
            ePath := PATH_GENERIC,
            tTimeout := T#1S);
            IF OpenFile[i].bBusy = NOT TRUE
                THEN ListOfAxisFileStates[i] := 2; OpenFile[i].bExecute := FALSE;
            END_IF
            ListOfAxisFileLastState[i] := 0;
            
    
        2:
        
            
            GetLine[i](sNetId := '192.168.178.24.1.1',
            hFile := OpenFile[i].hFile, 
            bExecute := TRUE,
            tTimeout := T#1S);
        
            IF GetLine[i].bBusy = NOT TRUE
                THEN ListOfAxisFileStates[i] := 5; 
            END_IF
            
            ListOfAxisFileLastState[i] := 2; 


            
        4:
            
    
            CloseFile[i](sNetId := '192.168.178.24.1.1',
            hFile := OpenFile[i].hFile, 
            bExecute := TRUE,
            tTimeout := T#1S);
            
            IF CloseFile[i].bBusy = NOT TRUE
                THEN ListOfAxisFileStates[i] := ListOfAxisFileStates[i] + 1; CloseFile[i].bExecute := FALSE;
            END_IF
            ListOfAxisFileLastState[i] := 4;
        
        5:
            


            
        END_CASE
END_FOR




bFinishedAll := TRUE;
FOR i := 0 TO 4 BY 1 DO
    
    IF    ListOfAxisFileStates[i] <> 5 
        THEN bFinishedAll := FALSE;
    
    END_IF
    
END_FOR
    
IF bFinishedAll
    THEN
    FOR i := 0 TO 4 BY 1 DO
    ListOfPositions[i] := STRING_TO_LREAL (GetLine[i].sLine);
    GetLine[i].bExecute := FALSE;
    ListOfAxisFileStates[i] := 2;
    NewData := 1;
    END_FOR
    
END_IF
 
Schau Dir die Datei mal mit einem Hex-Editor oder so an, enthält sie am Zeilenende auch das Line Feed Zeichen (0x0A) oder steht da vielleicht nur ein Carriage Return (0x0D)?
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Unabhängig davon, warum es gerade nicht funktioniert, hier mal ein paar Dinge, die ich für schlechten Stil halte
Code:
CASE ListOfAxisFileStates[i] OF
           0: // <-- Benutz hier lieber ein ENUM statt "magischer Zahlen"
...
            OpenFile[i](sNetId := '192.168.178.24.1.1',
            sPathName := ListOfAxisFiles[i], // <-- hier würde ich eine Zusätzliche einrückung machen, bis zur passenden ')'
            nMode := FOPEN_MODETEXT OR FOPEN_MODEREAD,
            bExecute := TRUE,
            ePath := PATH_GENERIC,
            tTimeout := T#1S);
            IF OpenFile[i].bBusy = NOT TRUE // <-- Vergleiche mit TRUE oder FALSE sind unnötig, lieber direkt "IF NOT bBusy"
                THEN ListOfAxisFileStates[i] := 2; OpenFile[i].bExecute := FALSE; // <-- THEN auf die Zeile von dem IF packen, und die beiden Statements in verschiedene Zeilen.
            END_IF

...

                THEN ListOfAxisFileStates[i] := ListOfAxisFileStates[i] + 1; CloseFile[i].bExecute := FALSE; // <-- Wozu diese komische Addition?

...

IF bFinishedAll
    THEN
    FOR i := 0 TO 4 BY 1 DO
    ListOfPositions[i] := STRING_TO_LREAL (GetLine[i].sLine); // <-- hier fehlt eine Einrückung
    GetLine[i].bExecute := FALSE;
    ListOfAxisFileStates[i] := 2;
    NewData := 1;
    END_FOR
    
END_IF
 
Mal abgesehen von der grauseligen Formatierung und der nochmaligen Steigerung von "= FALSE" nach "=NOT TRUE" ist es mir ein Rätsel, warum da überhaupt irgendwas funktioniert, es sei denn Beckhoff hätte zwischenzeitlich gravierende Änderungen an seinen File-FBs vorgenommen.
Ich kenne es so, dass nach Abschluss einer Dateioperation (NOT bBusy) es nicht ausreicht, DateiFB.bExecute:=false zu setzen, sondern man den FB auch mit diesem bExecute-Wert aufrufen muss, um ihn für die nächste Operation vorzubereiten.
Ach ja, und bError nicht abzufragen, ist schon mehr als schlechter Stil.
 
Hallo Leute,

ja ich habe vergessen den FB mit bExecude := FALSE erneut aufzurufen, das war mein Problem.
Danke für die Hinweise zum Stil, darüber muss ich wohl mal nachdenken.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute,

ich möchte eine Datei einlesen und alle Zeile der Datei in einem Array schnell schreiben. Wegen der CASE-Struktur wie im Beispiel von Beckhoff ist das Einlesen sehr langsam.

Hat jemand Idee für mich, wie man die Datei schnell einlesen und schreiben kann.

Viele Grüße.
 
ich möchte eine Datei einlesen und alle Zeile der Datei in einem Array schnell schreiben. Wegen der CASE-Struktur wie im Beispiel von Beckhoff ist das Einlesen sehr langsam.

Hat jemand Idee für mich, wie man die Datei schnell einlesen und schreiben kann.
Das Problem ist nicht die CASE-Anweisung, sondern dass das Lesen aus einer Datei immer mehrere Zyklen dauert und das wirst Du auch nicht beschleunigen können.

Von irgendwas mit Internetzugang gesendet
 
Hallo Oliver,

ja ich gebe Dir Recht, da es mit der CASE-Anweisung mehrere Zyklen dauert. Ich habe von CASE-Anweisung auf IF-Anweisung umgebaut und konnte die gleiche Datei schneller einlesen. Es ist aber zu der Anforderung noch langsam.

Ich probiere jetzt mit FOR-Schleife wie das obige Beispiel, aber hat es leider noch nicht geklappt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Oliver,

ja ich gebe Dir Recht, da es mit der CASE-Anweisung mehrere Zyklen dauert. Ich habe von CASE-Anweisung auf IF-Anweisung umgebaut und konnte die gleiche Datei schneller einlesen. Es ist aber zu der Anforderung noch langsam.

Ich probiere jetzt mit FOR-Schleife wie das obige Beispiel, aber hat es leider noch nicht geklappt.
Nicht mit der CASE-Anweisung dauert es mehrere Zyklen, sondern generell. Die Umstellung von CASE auf IF hat vielleicht einen Geschwindigkeitsgewinn gebracht, aber dieser dürfte nur relativ gering sein. Wie ich schon schrieb, das Lesen und auch das Schreiben dauert immer mehrere Zyklen und daran kannst Du auch nichts ändern. Außerdem werden Dateizugriffe mit einer sehr niedrigen, wenn nicht sogar der niedrigsten, Priorität ausgeführt und somit auch ständig unterbrochen, was den Zeitbedarf auch noch erhöht. SPSen sind nicht für schnelle Dateizugriffe konzipiert.

Von irgendwas mit Internetzugang gesendet
 
Ich probiere jetzt mit FOR-Schleife wie das obige Beispiel, aber hat es leider noch nicht geklappt.
Das mit der FOR-Schleife hast Du übrigens missverstanden. Die FOR-Schleife wird genutzt, weil mehrere Dateien gleichzeitig eingelesen werden, der eigentliche Einlesevorgang jeder einzelnen Datei wird auch weiterhin über eine CASE-Anweisung gesteuert.
 
Zurück
Oben