Codesys - Data Logger

Mohd Faisal

Member
Join Date
Apr 2017
Location
Kuala Lumpur
Posts
2
Hi all,

I need help on how to create a data logger using Codesys.
I am using Overdigit PLC and I need to create a data log and save it to csv file.
Anyone have experience in this? I would really appreciate if anyone could share an example or maybe share a link?


Thank you in advance.
 
Welcome to the Forum !

That's not a very popular controller, but in general you need to find out if it supports a CoDeSys library that gives you access to its SD card.

Look for SysLibFile support in the user documentation: that's the basic library that should allow you access to the file system. Or look for hardware-specific
libraries called SD_Read and SD_Write.
 
Getting good at CoDeSys Ken!

OK. 1st of all the SysLibFile library should be supported by all CoDeSys controllers BUT that external SD is very important. If you don't have it I wouldn't risk constant writing to system flash (depending on your controller.) An external SC can be replaced when worn out which is not going to be the case with system flash.

Another point (and this may be too late) but here's a link to an application for WAGO PFC controllers. I haven't examined the source code but generally there isn't going to be anything too fancy. This is just a "drop in" kind of application.

www.youtube.com/watch?v=W--JcsNmzvs

Finally, some CoDeSys controllers support writing to SQL (MySQL or MS-SQL usually.) You may want to go that route if you're writing a lot of data often. Then you can use Excel or Access or whatever to retrieve your data.

Good luck!

Yosi
 
The Oscat network library has a nice set of logging components which can be used to write log files to csv, xml, html, either locally on your controller or to a server (ftp, smtp, rrd). Logging can be timed (every n seconds) or triggered (only write a log line when a predefined condition is met). See http://www.oscat.de/. This is a german site, however the libraries come with PDF documentation in English.
 
Hi Guys,

I have managed to create the data logger using the SysLibFile library.
I am new to codesys so it took me forever to figure it out.

Thanks for the help guys!;)
 
Not formatting correctly

The Oscat network library has a nice set of logging components which can be used to write log files to csv, xml, html, either locally on your controller or to a server (ftp, smtp, rrd). Logging can be timed (every n seconds) or triggered (only write a log line when a predefined condition is met). See http://www.oscat.de/. This is a german site, however the libraries come with PDF documentation in English.

Hi all,

I have tried to use the Oscat dlog to csv, however it does not seem to save in the correct format, e.g. I get my headings with values but the return characters appear randomly meaning parsing the data is a slog - especially at 1s intervals.
Please see the screenshot for details, data is misaligned.

Any suggestions?
:confused:

Screenshot 2021-12-15 134131.jpg
 
dtDate:=SysRTC23.SysRtcGetTime(TRUE);; //grab RTC date and time
FileName := GVL_Log.sDefaultPath;
FileName := CONCAT(FileName, '#A_#D_#H_Sys.CSV');
IF init THEN
enable:=FALSE;
init:=FALSE;
// x:=x_blank; //reset circular buffer
ELSE
enable:=TRUE;
END_IF

DateLog(x:=x,Column:='TimeStamp');
// Inverter Details
// BESS Outputs
IntLog0(X := x, Column := 'BESS State', Value := Main_v1.BESS_v4.o_BESS_State);
IntLog1(X := x, Column := 'Agg DCDC State', Value := Main_v1.BESS_v4.o_Agg_DCDCState);
IntLog2(X := x, Column := 'LG State', Value := GVL_Main.bmsBatt_State);
RealLog1(x:=x,Column:='SOC (%)',value:= GVL_Main.ONDBattData.AvgSOC,n:=1,d:='.');
RealLog2(x:=x,Column:='SOH (%)',value:=GVL_Main.ONDBattData.AvgSOH,n:=1,d:='.');
RealLog3(x:=x,Column:='Avg Cell Voltage (V)',value:= GVL_Main.ONDBattData.OND_AvgSUMCellVolt,n:=1,d:='.');
RealLog4(x:=x,Column:='Avg Cell Temperature (°C)',value:= GVL_Main.ONDBattData.OND_AvgModTemp,n:=1,d:='.');
BoolLog1(X:=x, Column := 'Battery ON', State := GVL_Main.bBatt_ON, OFF := 'OFF', ON := 'ON');
BoolLog2(X:=x, Column := 'Battery Fault', State := GVL_Main.bBatt_Fault, OFF := 'OK', ON := 'FAULT');
BoolLog3(X:=x, Column := 'Battery Warning', State := GVL_Main.bBatt_Warning, OFF := 'OK', ON := 'Warning');
RealLog5(x:=x,Column:='PV Production (kW)',value:= Main_v1.BESS_v4.o_rPVProd,n:=1,d:='.');

