# FB_FileWrite Writeerror



## COOLT (25 August 2009)

Hey leute ich hab mal wieder Probleme
Bei dem Baustein FB_FileWrite gibt es ein cbWriteLen um die Länge anzuzeigen. gibt es da iwie ein maximum? weil bei mir steht da 6500924 bytes und gleizeitig dazu zeigt er mir an bFileWriteerror=TRUE. Ergo is da iwo nen fehler. kann es daran liegen, das ich ein Array mit Struktur da reinschreiben will?


```
Var
    FB_FileWrite        :    FB_FileWrite;    (*    FileWrite um die veränderten Parameter in die geöffnete TxT Datei reinzuschreiben    *)
    bFileWrite        :    BOOL;
    bFileWriteBusy    :    BOOL;
    bFileWriteError    :    BOOL;
    nFileWriteErrorId    :    UDINT;
    nFileWriteCount    :    UDINT;
    arrFILEDATA         :    ARRAY[0..50] OF st_FileData;        (*    Für weitere veränderbare Parameter bitte Programm umschreiben.    *)
END_VAR
CODE:
    fb_FileWrite(
        hfile:=hfile,
        pWritebuff:=ADR(arrFILEDATA),
        cbWriteLen:=SIZEOF(arrFILEDATA),
        bExecute:=P_Main.Einlesen.O_bAbmeldung,
        tTimeout:=t#2s,
        bBusy=>bFilewriteBusy,
        bError=>bFileWriteError,
        nErrID=>nFileWriteErrorid,
        cbWrite=>nFileWriteCount);
```
das hfile bekommt es vom FB Open der auch noch da is.


----------



## bonatus (25 August 2009)

Es gibt dich zu jedem Fehler auch eine FehlerId. Schau doch erstmal nach was die FehlerId bedeutet.

Edit: Es liegt nicht daran das du ein Array schreiben willst.


----------



## COOLT (25 August 2009)

Hm Fehler ID 1795 steht bei bFilewriteerrorID dabei aber dazu find ich iwie nix.


----------



## bonatus (25 August 2009)

Also 1795 = 703hex = invalid index offset

Versuch mal die Hilfe zu benutzen!

Edit: In der Hilfe steht auch der Fehler:
0x703 Invalid or unknown file handle.


----------



## COOLT (25 August 2009)

Oh man ich peil nich was falsch daran sein soll.

```
VAR
    FB_FileOpen        :    FB_FileOpen;    (*    Fileopen und schreiben    *)
    bFileOpen        :    BOOL;
    bFileOpenBusy    :    BOOL;
    bFileOpenError    :    BOOL;
    nFileOpenErrId    :    UDINT;
    hFile            :    UINT;

    FB_FileWrite        :    FB_FileWrite;    (*    FileWrite um die veränderten Parameter in die geöffnete TxT Datei reinzuschreiben    *)
    bFileWrite        :    BOOL;
    bFileWriteBusy    :    BOOL;
    bFileWriteError    :    BOOL;
    nFileWriteErrorId    :    UDINT;
    nFileWriteCount    :    UDINT;
    arrFILEDATA         :    ARRAY[0..50] OF st_FileData;        (*    Für weitere veränderbare Parameter bitte Programm umschreiben.    *)

    nFiledataCounter    :    INT;                                (*    *)
    nFiledatareset    :    INT;                                (*    *)

    FB_FileClose        :    FB_FileClose;                    (*    FileClose für Dateischließung nach Abmeldung    *)
    bFileClose        :    BOOL;
    bFileCloseBusy    :    BOOL;
    bFileCloseError    :    BOOL;
    nFileCloseErrorId    :    UDINT;

(*Datum*)
    fbGetSystemTime     :    GETSYSTEMTIME;
    fileTime             :    T_FILETIME;


(***********************************************************)
    fbNextstep            :    FB_Next;                    (*    Funktion zur Schrittweiterschaltung    *)
    nStep                :    INT := 0;
    nNextStep            :    INT;
    bCondition            :    BOOL;
    nLastStep            :    INT;
END_VAR

CODE:

CASE nStep OF
    0:    nNextStep:=1;
        fb_FileOpen(
            sPathname:='\Hard Disk\Protkoll_fuer_Parameteränderungen.txt',
            nMode:=FOPEN_MODEAPPEND OR  FOPEN_MODEPLUS,
            bExecute:=P_Main.User.O_bFileOpen,
            tTimeout:=t#3s,
            bBusy=>bFileOpenBusy,
            bError=>bFileOpenError,
            nErrID=>nFileOPenErrID,
            hfile=>hfile);

        bCondition:=P_Main.User.O_bFileOpen;

        fbNextstep (I_bEnable:=bCondition, I_bSeqMode:= TRUE , I_tTimeValue:= t#0s);
            IF fbNextstep.O_bStart THEN
                nLastStep:=nStep;
                nStep:=nNextStep;
            END_IF
    (***************************************************************************************)
    1:    nNextStep:=2;
        fb_FileWrite(
            hfile:=hfile,
            pWritebuff:=ADR(arrFILEDATA),
            cbWriteLen:=SIZEOF(arrFILEDATA),
                bExecute:=P_Main.Einlesen.O_bAbmeldung,
            tTimeout:=t#2s,
            bBusy=>bFilewriteBusy,
            bError=>bFileWriteError,
            nErrID=>nFileWriteErrorid,
            cbWrite=>nFileWriteCount);

        bCondition:=    P_Main.Einlesen.O_bAbmeldung;

        fbNextstep (I_bEnable:= bCondition, I_bSeqMode:= TRUE , I_tTimeValue:= t#0s);
            IF fbNextstep.O_bStart THEN
                nLastStep:=nStep;
                nStep:=nNextStep;
            END_IF
    (********************************************************************************************)
    2:    nNextStep:=0;
        fb_FileClose(
            hfile:=hfile,
            bExecute:=P_Main.Einlesen.O_bAbmeldung,
                tTimeout:=t#3s);

        fbNextstep (I_bEnable:= TRUE, I_bSeqMode:= TRUE , I_tTimeValue:= t#0s);
            IF fbNextstep.O_bStart THEN
                nLastStep:=nStep;
                nStep:=nNextStep;
            END_IF
END_CASE

IF P_Main.Zuweisung.arrLastUserlist[P_Main.Zuweisung.nLastUserlistCounter].ID<>P_Main.Zuweisung.sLastID THEN
    nFiledataCounter:=nFiledataCounter+1;
END_IF

IF nFiledataCounter=25 AND arrFILEDATA[50].dDate<>'' THEN
    nFiledatareset:=26;
    FOR nFiledatareset:=26 TO 50 DO
        arrFILEDATA[nFiledatareset].dDate:='';
        arrFILEDATA[nFiledatareset].nPressure:=0;
    END_FOR
END_IF

IF nFiledataCounter=51 THEN
    nFiledatareset:=0;
    FOR nFiledatareset:=0 TO 25 DO
        arrFILEDATA[nFiledatareset].dDate:='';
        arrFILEDATA[nFiledatareset].nPressure:=0;
    END_FOR
END_IF


(**********************************************)
(*    DATUM    *)
    fbGetSystemTime(timeLoDW=>fileTime.dwLowDateTime, timeHiDW=>fileTime.dwHighDateTime );
    g_Date :=SYSTEMTIME_TO_STRING( FILETIME_TO_SYSTEMTIME( fileTime ) );
```

