求TwinCAT中Beckhoff PLC数据导出为Excel/CSV的可用示例代码
Beckhoff PLC作业数据CSV记录实现需求
需要将Beckhoff PLC控制的模拟器中JobNo、Processing Time、JobID、Process Number等数据记录为CSV/Excel文件,要求每个作业对应一行数据,示例格式如下:
| Jobno | ProcessTime | JobID | ProcessNo |
|---|---|---|---|
| 1 | 20 | 100 | 200 |
| 2 | 40 | 101 | 320 |
已参考Beckhoff官方资料、联系技术支持,但现有代码运行出错;论坛解决方案过于复杂。现提供当前使用的DUT、GVL及MAIN程序代码,恳请提供可直接使用的文件写入示例程序。
现有DUT定义(ST_data)
TYPE ST_data : STRUCT JOB_ID : STRING(255); Processing_Time : STRING(255); Setup_Time : STRING(255); Due_Date : STRING(255); END_STRUCT END_TYPE
现有全局变量列表(GVL)
{attribute 'qualified_only'} VAR_GLOBAL MACHINE : ARRAY[1..50] OF ST_data; sen5 : BOOL; sen2 : BOOL; state : BOOL; count :INT; hit: BOOL; tdelta : ULINT; tstart : ULINT; tend : ULINT; setuptime : LREAL; END_VAR
现有MAIN程序变量定义
PROGRAM MAIN VAR FB_FileOpen: FB_FileOpen; FB_FileWrite: FB_FileWrite; FB_FileClose: FB_FileClose; hFile: UINT; sPathName: T_MaxString; sWriteBuffer : STRING(5000); sBufferTemp : STRING(1000); // Temporary string that will hold the string that needs to be added to the full string bBuffTemp : BOOL ; //check if the strings have been concatinated sFormat : STRING(255); state: INT; bWrite: BOOL; NT_GetTime: NT_GetTime; bFill: BOOL; i: INT; FB_FormatString2: FB_FormatString2; trigger: BOOL; END_VAR
现有MAIN程序逻辑代码
//counter code //========================================================================================== IF GVL.sen5 = FALSE AND GVL.hit = FALSE THEN GVL.count := GVL.count +1; GVL.hit := TRUE; ELSIF GVL.sen5 = TRUE AND GVL.hit = TRUE THEN GVL.hit := FALSE; END_IF IF gvl.sen5= TRUE THEN GVL.tstart := F_GetSystemTime(); END_IF IF GVL.sen2 = TRUE THEN GVL.tend := F_GetsystemTime(); //trigger := TRUE; // this will trigger the file writing commands END_IF GVL.tdelta := GVL.tend - GVL.tstart; GVL.setuptime := GVL.tdelta*EXPT(10,-7); //Entering some value in array //========================================================================================== IF bFill THEN FOR i := 1 TO 50 BY 1 DO GVL.MACHINE[i].Due_Date :='10823'; //WORD_TO_STRING(NT_GetTime.TIMESTR.wDayOfWeek); GVL.MACHINE[i].JOB_ID := INT_TO_STRING(GVL.count) ;//INT_TO_STRING(i); GVL.MACHINE[i].Processing_Time := '125';//WORD_TO_STRING(NT_GetTime.TIMESTR.wMinute); GVL.MACHINE[i].Setup_Time := LREAL_TO_STRING(GVL.setuptime);//WORD_TO_STRING(NT_GetTime.TIMESTR.wSecond); END_FOR bFill := FALSE; END_IF //Functioin block to get local time //=========================================== IF NT_GetTime.start AND NOT NT_GetTime.BUSY THEN NT_GetTime.START :=FALSE; ELSE NT_GetTime.START := TRUE; END_IF NT_GetTime( NETID:='' , START:= , TMOUT:= , BUSY=> , ERR=> , ERRID=> , TIMESTR=> ); //CASE STATEMENT to handle writing //=========================================== CASE state OF 0: IF bWrite THEN // switch to true or false to control the execution State :=5; bWrite := FALSE; END_IF 5:// creating the file sPathName := CONCAT('C:\Users\Manjot Sanghera\Desktop\CSVRECORD',WORD_TO_STRING(NT_GetTime.TIMESTR.wDay)); sPathName := CONCAT(sPathName,'.'); sPathName := CONCAT(sPathName,WORD_TO_STRING(NT_GetTime.TIMESTR.wHour)); //sPathName := CONCAT(sPathName,'.'); //sPathName := CONCAT(sPathName,WORD_TO_STRING(NT_GetTime.TIMESTR.wMinute)); sPathName := CONCAT(sPathName,'_TestFile.csv'); State := 10; FB_FileOpen.bExecute := TRUE; 10: FB_FileOpen.bExecute := TRUE; IF NOT FB_FileOpen.bBusy AND NOT FB_FileOpen.bError THEN FB_FileOpen.bExecute := FALSE; State := 15; END_IF 15 : sWriteBuffer :='Due_Date, Job_ID, Processin_Time,Setup_Time $n'; sFormat :='%s, %s, %s, %s $n'; FOR i := 1 TO 50 BY 1 DO // loop is required so that you can loop through each line/row/arrayelement FB_FormatString2( pFormatString:= ADR(sFormat), arg1:= F_STRING(GVL.MACHINE[i].Due_Date), arg2:= F_STRING(GVL.MACHINE[i].JOB_ID), arg3:= F_STRING(GVL.MACHINE[i].Processing_Time), arg4:= F_STRING(GVL.MACHINE[i].Setup_Time), pDstString:= ADR(sBufferTemp) , nDstSize:= SIZEOF(sBufferTemp), bError=> , nErrId=> ); bBuffTemp := CONCAT2( pSrcString1 := ADR(sWriteBuffer),//main string pSrcString2 := ADR(sBufferTemp), //String to be added pDstString := ADR(sWriteBuffer),//destinatioin of the string nDstSize := SIZEOF(sWriteBuffer));//size of the final string END_FOR //sWriteBuffer := 'Job_ID__|__Processing_Time__|__SetupTime'; State := 20; FB_FileWrite.bExecute := TRUE; 20: FB_FileWrite.bExecute := TRUE; IF NOT FB_FileWrite.bBusy AND NOT FB_FileWrite.bError THEN FB_FileWrite.bExecute := FALSE; State := 30; FB_FileClose.bExecute := TRUE; END_IF 30: IF NOT FB_FileClose.bBusy AND NOT FB_FileClose.bError THEN FB_FileClose.bExecute := FALSE; State:= 0; END_IF END_CASE //OPEN, WRITE, CLOSE FILE //=========================================== FB_FileOpen( sNetId:= '', sPathName:= sPathName , nMode:= FOPEN_MODEWRITE OR FOPEN_MODEPLUS, ePath:= PATH_GENERIC, bExecute:= , tTimeout:= , bBusy=> , bError=> , nErrId=> , hFile=> hFile); FB_FileWrite( sNetId:= '', hFile:= hFile, pWriteBuff:= ADR(sWriteBuffer) , cbWriteLen:= SIZEOF(sWriteBuffer), bExecute:= , tTimeout:= , bBusy=> , bError=> , nErrId=> , cbWrite=> ); FB_FileClose( sNetId:= '', hFile:= hFile , bExecute:= , tTimeout:= , bBusy=> , bError=> , nErrId=> );
预期功能
计数器统计作业数量,完成一个作业后将对应数据写入CSV文件的一行;第二个作业数据就绪后,继续写入下一行。
内容的提问来源于stack exchange,提问作者manjot sanghera
相关产品推荐
相关产品推荐