// Temperatures
RealLog6(x:=x,Column:='External Temperature (°C)',value:= GVL_AnalogueInputs.rPO_Ext_Temp,n:=1,d:='.');
RealLog7(x:=x,Column:='Internal Temperature 1 (°C)',value:= GVL_AnalogueInputs.rPO_Int_Temp1,n:=1,d:='.');
RealLog8(x:=x,Column:='Internal Temperature 2 (°C)',value:= GVL_AnalogueInputs.rPO_Int_Temp2,n:=1,d:='.');
RealLog9(x:=x,Column:='Internal Humidity (%)',value:= GVL_AnalogueInputs.rPO_Int_RH,n:=1,d:='.');

// Temperatures
RealLog10(x:=x,Column:='BESS2 Ext Temperature (°C)',value:= GVL_IOComms.unSlv_RegIn.strRegIn.fSys_ExtTemp,n:=1,d:='.');
RealLog11(x:=x,Column:='BESS2 Int Temperature 1 (°C)',value:= GVL_IOComms.unSlv_RegIn.strRegIn.fSys_ContTemp1,n:=1,d:='.');
RealLog12(x:=x,Column:='BESS2 Int Temperature 2 (°C)',value:= GVL_IOComms.unSlv_RegIn.strRegIn.fSys_ContTemp2,n:=1,d:='.');
RealLog13(x:=x,Column:='BESS2 Int Humidity (%)',value:= GVL_IOComms.unSlv_RegIn.strRegIn.fSys_ContRH,n:=1,d:='.');
// Digital IO
BoolLog4(X:=x, Column := 'Emergency Stop', State := GVL_DigitalIO.bSftyCntrler_E_Stop, OFF := 'OK', ON := 'EStop');
// Digital IO
BoolLog5(X:=x, Column := 'Emergency Stop BESS2', State := GVL_IOComms.unSlv_RegIn.strRegIn.wSys_EStopSts.0, OFF := 'OK', ON := 'EStop');
// LogCSV
LogCSV(x:=x,enable:=enable,Trig_M:=manual,Filename:=FileName,DTI:=dtDate,sep:=44,trig_t:=lograte);

////////////////////

Log rate is 1

/csv attached - *** edited to .txt for upload
 
Last edited:
changed quote to code to get indentation.

Code:
dtDate:=SysRTC23.SysRtcGetTime(TRUE);; //grab RTC date and time
FileName := GVL_Log.sDefaultPath;
FileName := CONCAT(FileName, '#A_#D_#H_Sys.CSV');


IF init THEN
     enable:=FALSE;
    init:=FALSE;
    //    x:=x_blank; //reset circular buffer
ELSE
    enable:=TRUE;
END_IF

DateLog(x:=x,Column:='TimeStamp');

    // Inverter Details
    // BESS Outputs
    IntLog0(X := x, Column := 'BESS State', Value := Main_v1.BESS_v4.o_BESS_State);
    IntLog1(X := x, Column := 'Agg DCDC State', Value := Main_v1.BESS_v4.o_Agg_DCDCState);
    IntLog2(X := x, Column := 'LG State', Value := GVL_Main.bmsBatt_State);
    RealLog1(x:=x,Column:='SOC (%)',value:= GVL_Main.ONDBattData.AvgSOC,n:=1,d:='.');
    RealLog2(x:=x,Column:='SOH (%)',value:=GVL_Main.ONDBattData.AvgSOH,n:=1,d:='.');
    RealLog3(x:=x,Column:='Avg Cell Voltage (V)',value:= GVL_Main.ONDBattData.OND_AvgSUMCellVolt,n:=1,d:='.');
    RealLog4(x:=x,Column:='Avg Cell Temperature (°C)',value:= GVL_Main.ONDBattData.OND_AvgModTemp,n:=1,d:='.');
    BoolLog1(X:=x, Column := 'Battery ON', State := GVL_Main.bBatt_ON, OFF := 'OFF', ON := 'ON');
    BoolLog2(X:=x, Column := 'Battery Fault', State := GVL_Main.bBatt_Fault, OFF := 'OK', ON := 'FAULT');
    BoolLog3(X:=x, Column := 'Battery Warning', State := GVL_Main.bBatt_Warning, OFF := 'OK', ON := 'Warning');
    RealLog5(x:=x,Column:='PV Production (kW)',value:= Main_v1.BESS_v4.o_rPVProd,n:=1,d:='.');
    
    // Temperatures
    RealLog6(x:=x,Column:='External Temperature (°C)',value:= GVL_AnalogueInputs.rPO_Ext_Temp,n:=1,d:='.');
    RealLog7(x:=x,Column:='Internal Temperature 1 (°C)',value:= GVL_AnalogueInputs.rPO_Int_Temp1,n:=1,d:='.');
    RealLog8(x:=x,Column:='Internal Temperature 2 (°C)',value:= GVL_AnalogueInputs.rPO_Int_Temp2,n:=1,d:='.');
    RealLog9(x:=x,Column:='Internal Humidity (%)',value:= GVL_AnalogueInputs.rPO_Int_RH,n:=1,d:='.');
    
    // Temperatures
    RealLog10(x:=x,Column:='BESS2 Ext Temperature (°C)',value:= GVL_IOComms.unSlv_RegIn.strRegIn.fSys_ExtTemp,n:=1,d:='.');
    RealLog11(x:=x,Column:='BESS2 Int Temperature 1 (°C)',value:= GVL_IOComms.unSlv_RegIn.strRegIn.fSys_ContTemp1,n:=1,d:='.');
    RealLog12(x:=x,Column:='BESS2 Int Temperature 2 (°C)',value:= GVL_IOComms.unSlv_RegIn.strRegIn.fSys_ContTemp2,n:=1,d:='.');
    RealLog13(x:=x,Column:='BESS2 Int Humidity (%)',value:= GVL_IOComms.unSlv_RegIn.strRegIn.fSys_ContRH,n:=1,d:='.');

    // Digital IO
     BoolLog4(X:=x, Column := 'Emergency Stop', State := GVL_DigitalIO.bSftyCntrler_E_Stop, OFF := 'OK', ON := 'EStop');
    // Digital IO
    BoolLog5(X:=x, Column := 'Emergency Stop BESS2', State := GVL_IOComms.unSlv_RegIn.strRegIn.wSys_EStopSts.0, OFF := 'OK', ON := 'EStop');

    // LogCSV    
    LogCSV(x:=x,enable:=enable,Trig_M:=manual,Filename:=FileName,DTI:=dtDate,sep:=44,trig_t:=lograte);

    ////////////////////