Kann mir iwer sagen wo da ein fehler sein soll?


----------



## Cerberus (25 August 2009)

Bist du dir sicher, dass das Öffnen der Datei funktioniert?? Mir fällt nämlich gerade auf, dass du weder beim Öffnen noch beim Schreiben noch beim Schließen der Datei eine AmsNetId zugewiesen hast.


----------



## COOLT (25 August 2009)

Ich hab die deklarationen und beschriftungen aus dem Beispiel von Beckhoff, dort haben die auch keine AmsNetId zugewiesen sondern das feld einfach offen gelassen.


----------



## Cerberus (25 August 2009)

Also im Info-System von Beckhoff wird dem Eingabe-Parameter "sNetId" ein leerer String übergeben. Könntest auch mal versuchen.


----------



## COOLT (25 August 2009)

Hm.. hat iwie nix gebracht hab den ePath beim Open noch ergänzt und die sNetId überall als Leerstring hinzugefügt aber immer noch derselbe fehler.


----------



## Cerberus (25 August 2009)

Und du bist dir sicher, dass das Öffnen der Datei funzt? Denn die Fehler-Beschreibung "invalid file handle" legt nahe, dass dabei irgendwas schief läuft.


----------



## COOLT (26 August 2009)

hm 1. denk ich ma schon 2. wie kann ich des überprüfen? und 3. tritt da kein fehler auf, von daher denk ich mal es funzt.


----------



## Cerberus (26 August 2009)

Also wenn deine Variable "bFileOpenError" keinen Fehler anzeigt, dann hat das Öffnen funktioniert. In dem Fall bin ich auch ratlos wieso das Schreiben nicht funktionieren soll.

Mal noch was anderes:
Prüfst du in deinem fbNeytStep ab, ob beim Öffnen, Schreiben, Schließen der Datei ein Fehler aufgetreten ist? Würde das auf jeden Fall auch als Bedingung dafür benutzen, ob in den nächsten Step gesprungen wird oder nicht.


----------



## COOLT (26 August 2009)

Ne bisher isses nich drin aber bau ich vielleicht noch rein. Dann muss ich auch noch ne Fehlerübertragung wieder einbauen uiui das wird ja doch schwieriger als erwartet dabei hab ich nur noch bis Freitag zeit. Naja dann stell ich das mal hinten an und guck erstmal nach meiner Dokumentation vielen dank für die Hilfe
Mfg
COOLT


----------



## Cerberus (26 August 2009)

Ich habe jetzt mal dein Programm bei mir auf dem PC nachvollzogen. Und es kam der gleiche Fehler.

Bei mir war es nun so, dass die Zuweisung
	
	



```
hfile=> hfile
```
im Baustein fb_FileOpen unverständlicherweise nicht funktioniert hat.

Hab dir hier nun ein Beispiel zum Erzeugen einer Datei, das bei mir funzt:

