lt123
lt123

Reputation: 117

Exporting Array to CSV in CODESYS

I am taking over a project with code from another person. I have a PLC that currently has inputs in from pressure sensors and thermocouples. It then scales that data to PSI and temperature in fahrenheit. The way the data is set up from each of those sensors is to be formatted into an array. So, once the data is scaled it is in an array that is also in the Network Variable List of the program. I am trying to take each of these values from the array, record the value every certain amount of time (say 1 recording per second for sake of clarity), and then export each piece of data to a CSV file for every second. Not sure where to even go with this. This is the code I was left with, but I feel as if it it unnecessarily complicated?

//This is the support class for File_Handler
FUNCTION_BLOCK fileWrite
VAR_INPUT
    xWrite : BOOL;
    sData : STRING(200);
    uiLineLength : INT := 200;
    sDirectory : STRING := 'C:\ProgramData\CODESYS\CODESYSHMIWinV3\D5050FE1\PlcLogic\data';
    //sDirectory : STRING := '/home/cds-apps/PlcLogic/data/';
    sFilename : STRING;
END_VAR
VAR_OUTPUT
    BytesWritten : __XWORD;
    BytesWrittenTotal: DWORD;
    xDone: BOOL;
END_VAR
VAR
    hFile_: sysfile.RTS_IEC_HANDLE := sysfile.RTS_INVALID_HANDLE;
    FileWriteResult: sysfile.RTS_IEC_RESULT;
    FileOpenResult: sysfile.RTS_IEC_RESULT;
    state: INT;
    sys_Us_start: SYSTIME;
    sys_Us_end: SYSTIME;
    WriteTimeMS: ULINT;
END_VAR
sFilename := CONCAT(sDirectory, sFilename);
hFile_ := SysFileOpen(szFile:= sFilename, am:= ACCESS_MODE.AM_APPEND_PLUS, pResult:= ADR(FileOpenResult));
SysTimeGetUs(pUsTime:=sys_Us_start );
BytesWritten := SysFileWrite(hFile:= hfile_, pbyBuffer:= ADR(sData), ulSize:= uiLineLength, pResult:= ADR(FileWriteResult));    
BytesWrittenTotal := BytesWrittenTotal + BytesWritten;
SysTimeGetUs(pUsTime:=sys_Us_end );
WriteTimeMS := (sys_Us_end - sys_Us_start)/1000;
SysFileClose(hFile:= hFile_);

I am not sure where to go with this code. It does create a CSV file, but I was looking to be able to create a CSV file for a piece of data every second? If anyone has any thoughts or resources I could check out that would be great.

Upvotes: 0

Views: 3829

Answers (1)

Filippo Boido
Filippo Boido

Reputation: 1206

A basic example of how to call this routine every second could be the following:

1)

You create a FuncBlock that takes care of calling your logger block. Let's say you call it LoggerTask.

FUNCTION_BLOCK LoggerTask
VAR_INPUT
     sData : STRING(200);
     sFilename : STRING;
     xExecute : BOOL;
END_VAR

VAR
    fbRepeatTask : TON;
    fbFileWrite : FileWrite;
    uiStep : UINT;
END_VAR

2)

After that create a simple step chain: (You can obviously extend and customize it as you like, you should add error handling in the case when FileWrite fails to write to file or writes less than expected for example.)

Implementation part:

fbRepeatTask(PT:=T#1S);
fbFileWrite(sData := sData, sFileName := sFileName);

IF  xExecute 
    AND uiStep = 0
THEN
    uiStep := 10;
ELSIF NOT xExecute 
THEN
    uiStep := 0;
    fbFileWrite.xWrite := FALSE;
    fbRepeatTask.IN := FALSE;
END_IF

CASE uiStep OF

    10:

        fbFileWrite.xWrite := TRUE;
        IF fbFileWrite.xDone
        THEN
            fbFileWrite.xWrite := FALSE;
            uiStep := 20;
        END_IF

    20: 

        fbRepeatTask.IN := TRUE;
        IF fbRepeatTask.Q
        THEN
            fbRepeatTask.IN := FALSE;
            uiStep := 10;
        END_IF

END_CASE

3)

As you can see this block gets executed as soon as xExecute is set to true. In order to reset the step chain set xExecute to false. Just run this block cyclically for example like this fbLoggerTask(xExecute := TRUE); I don't think you posted all the code of your FileWrite block because xDone is not set and xWrite is not checked anywhere. So make sure that xDone is set to true for one cycle after the String is written to the file (if it's not already been implemented).

Upvotes: 0

Related Questions