Log rate is 1

/csv attached - *** edited to .txt for upload
 
Last edited:
Well, it seems likely that the log library routines have bugs. This only confirms my opinion of Codesys, that as simple an application as this is not coded correctly. I'll bet I could do a better job in ladder, which is a terrible language in its own right. But I digress ...

The problem starts after 40 lines of data; every line except the last has 22 comma-separated fields. The timestamp makes it easy to reorder the fields and start new lines (cf. the BASH command below, which works in Linux and should also work in the WSL environment under Windows 10), but there are missing data; it appears the missing data are usually, but not always, some random number of fields from the end of each line.


tr -d \\r < 2021_12_15_Sys.txt | gawk -F, 'FNR==1{printf "%s",$0;next}{for (i=1; i<=NF; ++i) {printf "%s%s",($i~/^2021-/?"\r\n":","),$i}}END{printf "\r\n"}' | tee 2021_12_15_Sys_fixed.txt

 
Last edited:
I have used the CSV Utility library from CODESYS which is part of the IIoT Libraries SL library which is not free of charge (US$ 60/runtime). I did a project which requires logging of data from HART devices connected to a gateway. I do not think I would have figured out by myself writing a library with that functionality. Or maybe I would have, but it would have taken me a lot of time. The only problem I found with this library is that it does not have a function for WSTRING which is for Asian fonts. So if you only need to store ASCII data I recommend this library if you do not have too much time.

https://us.store.codesys.com/iiot-libraries-sl.html
 
Well, it seems likely that the log library routines have bugs. This only confirms my opinion of Codesys, that as simple an application as this is not coded correctly. I'll bet I could do a better job in ladder, which is a terrible language in its own right. But I digress ...

That is rather harsh and I am under the impression that you are cutting corners to drive a point home about Codesys where the lib we are looking at was not produced by 3S Software (the makers of codesys) but rather the product of an independent group of software developers. Codesys have nothing to do with Oscat other than that the Oscat libraries were written in Codesys.

What I see in the posted log file is quite typical for a buffer filling up faster than it can be emptied. At first everything seems to go fine. Then when the buffer gets full, data is lost because there is just no room for more.

Some possible causes spring to mind. One is that the file system where the log files are written to is not fast enough to keep up with a log line per second. Or the plc system is too busy to keep up with writing to the filesystem. Or the task where the routines are used is running with a rather long cycle time. We do not know what hardware is running this bit of code. And we do not know what else that hardware is doing.

One way or another, your bashing of codesys for this is barking up the wrong tree.
 

Similar Topics

Hello. I have been using CODESYS for years and had taken for granted that the PLC part was very similar to TwinCAT. but just found one issue that...
Replies
1
Views
1,964
Does anyone in the community have some experience to help a novice understand how to use the Configuration Assembly data for an Adapter device...
Replies
16
Views
7,850
This is a sort of beginner question, but I'd appreciate some input. I'm a longtime Rockwell user, and one of the convenient things about the A-B...
Replies
15
Views
4,775
Basically looking for a scatter plot, looking at the trace feature seems all the x-axis data is time-series only. I'd to display speed vs flow, so...
Replies
2
Views
1,891
I have an existing array in Global Variables, Test_Array: ARRAY [0..3,0..20] OF DINT that is working fine. I can see the values changing when I...
Replies
4
Views
5,230
Back
Top Bottom