```
VAR
 fbOpen: FB_FileOpen;
 fbWrite: FB_FileWrite;
 fbClose: FB_FileClose;
 nStep: INT := 0;
 hFile: UINT;
 Timer1: TON;
 sLogDaten: STRING := '';
END_VAR
(**************************************)
CASE nStep OF
 0:
    fbOpen( sNetId:= '',
       sPathName:= 'C:\Test\Test1.txt',
       nMode:= FOPEN_MODEAPPEND OR  FOPEN_MODEPLUS,
       ePath:= PATH_GENERIC,
       bExecute:= TRUE,
       tTimeout:= t#3s,
       bBusy=> ,
       bError=> ,
       nErrId=> ,
       hFile=> hFile);
    Timer1(IN:= TRUE, PT:= t#4s);
    nStep := 1;
 1:
    Timer1();
    IF Timer1.Q THEN
       Timer1(IN:= FALSE);
       fbOpen();
       IF NOT fbOpen.bBusy THEN
          hFile := fbOpen.hFile;
          IF NOT fbOpen.bError THEN
             (* Kein Fehler beim Oeffnen *)
             sLogDaten := 'Teststring1';
             fbWrite( sNetId:= '',
                hFile:= hFile,
                pWriteBuff:= ADR(sLogDaten),
                cbWriteLen:= SIZEOF(sLogDaten),
                bExecute:= TRUE,
                tTimeout:= t#3s,
                bBusy=> ,
                bError=> ,
                nErrId=> ,
                cbWrite=> );
             Timer1(IN:= TRUE, PT:= t#4s);
             nStep := 2;
          ELSE
             ; (* Fehlerbehandlung *)
          END_IF
          fbOpen(bExecute:= FALSE);
       END_IF
    END_IF
 2:
    Timer1();
    IF Timer1.Q THEN
       Timer1(IN:= FALSE);
       fbWrite();
       IF NOT fbWrite.bBusy THEN
          IF NOT fbWrite.bError THEN
             (* Kein Fehler beim Schreiben *)
             fbClose( sNetId:= '',
                hFile:= hFile,
                bExecute:= TRUE,
                tTimeout:= t#3s,
                bBusy=> ,
                bError=> ,
                nErrId=> );
             Timer1(IN:= TRUE, PT:= t#4s);
             nStep := 3;
          ELSE
             ; (* Fehlerbehandlung *)
          END_IF
          fbWrite(bExecute:= FALSE);
       END_IF
    END_IF
 3:
    Timer1();
    IF Timer1.Q THEN
       Timer1(IN:= FALSE);
       fbClose();
       IF NOT fbClose.bBusy THEN
          IF NOT fbClose.bError THEN
             (* Kein Fehler beim Schliessen *)
             nStep := 0;
          ELSE
             ; (* Fehlerbehandlung *)
          END_IF
       fbClose(bExecute:= FALSE);
       END_IF
    END_IF
END_CASE
```


----------



## ybbs (26 August 2009)

COOLT schrieb:


> Kann mir iwer sagen wo da ein fehler sein soll?



Kann es sein, dass Du die Datei bereits schließt, obwohl der Schreibvorgang noch nicht beendet ist?

Für einen zuverlässigen Ablauf ist es m.E. mindestens folgendes erforderlich
1. BusyFlags der FBs auszuwerten
2. Errorflags auszuwerten und entsprechend reagieren.
3. Soll - Ist Vergleich Anzahl der geschriebenen Daten.

Natürlich kann es auch ohne funktionieren, muss aber nicht. 




COOLT schrieb:


> Bei dem Baustein FB_FileWrite gibt es ein cbWriteLen um die Länge anzuzeigen. gibt es da iwie ein maximum? weil bei mir steht da 6500924 bytes



6,5 MB ist schon ne ganze Menge für eine Benutzerverwaltung mit max. 51 Einträgen. Erscheint mir etwas sehr viel, wie sieht denn die Struktur aus?


----------



## COOLT (26 August 2009)

k habs jetz glaub ich fertig zumindest tritt kein Fehler mehr auf. Wie guck ich denn nach was der jetz da reingeschrieben hat? Also wie kann ich die Datei auslesen?


----------



## Cerberus (26 August 2009)

Wo wird die Datei denn abgespeichert? Auf die Flash-Karte? Würde dann diese einfach mal mit nem Kartenleser an den PC anschließen und schauen was drauf ist.


----------



## sps-neuling1234 (18 April 2011)

Das Thema ist zwar schon etwas älter aber ich hoffe trotzdem noch eine Antwort zu bekommen  da dies mein erster Beitrag in diesem Forum ist und ich das erste mal mit twincat arbeite bzw in berührung komme (sogar das erste mal mit dem Theme SPS in berührung komme) hoffe ich auf freundliche und geduldige Menschen 

Wie schon angedeutet, will ich ebenfalls eine Datei öffnen und diese beschreiben (in ST). Mir ist auch klar, dass ich die Bausteine Fileopen, filewrite und Fileclose brauche. Jedoch verstehe ich das Besipielprogramm von 'Ceberus' nicht wirklich.
Wird im ersten step(step=0) der Baustein und der Timer nur mit seinen startwerten initialisiert oder werden da beide schonmal aufgerufen und abgearbeitet?
Falls sie nur initialisiert werden, ist es so, dass das die Bausteine erst im zweiten step(step=1) aufgerufen werden durch Timer() und fbopen()?

Und wozu braucht es eigentlich den Timer?
Und zu guter letzt, was wird denn in der Zeile





> bBusy=>,


 zugewiesen?
