File access from the PLC

The use of the PLC function blocks for data access from the Tc2_system library is introduced in this example. A new function block, FB_FileCopy, is implemented with the aid of the existing function blocks. Using the FB_FileCopy function block, binary files can be copied in the local TwinCAT system or between a local and a remote TwinCAT system.

The complete source code for the example project can be unpacked from here: FileCopyExample.zip

File access from the PLC 1:

Network drives cannot be accessed using the FB_FileCopy function block.

A rising edge at the bExecute input of the FB_FileCopy block results in execution of the following steps.

a) Open the source and destination files

b) Read the source file into a buffer

c) Write the bytes that have been read from the buffer into the destination file

d) Check whether the end of the source file has been reached. If not, then repeat b) and c). If yes, then jump to e)

e) Close the source and destination files;

The file is copied one segment at a time. In this example, the size of the buffer has been specified as 1000 bytes, but this can be modified.

PLC program

File access from the PLC 2:

Declaration Part

FUNCTION_BLOCK FB_FileCopy
VAR_INPUT
    sSrcNetId            : T_AmsNetId;
    sSrcPathName         : T_MaxString;
    sDestNetId           : T_AmsNetId;
    sDestPathName        : T_MaxString;
    bExecute             : BOOL;
    tTimeOut             : TIME := DEFAULT_ADS_TIMEOUT;
END_VAR
VAR_OUTPUT
    bBusy                : BOOL;
    bError               : BOOL;
    nErrId               : UDINT;
END_VAR
VAR
    fbFileOpen           : FB_FileOpen;
    fbFileClose          : FB_FileClose;
    fbFileRead           : FB_FileRead;
    fbFileWrite          : FB_FileWrite;
    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;
END_VAR

Implementation

RisingEdge(CLK:=bExecute); 
 
CASE Step OF 
     0:     (* Idle state *) 
          IF RisingEdge.Q THEN 
               bBusy := TRUE; 
               bError:= FALSE; 
               nErrId:=0; 
               Step := 1; 
               cbReadLength:=0; 
               hSrcFile:=0; 
               hDestFile:=0; 
          END_IF 
 
     1:     (* Open source file *) 
          fbFileOpen( bExecute := FALSE ); 
          fbFileOpen( sNetId := sSrcNetId, sPathName := sSrcPathName, 
                         nMode := FOPEN_MODEREAD OR FOPEN_MODEBINARY, 
                         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:     (* Open destination file *) 
          fbFileOpen( bExecute := FALSE ); 
          fbFileOpen( sNetId := sDestNetId, sPathName := sDestPathName, 
                         nMode := FOPEN_MODEWRITE OR FOPEN_MODEBINARY, 
                         ePath := PATH_GENERIC, tTimeout := tTimeOut, bExecute := TRUE ); 
          Step := Step+1; 
     4: 
          fbFileOpen( bExecute := FALSE ); 
          IF NOT fbFileOpen.bBusy THEN 
               IF fbFileOpen.bError THEN 
                    nErrId := fbFileOpen.nErrId; 
                    bError := TRUE; 
                    Step := 50; 
               ELSE 
                    hDestFile := fbFileOpen.hFile; 
                    Step := Step + 1; 
               END_IF 
          END_IF 
 
     5:     (* Read data from source file *) 
          cbReadLength := 0; 
          fbFileRead( bExecute:= FALSE ); 
          fbFileRead( sNetId:=sSrcNetId, hFile:=hSrcFile, 
                         pReadBuff:= ADR(buffRead), cbReadLen:= SIZEOF(buffRead), 
                         bExecute:=TRUE, tTimeout:=tTimeOut ); 
          Step := Step + 1; 
     6: 
          fbFileRead( bExecute:= FALSE ); 
          IF NOT fbFileRead.bBusy THEN 
               IF fbFileRead.bError THEN 
                    nErrId := fbFileRead.nErrId; 
                    bError := TRUE; 
                    Step := 50; 
               ELSE 
                    cbReadLength := fbFileRead.cbRead; 
                    Step := Step + 1; 
               END_IF 
          END_IF 
 
     7:     (* Write data to destination file *) 
          fbFileWrite( bExecute := FALSE ); 
          fbFileWrite( sNetId:=sDestNetId, hFile:=hDestFile, 
                         pWriteBuff:= ADR(buffRead), cbWriteLen:= cbReadLength, 
                         bExecute:=TRUE, tTimeout:=tTimeOut ); 
          Step := Step + 1; 
     8: 
          fbFileWrite( bExecute := FALSE ); 
          IF NOT fbFileWrite.bBusy THEN 
               IF fbFileWrite.bError THEN 
                    nErrId := fbFileWrite.nErrId; 
                    bError := TRUE; 
                    Step := 50; 
               ELSE 
                    IF fbFileRead.bEOF THEN (* Check if the EOF flag ist set *) 
                         Step := 50;     (* Cleanup: close the destination and source files *) 
                    ELSE 
                         Step := 5; (* Repeat reading/writing *) 
                    END_IF 
               END_IF 
          END_IF 
 
     30:     (* Close the destination file *) 
          fbFileClose( bExecute := FALSE ); 
          fbFileClose( sNetId:=sDestNetId, hFile:=hDestFile, bExecute:=TRUE, tTimeout:=tTimeOut ); 
          Step := Step + 1; 
     31: 
          fbFileClose( bExecute := FALSE ); 
          IF NOT fbFileClose.bBusy THEN 
               IF fbFileClose.bError THEN 
                    nErrId := fbFileClose.nErrId; 
                    bError := TRUE; 
               END_IF 
               Step := 50; 
               hDestFile := 0; 
          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 ( hDestFile <> 0 ) THEN 
               Step := 30; (* Close the destination file*) 
          ELSIF (hSrcFile <> 0 ) THEN 
               Step := 40; (* Close the source file *) 
          ELSE 
               Step := 0;     (* Ready *) 
               bBusy := FALSE; 
          END_IF 
 
END_CASE