用CSV文件记录变量或报警趋势
CoDeSys是支持CSV Utility的,但收费50euro。通过caa file和systime,我们可以做一个每天自动更新csv文件、每秒更新变量趋势的PLC程序。
1 架构:
在C:\Example下创建一个模板文件,每天自动新建一个以日期命名的文件,如果一天多次开关机则保持源文件不变,直接往后加内容。
主要用到SysTime库获取日期和时间,CAA File用于异步写文件。
2 变量表:
PROGRAM PLC_PRG
VAR
tDelayTime:TIME:=T#3s;//每3秒写入一次
sTemplateFileName:FILE.CAA.FILENAME:='C:/Example/template.csv';//模板文件位置
fileOpen:FILE.Open;
fileCopy:FILE.Copy;
fileWrite:FILE.Write;
iState:INT;
dtDateAndTime:DT;
dtDate:DATE;
xEnable: BOOL;
sFileWriteName:File.CAA.FILENAME;
udiUtcTime:UDINT;
udiResult:UDINT;
udiUtcTimeLocal:UDINT;
ton_Delay:TON;
hFile:File.CAA.HANDLE;
arDataForTest:ARRAY[1..10] OF REAL:=[1.2,1.3,1.5,2.5,10.5,66.6,78.5,99.4,15.5,15.8];
iDataSize:INT:=10;
i:INT;
sWriteStr:STRING:='$n';//默认前面带一个换行
END_VAR
3 获取当前时间
CASE iState OF
0://get act date
IF xEnable THEN
udiUtcTime:=SysTimeRtcGet(udiResult);//获取rtc时间
udiResult := SysTimeRtcConvertUtcToLocal(udiUtcTime, udiUtcTimeLocal);//转为本地时间
dtDateAndTime:=UDINT_TO_DT(udiUtcTimeLocal);//转为DT格式,例如DT#1999-1-1-0:0:0
dtDate:=DT_TO_DATE(dtDateAndTime);//截取日期,例如D#1999-1-1
//ToString时会自动补0,所以只截取右边10位
sFileWriteName:=CONCAT('C:/FileUtilitiesExample/',RIGHT(DATE_TO_STRING(dtDate),10));
sFileWriteName:=CONCAT(sFileWriteName,'.csv');//格式
IF udiUtcTimeLocal <> 0 THEN//读取成功进入下一步
iState:=10;
END_IF
END_IF
4 尝试读取文件,如果不存在,则从模板文件复制
10://open act file or create file
fileOpen(xExecute:=TRUE,sFileName:=sFileWriteName,xExclusive:=FALSE,eFileMode:= File.MODE.MAPPD);
IF fileOpen.xDone THEN
iState:=50;//have file
hFile:=FileOpen.hFile;
fileOpen(xExecute:=FALSE);
ELSIF fileOpen.xError THEN
iState:=20;//no file,create it
fileOpen(xExecute:=FALSE);
END_IF
20://create file
fileCopy(xExecute:=TRUE,sFileNameDest:=sFileWriteName,sFileNameSource:=sTemplateFileName,xOverWrite:= TRUE);
IF FileCopy.xDone OR FileCopy.xError THEN
iState:=10;
fileCopy(xExecute:=FALSE);
END_IF
5 生成当前需要写入的行内容
50://generate string
//act local time
udiUtcTime:=SysTimeRtcGet(udiResult);
udiResult := SysTimeRtcConvertUtcToLocal(udiUtcTime, udiUtcTimeLocal);
dtDateAndTime:=UDINT_TO_DT(udiUtcTimeLocal);
sWriteStr:=CONCAT(sWriteStr,RIGHT(DT_TO_STRING(dtDateAndTime),8));//获取当前时间,例如00:00:00
sWriteStr:=CONCAT(sWriteStr,',');//csv分隔符
//add string 添加方式有很多种,这里只添加预先写的模板。实际可以取其他变量
FOR i := 1 TO iDataSize DO
//real型乘100后用TRUNC取整,再转为REAL后除100,可强制小数点后两位。
sWriteStr:=CONCAT(sWriteStr,REAL_TO_STRING(DINT_TO_REAL(TRUNC(arDataForTest[i]*100))/100));
IF i <> iDataSize THEN
sWriteStr:=CONCAT(sWriteStr,',');//最后一位不需要分隔符
ELSIF i = iDataSize THEN
iState:=60;
END_IF
END_FOR
6 写入到文件及延时
60://write to file
fileWrite(xExecute:=TRUE,hFile:=hFile,pBuffer:=ADR(sWriteStr),szSize:=INT_TO_UDINT(LEN(sWriteStr)));
IF fileWrite.xDone THEN
iState:=70;
sWriteStr:='$n';
fileWrite(xExecute:=FALSE);
ELSIF fileWrite.xError THEN
iState:= 32767;
FileWrite(xExecute:= FALSE);
END_IF
70://write delay
ton_Delay(IN:=TRUE,PT:=tDelayTime);
IF ton_Delay.Q THEN
ton_Delay(IN:=FALSE);
iState:=50;
END_IF
END_CASE
Comments: 2
你好,CodeSys 是否可以写txt文件,类似写日志文件。
可以的,用的是一样的方式,只是后缀名改一下。写文章时输出csv是因为要保存的数据有二十多个变量,txt不方便查看。