Könnte ich auch einfach die nötigen sachen aus der twincat-info aus dem baustein "fb_filecopy" herausnehmen? Bzw wie müsste ich diese dann ändern?
Ich hoffe ihr könnt mir meine, für euch, sehr sehr seltsamen und einfachen Fragen beantworten  da ich die nächsten Monate noch ein wenig mit twincat beschäftigt sein werde, werde ich euch, falls ich das darf, noch öfters belästigen 
Vielen Dank schonmal im voraus =)


----------



## Cerberus (18 April 2011)

Hi sps-neuling,



sps-neuling1234 schrieb:


> Wird im ersten step(step=0) der Baustein und der Timer nur mit seinen startwerten initialisiert oder werden da beide schonmal aufgerufen und abgearbeitet?


 
Ja, beide Bausteine werden aufgerufen und abgearbeitet.



sps-neuling1234 schrieb:


> Und wozu braucht es eigentlich den Timer?


 
Den Timer brauchst du nicht wirklich, den kannst du auch weglassen!



sps-neuling1234 schrieb:


> Und zu guter letzt, was wird denn in der Zeile zugewiesen?


 
Nichts, die Zeilen ohne etwas nach dem "=>" kannst du auch rausnehmen. Ich hab sie nur drin gelassen, damit ich immer alle Ein-/Ausgänge der FBs sehe.

Hoffe dir geholfen zu haben und wünsch dir noch viel Spaß und Erfolg mit TwinCAT!

Gruß Cerberus


----------



## sps-neuling1234 (19 April 2011)

Danke für die schnelle Antwort, ich hab es nun einfach mal versucht zu programmieren  wie kann ich denn nun testen ob das funktioniert? Bzw. wie bringe ich das programm denn nun zum laufen?
Ich hänge es nun einfach mal noch mit an.

```
VAR
fbFileOpen    :FB_FileOpen;
fbFileClose    :FB_FileClose;
fbFileWrite    :FB_FileWrite;

bBusy        :BOOL;
bError1        :BOOL:=FALSE;
bError2        :BOOL:=FALSE;
bError3        :BOOL:=FALSE;

nErrId        :UDINT;


Step        :DWORD:=0;
BuffRead    :ARRAY[1..6] OF DINT;
hFileDatei    :UINT    := 0;(* file handle*)
A1:         DINT:=1;
A2:         DINT:=2;
A3:         DINT:=3;

END_VAR



CASE Step OF

    0: (*write data into array*)
    Buffread[1]:=A1;
    Buffread[2]:=A2;
    Buffread[3]:=A3;
    ;

    1:(* open file *)
    fbFileOpen(  bExecute := FALSE  );
    fbFileOpen(    sNetId := ‘‘,    (*eventuell noch ersetzen*)
        sPathName := ‘‘,     (*eventuell noch ersetzen*)
        nMode := FOPEN_MODEWRITE OR FOPEN_MODEBINARY
        ePath := PATH_GENERIC,
        tTimeout :=t#3s,
        bExecute := TRUE );
    Step := Step + 1;

    2:
    fbFileOpen( bExecute := FALSE );
    IF ( NOT fbFileOpen.bBusy ) THEN
        IF ( fbFileOpen.bError ) THEN
            nErrId := fbFileOpen.nErrId;
            bError1 := TRUE;
            Step := 50;
        ELSE
            hFileDatei := fbFileOpen.hFile;
            Step := Step + 1;
        END_IF
    END_IF

    3:(*write data to file*)
    fbFileWrite( bExecute := FALSE );
    fbFileWrite(    sNetId:=‘‘,     (*eventuell noch ersetzen*)
            hFile:=hFileDatei,
            pWriteBuff:= ADR(BuffRead),
            cbWriteLen:= 12,(*kann man hier irgendeine größe einsetzen? 12Byte, weil 3 Werte mit je 32Bit||SIZEOF(Buffread)*)
            bExecute:=TRUE,
            tTimeout:=t#3s );
    Step := Step + 1;

    4:
    fbFileWrite( bExecute := FALSE );
    IF ( NOT fbFileWrite.bBusy ) THEN
        IF ( fbFileWrite.bError ) THEN
            nErrId := fbFileWrite.nErrId;
            bError2 := TRUE;
            Step := 50;    
        END_IF
        Step:=50;
    END_IF

    30:
    (* close the file *)
    fbFileClose( bExecute := FALSE );
    fbFileClose(     sNetId:= ‘‘,     (*eventuell noch ersetzen*)
            hFile:=hFileDatei,
            bExecute:=TRUE,
            tTimeout:=t#3s );
    Step := Step + 1;

    31:
    fbFileClose( bExecute := FALSE );
    IF ( NOT fbFileClose.bBusy ) THEN
        IF ( fbFileClose.bError ) THEN
            nErrId := fbFileClose.nErrId;
            bError3 := TRUE;
        END_IF
        Step := 50;
    END_IF

    50: 
(*Fehler beim öffnen oder schreiben aufgetreten, von vorne anfangen*)
    IF (bError1=true || bError2=true) THEN
        bError1:=false;
        bError2:=false;
        Step := 0; 
    
(*kein fehler beim öffnen oder schreiben aufgetreten, Datei schließen*)
    ELSIF (bError1=false & bError2=false) THEN
        Step := 30;
        (*bBusy := FALSE; (*???*)*)
(*Fehler beim schließen der Datei aufgetreten, von vorne anfangen*)
    ELSIF (bError3=true) THEN
        bError3:=false;
        Step:=0;
    END_IF

END_CASE
```


