Efficiently Logging Data: Writing DINT Arrays to Text Files in CODESYS

Question:

In a recent project, I encountered the need to write a DINT array to a text file using CODESYS. To address this, I developed a small data logger to collect data in a DINT array and then transfer it to a file. Throughout this process, I faced a challenge that required me to seek solutions from online forums. This made me consider if there's a more streamlined approach to handling this task, as the current method involves several variables. It was also interesting to learn that CODESYS uses '$R$N' to represent CRLF (carriage return and line feed) for Windows OS line endings. As I continue this project, I plan to incorporate error handling and verification for file operations. I am contemplating if converting the DINT array to an array of strings and adding newline characters to each element before writing to the file might be a more efficient method. Included below is a snippet of the CODESYS support class for file handling: ```CODE // Support class for File_Handler FUNCTION_BLOCK fileWrite VAR_INPUT xEnableWrite : BOOL; iMaxSize : INT; END_VAR VAR_IN_OUT diData : ARRAY[*] OF DINT; END_VAR VAR_OUTPUT xDone: BOOL := FALSE; END_VAR VAR _hfile : SysFile.RTS_IEC_HANDLE; pResult: POINTER TO SysFile.RTS_IEC_RESULT; _sFileName : STRING := 'C:/temp/DataLogger.txt'; _sArray : ARRAY [0..255] of STRING; i :INT := 0; xFinished : BOOL := FALSE; sStringTmp : STRING(128); END_VAR //----------------------------------------------------------- IF xEnableWrite AND NOT xFinished THEN _hFile := SysFileOpen(_sFileName, am:=SysFile.ACCESS_MODE.AM_WRITE, pResult); // Convert DINT array to StringArray FOR i := 0 TO iMaxSize - 1 DO // Convert DINT to STRING and store in StringArray _sArray[i] := DINT_TO_STRING(diData[i]); sStringTmp := CONCAT(_sArray[i], '\n'); //'$R$N'); SysFileWrite(_hFile, ADR(sStringTmp), LEN(sStringTmp), pResult); END_FOR xFinished := TRUE; xDone := TRUE; END_IF ``` By optimizing the process of writing DINT arrays to text files in CODESYS, we can enhance efficiency and performance in data logging tasks.

Top Replies

If you find that xFinished is not being used, it can be removed from the IF statement along with the AND NOT xFinished sub-expression. However, if xFinished is effectively static, despite being declared in a VAR-END_VAR stanza instead of a VAR_STATIC-END_VAR stanza, this may not be necessary. The issue arises if xFinished is not effectively static, as the routine may only be able to write the file once. The variable sArray is not required; both occurrences can be replaced with sStringTmp. It may be possible to omit pResult in the calls if you are not examining the result within this routine. If nothing is being done with the output parameter referenced by xDone in the calling routine, it can also be eliminated. Consider using functions like SIZE, UPPER_BOUND, and LOWER_BOUND to determine the length of the diData array, potentially removing the need for iMaxSize. In CODESYS, $Rand$N is equivalent to \rand\n in languages like C and Python, while $R$N is equivalent to "\r\n" or CRLF. Placing the array diData in the VAR_IN section instead of VAR_IN_OUT may not save a variable but can save two lines of code. You could eliminate xEnableWrite and the IF-ENDIF by making the external call to this routine optional based on the input parameter xEnableWrite. Only call the routine when xEnableWrite is True by using IF enableWrite THEN fileWrite(diData,...); END_IF.

Thank you for the valuable feedback, drbitboy. Here is an enhanced version of the code based on your input: Function Block: fileWrite VAR_IN_OUT diData: ARRAY[*] OF DINT; END_VAR VAR_OUTPUT xDone: BOOL := FALSE; END_VAR VAR _hfile: SysFile.RTS_IEC_HANDLE; _pResult: POINTER TO SysFile.RTS_IEC_RESULT; _sFileName: STRING := 'C:/temp/DataLogger.txt'; _i: DINT := 0; _sStringTmp: STRING(128); END_VAR If xDone is false, the code will perform the following actions: 1. Open the file for writing. 2. Convert the DINT array to a StringArray and write it to the file. 3. Close the file once writing is completed. Some suggestions mentioned could not be implemented at this stage. For error checking and ensuring that writing occurs only once, the xDone variable is utilized. Placing the array diData inside the VAR_IN_OUT block resolves error messages. The code has been improved accordingly. Thank you for your guidance.

