Following on my previous blog “Datalogging in IEC 61131-3: The basic principle”, I want to show you something extra.
To read and write data, you only need to implement some basic commands.
In this blog, we are going to create the following methods:
- Create a file
- Create a file and directly write a header line
- Delete a file
- Read a line
- Write a line
Please note that some extra error handling is needed for real life applications.
If you are interested in the complete PLCnext Engineer project, just let me know. (slemmens@phoenixcontact.be)
First, we are going to create one custom datatype, for reading and writing data. (arr_Byte_1_500 : Array[1..500] Of Byte)
Then, we need the implementation of our methods. In fact they only transfer some data towards the function block. We don’t use a return type because the complete process takes more than one program cycle.
// *** Method code: *** /* Create a file */ sRequestedFileName:= sFileName; IF iFileManager = 0 THEN iFileManager:= 20; END_IF; /* Create a file and directly write a header line */ sRequestedFileName:= sFileName; sRequestedText:= sHeader; IF iFileManager = 0 THEN iFileManager:= 10; END_IF; /* Delete a file */ sRequestedFileName:= sFileName; IF iFileManager = 0 THEN iFileManager:= 30; END_IF; /* Read a line */ sRequestedFileName:= sFileName; IF xFirstLine THEN diMemoryCursor:= DINT#0; END_IF; IF iFileManager = 0 THEN iFileManager:= 40; END_IF; /* Write a line */ sRequestedFileName:= sFileName; sRequestedText:= sText; IF iFileManager = 0 THEN iFileManager:= 10; END_IF;
The following function block implements the real program behavior.
// *** Function block code: *** xIdle:= iFileManager = 0; CASE iFileManager OF 10: // Determine the length of the string and convert it to a byte array diLengthTempText:= TO_DINT(LEN(sRequestedText)); sTempText:= sRequestedText; xConvert:= TRUE; iFileManager:= 11; 11: IF xDoneConvert THEN xConvert:= FALSE; iTempPointer:= TO_INT(diLengthTempText) + 1; arrBuffer_FW[iTempPointer]:= BYTE#16#0D; /* Carriage return */ iTempPointer:= iTempPointer + 1; arrBuffer_FW[iTempPointer]:= BYTE#16#0A; /* Line feed */ udiLength_FW:= TO_UDINT(iTempPointer); iFileManager:= 150; // Open file iReturnStep:= 12; END_IF; 12: // Move the current file pointer to a new position, in our case the end of the file xExecute_FS:= TRUE; uiHandle_FS:= uiHandleMemory; diPosition_FS:= DINT#0; uiMode_FS:= UINT#2; iFileManager:= 13; 13: IF xDone_FS THEN xExecute_FS:= FALSE; iFileManager:= 14; END_IF; 14: // Write data in the file xExecute_FW:= TRUE; uiHandle_FW:= uiHandleMemory; iFileManager:= 15; 15: IF xDone_FW THEN xExecute_FW:= FALSE; iFileManager:= 100; // Close file END_IF; 20: iFileManager:= 150; // Open file iReturnStep:= 100; // Close file 30: // Delete a file sName_FRe:= sRequestedFileName; xExecute_FRe:= TRUE; iFileManager:= 31; 31: IF xDone_Fre THEN xExecute_FRe:= FALSE; iFileManager:= 0; END_IF; 40: iFileManager:= 150; // Open file iReturnStep:= 42; 42: // Move the current file pointer to a new position xExecute_FS:= TRUE; uiHandle_FS:= uiHandleMemory; diPosition_FS:= diMemoryCursor; uiMode_FS:= UINT#0; iFileManager:= 43; 43: IF xDone_FS THEN xExecute_FS:= FALSE; iFileManager:= 44; END_IF; 44: // Read data xExecute_FR:= TRUE; uiHandle_FR:= uiHandleMemory; udiMaxLength_FR:= UDINT#100; // We expect a line with a maximum length of 80 char iFileManager:= 45; 45: IF xDone_FR OR (xError_FR & uiErrorID_FR = UINT#10) THEN xExecute_FR:= FALSE; iAmountOfData:= TO_INT(udiLengthRead_FR); IF iAmountOfData > 0 THEN FOR iLoop:= 1 TO iAmountOfData DO IF arrBuffer_FR[iLoop] = BYTE#16#0D THEN /* Carriage return */ iLengtLine:= iLoop - 1; diLengtLine:= TO_DINT(iLengtLine); diMemoryCursor:= diMemoryCursor + diLengtLine + DINT#2; EXIT; END_IF; END_FOR; iFileManager:= 46; ELSE diMemoryCursor:= DINT#0; sData:= ''; iFileManager:= 100; // Close file END_IF; END_IF; 46: xConvertRead:= TRUE; iFileManager:= 47; 47: IF xDoneConvertRead THEN xConvertRead:= FALSE; iFileManager:= 100; // Close file END_IF; // Close file 100: xExecute_FC:= TRUE; uiHandle_FC:= uiHandleMemory; iFileManager:= 101; 101: IF xDone_FC THEN xExecute_FC:= FALSE; iFileManager:= 0; END_IF; // Open file 150: sName_FO:= sRequestedFileName; xExecute_FO:= TRUE; iFileManager:= 151; 151: IF xDone_FO THEN uiHandleMemory:= uiHandle_FO; xExecute_FO:= FALSE; iFileManager:= iReturnStep; END_IF; END_CASE; // Converts the string variable to a byte array ConvertString_To_Buf(Req := xConvert, Buf_Format := FALSE, Buf_Offs := DINT#0, Buf_Cnt := diLengthTempText, Done => xDoneConvert, Error => xErrorConvert, Status => iStatusConvert, SRC := sTempText, BUFFER := arrBuffer_FW); // Converts a byte array to a string variable ConvertBuf_To_String(REQ := xConvertRead, BUF_FORMAT := FALSE, BUF_OFFS := DINT#0, BUF_CNT := diLengtLine, DONE => xDoneConvertRead, ERROR => xErrorConvertRead, STATUS => iStatusConvertRead, BUFFER := arrBuffer_FR, DST := sData); // Opens an existing file in the parameterization memory with a specific name or creates a new file. FileOpenLogging(Execute := xExecute_FO, Name := sName_FO, Done => xDone_FO, Handle => uiHandle_FO, Error => xError_FO, ErrorID => uiErrorID_FO); // Moves the current file pointer to a new position. FileSeekLogging(Execute := xExecute_FS, Handle := uiHandle_FS, Position := diPosition_FS, Mode := uiMode_FS, Done => xDone_FS, Error => xError_FS, ErrorID => uiErrorID_FS); // Writes data to a file that was opened previously. FileWriteLogging(Execute := xExecute_FW, Handle := uiHandle_FW, Done => xDone_FW, LengthWritten => udiLengthWritten_FW, Buffer := arrBuffer_FW, Length := udiLength_FW, Error => xError_FW, ErrorID => uiErrorID_FW); // Reads data from a file that has been opened using the FILE_OPEN function block. FileReadLogging(Execute := xExecute_FR, Handle := uiHandle_FR, Done => xDone_FR, LengthRead => udiLengthRead_FR, Buffer := arrBuffer_FR, MaxLength := udiMaxLength_FR, Error => xError_FR, ErrorID => uiErrorID_FR); // Closes a file in the parameterization memory that has been opened using the FILE_OPEN function block. FileCloseLogging(Execute := xExecute_FC, Handle := uiHandle_FC, Done => xDone_FC, Error => xError_FC, ErrorID => uiErrorID_FC); // Deletes a file with a specific name. FileRemoveLogging(Execute := xExecute_FRe, Name := sName_FRe, Done => xDone_FRe, Error => xError_FRe, ErrorID => uiErrorID_FRe);
The following program gives you an overview how you can access our ‘file manager’. Please note that we don’t have a buffer implemented. This means that you cannot give multiple commands at once.
// *** Program code: *** FileManager(xIdle => xFileManagerReady, sData => sResult); IF xCreateFileWithHeader & xFileManagerReady THEN xCreateFileWithHeader:= FALSE; FileManager.CreateFileWithHeader('ThisIsMyFirstFile.txt','Timestamp;Value_1;Value_2'); END_IF; IF xCreateFile & xFileManagerReady THEN xCreateFile:= FALSE; FileManager.CreateFile('ThisIsMySecondFile.txt'); END_IF; IF xDeleteFile & xFileManagerReady THEN xDeleteFile:= FALSE; FileManager.DeleteFile('ThisIsMySecondFile.txt'); END_IF; IF xWriteLine & xFileManagerReady THEN xWriteLine:= FALSE; FileManager.WriteLine('ThisIsMyFirstFile.txt','19/12/2019 09:34:12;78.3;1285'); END_IF; CASE iWriteMultipleLine OF 0: IF xWriteMultiLine THEN xWriteMultiLine:= FALSE; iWriteMultipleLine:= 1; END_IF; 1: IF xFileManagerReady THEN FileManager.WriteLine('ThisIsMyFirstFile.txt','19/12/2019 10:34:12;78.3;1285'); iWriteMultipleLine:= 2; END_IF; 2: IF xFileManagerReady THEN FileManager.WriteLine('ThisIsMyFirstFile.txt','19/12/2019 11:45:12;7.3;185'); iWriteMultipleLine:= 3; END_IF; 3: IF xFileManagerReady THEN FileManager.WriteLine('ThisIsMyFirstFile.txt','19/12/2019 12:04:08;35.8;17777'); iWriteMultipleLine:= 0; END_IF; END_CASE; IF xReadFirstLine & xFileManagerReady THEN // Output is written to variable 'sResult' xReadFirstLine:= FALSE; // Read the first line from this file, the cursor position is set to zero FileManager.ReadLine('ThisIsMyFirstFile.txt',TRUE); END_IF; IF xReadNextLine & xFileManagerReady THEN // Output is written to variable 'sResult' xReadNextLine:= FALSE; // Read the next line from this file, the cursor position is shifted by the program // When the end of the file is reached, you will receive an empty string // The next attempt, you will receive the first line again FileManager.ReadLine('ThisIsMyFirstFile.txt',FALSE); END_IF;
Leave a Reply
You must be logged in to post a comment.