----------



## Cerberus (19 April 2011)

Dein Beispiel wird nicht funktionieren. Du brichst in den Schritten 2, 4 und 31 mit deinem "bExecute := FALSE" die Bearbeitung der jeweiligen FBs ab. Nimm dieses bitte raus und ruf die FB mit leeren Klammern auf.

Testan kannst du das Ganze, indem du einen Pathname einsetzt, z.B. "C:/Test/Test.txt" und das Programm auf deinem PC laufen lässt.


----------



## StructuredTrash (19 April 2011)

Cerberus schrieb:


> Dein Beispiel wird nicht funktionieren. Du brichst in den Schritten 2, 4 und 31 mit deinem "bExecute := FALSE" die Bearbeitung der jeweiligen FBs ab.


Sicher? Ich meine, dass es nur auf die steigende Flanke am "bExecute" ankommt.


----------



## Cerberus (19 April 2011)

StructuredTrash schrieb:


> Sicher? Ich meine, dass es nur auf die steigende Flanke am "bExecute" ankommt.


 
So viel ich weiß, wird der Baustein mit bExecute:=FALSE zurückgesetzt.


----------



## Cerberus (19 April 2011)

Cerberus schrieb:


> So viel ich weiß, wird der Baustein mit bExecute:=FALSE zurückgesetzt.


 
Habs grad im Infosys nachgeschaut. Dort steht nur drin:


> *bExecute*: Durch eine steigende Flanke an diesem Eingang wird der Funktionsbaustein aktiviert.


 
Könnte also doch sein, dass es funzt.


----------



## StructuredTrash (19 April 2011)

Cerberus schrieb:


> Könnte also doch sein, dass es funzt.


Ja, das geht. Ich habe in meinen Schrittketten immer nur einen Zyklus für "bExecute=True", dann kommt sofort der nächste Schritt zum Auswerten von "bBusy" und "bError".


----------



## sps-neuling1234 (19 April 2011)

Nachdem ich das Programm nun endlich zum laufen gebracht habe (danke Cerberus) habe ich nun direkt in Step2 einen error. Undzwar wechselt, bei step2, in der ersten Zeile 
	
	



```
fbFileOpen( bExecute:=FALSE );
```
 der Wert von 
	
	



```
fbFileOpen.bBusy
```
 von TRUE auf FALSE, dies ist soweit auch richtig (glaube ich). Das Problem ist, dass im selben moment 
	
	



```
fbFileOpen.bError
```
 von FALSE auf TRUE wechselt. Die entsprechende ErrId ist 1861, was wohl ein Problem mit dem Timer ist?! Dies sollte aber eigentlich nicht passieren, bzw ich verstehe nicht wieso 
abermals danke im voraus =)



> 1* open file *)
> fbFileOpen(  bExecute := FALSE  );
> fbFileOpen(    sNetId := '',
> sPathName := 'C:\Dokumente und Einstellungen\Desktop\test.txt',
> ...


----------



## Cerberus (20 April 2011)

sps-neuling1234 schrieb:


> Nachdem ich das Programm nun endlich zum laufen gebracht habe (danke Cerberus) habe ich nun direkt in Step2 einen error. Undzwar wechselt, bei step2, in der ersten Zeile
> 
> 
> 
> ...


 
Dein Fehler 1861 heißt laut Beckhoff:


> Timeout elapsed


Dein Timeout hat also zugeschlagen. Verursacht wird das Ganze meiner Meinung nach von deinem Pfad. Ich glaube, dass der nicht korrekt ist. Oder hast du direkt unter "C:/Dokumente und Einstellungen/" einen Ordner "Desktop"? Bei mir kommt da noch der Benutzername.


----------



## sps-neuling1234 (20 April 2011)

Den Benutzernamen hatte ich aus gründen der anonymität, entfernt


----------



## Cerberus (20 April 2011)

Ok, dann probier mal bitte folgendes:

1. Nimm mal im Step 2 das "bExecute:=FALSE" raus (ich trau dem nicht).

2. Ich weiß nicht, ob "FOPEN_MODEWRITE" eine existierende Datei voraussetzt. Probiers mal indem du eine leere test.txt anlegst.

Wenn das alles nicht hilft, dann liegst höchst wahrscheinlich nicht an deinem Programm, aber das schauen wir dann wenn es soweit ist.


----------



## sps-neuling1234 (20 April 2011)

> 1. Nimm mal im Step 2 das "bExecute:=FALSE" raus (ich trau dem nicht).


das hat wohl geholfen (obwohl ich mir sicher bin, dass ich es gestern auch schon einmal weg hatte =) )
Nun schreibt er mir in die datei aber nicht einfach die Zahlen 1 2 3 sondern einfach 3 kleine Rechtecke  ist da noch irgendein Format falsch?


----------



## Cerberus (20 April 2011)

Ich vermute dass er deine Zahlen als ASCII interpretiert.

Ich selber schreibe immer Strings in meine Dateien. Du könntest dein Array in einen String umwandeln ala