Here are some additional "Code Golf" tips: If xDone is complete, then return; // eliminate the END_IF at the end. I am unsure about the significance of xDone. I anticipate that VAR_OUT-END_VAR will set xDone to FALSE each time it's called, so the IF-END_IF statement will always run. However, it's uncertain if CodeSys handles this correctly. What occurs if xDone is not initialized within VAR_OUT-END_VAR, and xDone := assignment is commented out? Will it result in a compilation error?

When it comes to the value of xDone, I would expect the VAR_OUT to initialize it to FALSE every time it is called. This means that the IF clause will always execute. However, it is uncertain whether CodeSys handles this correctly or sensibly. If the value of xDone is not initialized in the VAR_OUT stanza and the xDone := assignment is commented out, will the code fail to compile? Click to expand... Hello drbitboy, To address your question regarding xDone: If I do not initialize xDone, it defaults to FALSE. It appears to be a feature of CodeSys that all variables start with a value of FALSE or 0. Removing the xDone := TRUE; assignment from the code allows it to compile successfully and execute consistently, with the file being rewritten in each cycle. This can be observed by monitoring the modified time in Windows Explorer. In contrast, the provided code functions as intended. Once the writing is completed and xDone is set to TRUE, the file will no longer be overwritten, as evidenced by the unchanged modified date/time. For users who have upgraded to CODESYS version 3.5.20, it is important to note that PLC applications are no longer permitted to write to the local file system for security reasons. File creation and writing are now limited to the current application directory. This directory has been relocated from "%ProgramData%\CODESYS" to the following path: C:\Windows\System32\config\systemprofile\AppData\Roaming\CODESYS\CODESYSControlWinV3x64\...\PlcLogic. Further details can be found in the attachment.

Thank you for checking back. It appears that CODESYS functions in a similar manner to Fortran-IV, behaving like many Fortran functions that include a SAVE statement.

Indeed, handling DINT arrays in CODESYS can get a bit convoluted. Converting to STRING and adding newline characters seems a reasonable idea, though it could potentially add extra overhead, especially if your data sets are large. One possible alternative could involve writing a custom function in C that accepts DINT arrays and directly writes them to a file. This might bypass the need to convert DINTs to strings within the PLC logic and could theoretically be more efficient. However, I urge you to run some performance tests between your method and this proposed method to see what actually works better in your specific scenario. Regardless, it's refreshing to see someone taking the initiative to streamline such processes! Keep up the good work.

More Replies →

Streamline Your Asset Management
See How Oxmaint Works!!

✅   Work Order Management

✅   Asset Tracking

✅   Preventive Maintenance

✅   Inspection Report

We have received your information. We will share Schedule Demo details on your Mail Id.

To add a comment, please sign in or register if you haven't already..   

Frequently Asked Questions (FAQ)

FAQ: 1. Question: What was the challenge faced when writing a DINT array to a text file in CODESYS?

Answer: Answer: The challenge faced was related to efficiently transferring a DINT array to a text file in CODESYS, prompting the need to seek solutions from online forums.

FAQ: 2. Question: What line ending representation does CODESYS use for Windows OS?

Answer: Answer: CODESYS uses '$R$N' to represent CRLF (carriage return and line feed) for Windows OS line endings.

FAQ: 3. Question: How can error handling and verification be incorporated into file operations in CODESYS?

Answer: Answer: Error handling and verification can be incorporated by implementing additional checks and feedback mechanisms within the file handling function.

FAQ: 4. Question: Is converting the DINT array to an array of strings and adding newline characters for each element a more efficient method for writing to a text file?

Answer: Answer: Converting the DINT array to an array of strings and adding newline characters can be considered as a potential method for optimizing the process of writing DINT arrays to text files in CODESYS for improved efficiency.

Ready to Simplify Maintenance?

Join hundreds of satisfied customers who have transformed their maintenance processes.
Sign up today and start optimizing your workflow.

Request Demo  â†’