```
LogString := DINT_TO_STRING(BuffRead[0]);
LogString := CONCAT(LogString, ' ');
LogString := CONCAT(LogString, DINT_TO_STRING(BuffRead[1])); 
LogString := CONCAT(LogString, ' ');
LogString := CONCAT(LogString, DINT_TO_STRING(BuffRead[2])); 
LogString := CONCAT(LogString, ' ');
LogString := CONCAT(LogString, DINT_TO_STRING(BuffRead[3])); 
LogString := CONCAT(LogString, ' ');
LogString := CONCAT(LogString, DINT_TO_STRING(BuffRead[4])); 
LogString := CONCAT(LogString, ' ');
LogString := CONCAT(LogString, DINT_TO_STRING(BuffRead[5]));
```
und diesen String dann wegschreiben.


----------



## sps-neuling1234 (20 April 2011)

Also bis ich herausgefunden hätte, dass ich das machen muss und wie das geht, wären wohl einige Monde vergangen 
Also es klappt nun schon sehr gut und ich bin auch wirklich begeistert 
nur habe ich nun noch das Problem, dass er immer wieder in den Step31 springt am ende, da muss es doch sowas wie ein 





> break;


 geben um aus der case anweisung zu springen oder?


----------



## Cerberus (20 April 2011)

Also ich mach das bei mir immer so, dass ich eine boolsche Variable und zwei Flankentrigger
	
	



```
bLogOn: BOOL := FALSE;
fbRTrig: R_TRIG;
fbFTrig: F_TRIG;
```
 hab und während die Variable true ist, wird geloggt.
Ganz am Anfang von meinem Programm aktualisiere ich meine Flankentrigger 
	
	



```
fbRTrig(CLK:= bLogOn);
fbFTrig(CLK:= bLogOn);
```
Um den File-Open-Code (bei dir Schritt 1) machst du dann

```
fbRTrig();
IF fbRTrig.Q OR bLogOn THEN
    (* Hier kommt der Code zum File öffnen *)
END_IF
```
und um den File-Write-Code (bei dir Schritt 3) kommt

```
fbFTrig();
IF NOT fbFTrig.Q THEN
    (* Hier kommt der Code zum File beschreiben *)
ELSE
    (* File schließen *)
    Step := 30;
END_IF
```
 
Den mittleren If-Zweig im Step 50 kannst du dir dann sparen.


----------



## sps-neuling1234 (20 April 2011)

Ich verstehe nicht so richtig wo ich nun was einfügen müsste,
gibt es denn kein "richtiges" switch-case Konstrukt bei dem man ein break nutzen kann?

Also was ich eigentlich machen will ist, dass er bei Knopfdruck einfach 6 Werte in eine datei schreibt. Am besten sollten die Werte untereinander stehen


----------



## Cerberus (20 April 2011)

Dann machs doch einfach so:
	
	



```
fbRTrig(CLK:=bLogOn);
 
sLogDaten := DINT_TO_STRING(BuffRead[0]);
sLogDaten := CONCAT(LogString, '$n');
sLogDaten := CONCAT(LogString, DINT_TO_STRING(BuffRead[1])); 
sLogDaten := CONCAT(LogString, '$n');
sLogDaten := CONCAT(LogString, DINT_TO_STRING(BuffRead[2])); 
sLogDaten := CONCAT(LogString, '$n');
sLogDaten := CONCAT(LogString, DINT_TO_STRING(BuffRead[3])); 
sLogDaten := CONCAT(LogString, '$n');
sLogDaten := CONCAT(LogString, DINT_TO_STRING(BuffRead[4])); 
sLogDaten := CONCAT(LogString, '$n');
sLogDaten := CONCAT(LogString, DINT_TO_STRING(BuffRead[5]));
 
CASE Step OF
    1:    (* File oeffnen *)
        fbRTrig();
        IF fbRTrig.Q THEN
            fbFileOpen(sNetId:= '',
                sPathName:= 'C:/Dokumente und Einstellungen/Cerberus/Desktop/test.txt,
                nMode:= FOPEN_MODEWRITE OR FOPEN_MODETEXT,
                ePath:= PATH_GENERIC,
                bExecute:= TRUE,
                tTimeout:= t#3s);
            Step := 2;
        END_IF
    2:
        fbFileOpen();
        IF NOT fbFileOpen.bBusy THEN
            IF fbFileOpen.bError THEN
                nErrId := fbFileOpen.nErrId;
                bError1 := TRUE;
                Step := 50;
            ELSE
                hFileDatei := fbFileOpen.hFile;
                Step := 3;
            END_IF
            fbFileOpen(bExecute:= FALSE);
        END_IF
    3:    (* File schreiben *)
        fbFileWrite(sNetId:= '',
            hFile:= hFileDatei,
            pWriteBuff:= ADR(sLogDaten),
            cbWriteLen:= LEN(sLogDaten),
            bExecute:= TRUE,
            tTimeout:= t#3s);
        Step := 4;
    4:
        fbFileWrite();
        IF NOT fbFileWrite.bBusy THEN
            IF fbFileWrite.bError THEN
                nErrID := fbFileWrite.nErrId;
                bError2 := TRUE;
                Step := 50;
            ELSE
                Step := 5;
            END_IF
            fbFileWrite(bExecute:= FALSE);
        END_IF
    5:    (* File schliessen *)
        fbFileClose(sNetId:= '',
            hFile:=hFileDatei,
            bExecute:= TRUE,
            tTimeout:= t#3s);
        Step := 6;
    6:
        fbFileClose();
        IF NOT fbFileClose.bBusy THEN
            IF fbFileClose.bError THEN
                nErrId := fbFileClose.nErrId;
                bError3 := TRUE;
                Step := 50;
            ELSE
                Step := 1;
            END_IF
            fbFileClose(bExecute:= FALSE);
        END_IF
END_CASE
```


----------



## sps-neuling1234 (20 April 2011)

Danke.
Dies entspricht, abgesehen von dem R_TRIG ja vom prinzip meinem Programm. Hier habe ich doch aber wieder das problem, dass wenn ich bspw dies als Function machen möchte und es aus meinem main Programm auffrufe, dann doch aber wieder ganze Zeit in dieser case anweisung gefangen bin oder wann würde er hier das case denn verlassen?
Wenn man bedenkt, dass case50  nun so aufgebaut ist





> 50:
> (*Fehler beim öffnen oder schreiben aufgetreten, von vorne anfangen*)
> IF (bError1=TRUE OR bError2=TRUE) THEN
> bError1:=FALSE;
> ...


----------



## Cerberus (20 April 2011)

Das RTrig srogt dafür, dass der Log-Prozess auf eine Variable reagiert. Diese kannst du dann im Knopfdruck setzen.

Das Problem an der Funktion bzw. FB ist, dass beide das CASE einmal durchlaufen, dann verlassen und auch den FB bzw. Funktion verlassen. Deshalb würd ich so ne File-Write-Geschichte auch immer im Programm laufen lassen.


----------



## Cerberus (20 April 2011)

Cerberus schrieb:


> Das Problem an der Funktion bzw. FB ist, dass beide das CASE einmal durchlaufen, dann verlassen und auch den FB bzw. Funktion verlassen.


 
Um Missverständnissen vorzubeugen:
In deinem Fall würde in ner Funktion das CASE mit Step = 1 durchgeführt und danach wieder verlassen. Es würde also nur die Datei geöffnet, nichts geschrieben und so.


----------



## sps-neuling1234 (21 April 2011)

Ja genau! Aber gerade das soll ja nicht passieren  daher wundert es mich ja so stark, dass es keinen switch befehl gibt! Dieser würde ja genau dieses verhalten verhindern.


> In deinem Fall würde in ner Funktion das CASE mit Step = 1 durchgeführt und danach wieder verlassen. Es würde also nur die Datei geöffnet, nichts geschrieben und so.


d.h. mein Konstrukt mit dem case ist in diesem fall alles andere als sinnvoll, hast du eine Idee wie ich es ansonsten machen könnte? Wenn ich kein richtiges switch-case Konstrukt habe, dann kann ich doch nie wirklich auf meine Errors eingehen oder?

Ich könnte natürlich einfach fileopen-filewrite-fileclose hintereinander ausführen lassen und in meinem fall einfach case 50 komplett weglassen. Und wenn es dann halt mal einen Error gibt, dann funktioniert die Funktion halt einmal nicht  oder ist eine SPS so schnell, das es egal ist wenn er beim ersten durchlaufen nur case1 macht und wenn dann das ganze SPS-Programm wieder von vorne läuft, dann würde er ja case2 bearbeiten...eine SPS arbeitet schon wie in so ner endlosschleife, arbeitet also immer wieder die MAIN ab oder?=)


----------



## Cerberus (21 April 2011)

sps-neuling1234 schrieb:


> daher wundert es mich ja so stark, dass es keinen switch befehl gibt! Dieser würde ja genau dieses verhalten verhindern.
> d.h. mein Konstrukt mit dem case ist in diesem fall alles andere als sinnvoll, hast du eine Idee wie ich es ansonsten machen könnte? Wenn ich kein richtiges switch-case Konstrukt habe, dann kann ich doch nie wirklich auf meine Errors eingehen oder?


 
Das Case ist ein ganz normales switch-case!!




sps-neuling1234 schrieb:


> Ich könnte natürlich einfach fileopen-filewrite-fileclose hintereinander ausführen lassen und in meinem fall einfach case 50 komplett weglassen. Und wenn es dann halt mal einen Error gibt, dann funktioniert die Funktion halt einmal nicht  oder ist eine SPS so schnell, das es egal ist wenn er beim ersten durchlaufen nur case1 macht und wenn dann das ganze SPS-Programm wieder von vorne läuft, dann würde er ja case2 bearbeiten...eine SPS arbeitet schon wie in so ner endlosschleife, arbeitet also immer wieder die MAIN ab oder?=)


 
Also wenn du das ganze in ner Funktion laufen lassen würdest, dann würde er bei jeder Durchführung immer nur den case 1 durchlaufen. Das liegt daran, dass bei jedem Aufruf der Funktion die internen Variablen Default-Werte erhalten.
Ob es in nem FB funzt, kann ich dir nicht sagen.

Was du natürlich machen könntest, ist, dass du deine Variable Step als In-Out-Variable im FB deklarierst. Dann würdest du den FB mit Step = 1 aufrufen und er würde dir nach der Bearbeitung Step = 2 zurückgeben. Im nächsten Schritt musst du dann halt den FB mit Step = 2 aufrufen.


----------



## sps-neuling1234 (21 April 2011)

> Was du natürlich machen könntest, ist, dass du deine Variable Step als In-Out-Variable im FB deklarierst. Dann würdest du den FB mit Step = 1 aufrufen und er würde dir nach der Bearbeitung Step = 2 zurückgeben. Im nächsten Schritt musst du dann halt den FB mit Step = 2 aufrufen.


Ich könnte aber auch die Variable einfach als Globale Variable nehmen oder? Ist zwar nicht das sinnvollste, aber vllt auf anhieb das leichteste


----------



## Cerberus (21 April 2011)

sps-neuling1234 schrieb:


> Ist zwar nicht das sinnvollste, aber vllt auf anhieb das leichteste


 
Zwar auf Anhieb das leichteste, aber nichts von Dauer, weil unsauber. Eine VAR_IN_OUT ist die sauberste Variante.


----------



## sps-neuling1234 (21 April 2011)

Alles klar, dann werde ich mir das auch mal noch anschauen 
ich hab meinen code nun noch bissel verändert, eventuell kannst du ja mal sagen wie du ihn so findest, ich finds so glaub besser! Weil er am Anfang nun zwingend auf die steigende Flanke (Tastendruck) wartet.



```
PROGRAM MAIN
VAR
    fbFileOpen    :FB_FileOpen;
    fbFileClose    :FB_FileClose;
    fbFileWrite    :FB_FileWrite;

    bBusy        :BOOL;
    bError1        :BOOL:=FALSE;
    bError2        :BOOL:=FALSE;
    bError3        :BOOL:=FALSE;

    nErrId        :UDINT;

    Step        :DWORD:=0;
    BuffRead    :ARRAY[1..6] OF DINT;
    hFileDatei    :UINT    := 0;(* file handle*)
    A1:         DINT:=1;
    A2:         DINT:=2;
    A3:         DINT:=3;

    LogString: STRING;
    fbRTrig: R_TRIG;
    blogOn: BOOL:=TRUE;
    halter: BOOL;
END_VAR


fbRTrig(CLK:=blogOn);

IF fbRTrig.Q OR halter THEN


CASE Step OF

    0:    (*Werte laden*)

    Buffread[1]:=A1;
    Buffread[2]:=A2;
    Buffread[3]:=A3;

   LogString := DINT_TO_STRING(BuffRead[1]);
   LogString := CONCAT(LogString, '$n');
   LogString := CONCAT(LogString, DINT_TO_STRING(BuffRead[2]));
   LogString := CONCAT(LogString, '$n');
   LogString := CONCAT(LogString, DINT_TO_STRING(BuffRead[3]));
   LogString := CONCAT(LogString, '$n');
   LogString := CONCAT(LogString, '$n');

   fbRTrig();(*nicht notwendig, nur zur Kontrolle des Wertes*)
   halter:=TRUE;
   Step:=1;

    1:    (* open file *)

            fbFileOpen(  bExecute := FALSE  );
            fbFileOpen(    sNetId := '',
                sPathName := 'C:\Dokumente und Einstellungen\Administrator.BECKHOFFKR16\Desktop\test.txt',
                nMode := FOPEN_MODEAPPEND OR FOPEN_MODETEXT,
                ePath := PATH_GENERIC,
                tTimeout :=t#3s,
                bExecute := TRUE );
        Step :=  2;

    2:

       fbFileOpen(  );
        IF ( NOT fbFileOpen.bBusy ) THEN
            IF ( fbFileOpen.bError ) THEN
                    nErrId := fbFileOpen.nErrId;
                    bError1 := TRUE;
                   Step := 50;
            ELSE
                    hFileDatei := fbFileOpen.hFile;
                    Step := 3;
            END_IF
        END_IF

    3:    (*write data to file*)

    fbFileWrite( bExecute := FALSE );
    fbFileWrite(    sNetId:='',
            hFile:=hFileDatei,
            pWriteBuff:= ADR(LogString),
            cbWriteLen:= LEN(LogString),
            bExecute:=TRUE,
            tTimeout:=t#3s );
    Step := 4;

    4:

    fbFileWrite(  );
    IF ( NOT fbFileWrite.bBusy ) THEN
        IF ( fbFileWrite.bError ) THEN
            nErrId := fbFileWrite.nErrId;
            bError2 := TRUE;
         Step:=50;
        END_IF
    END_IF
     Step:=5;

    5:     (* close the file *)

    fbFileClose( bExecute := FALSE );
    fbFileClose(     sNetId:= '', 
            hFile:=hFileDatei,
            bExecute:=TRUE,
            tTimeout:=t#3s );
    Step := 6;

    6:

    fbFileClose(  );
    IF ( NOT fbFileClose.bBusy ) THEN
        IF ( fbFileClose.bError ) THEN
            nErrId := fbFileClose.nErrId;
            bError3 := TRUE;
         Step:=50;
     ELSE
        Step:=50;
        END_IF
    END_IF


    50:
(*Fehler beim öffnen oder schreiben aufgetreten, von vorne anfangen*)
    IF (bError1=TRUE OR bError2=TRUE) THEN
        bError1:=FALSE;
        bError2:=FALSE;
        Step := 0;
(*Fehler beim schließen der Datei aufgetreten, von vorne anfangen*)
    ELSIF (bError3=TRUE) THEN
        bError3:=TRUE;
        Step:=0;
 (*Programm ohne fehler durchgelaufen*)
    ELSE
    halter:=FALSE;
    Step:=0;

    END_IF

END_CASE

END_IF
```


----------



## Cerberus (21 April 2011)

Sieht auf den ersten Blick in Ordnung aus.


----------

