• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

在CODESYS数组导出为CSV

用户头像
it1352
帮助1

问题说明

我正在用另一个人的代码接管一个项目。我有一个PLC,目前有来自压力传感器和热电偶的输入。然后将数据缩放为PSI和华氏温度。从这些传感器中的每个传感器设置数据的方式将被格式化为一个数组。因此,一旦缩放数据,它就位于程序的网络变量列表中的数组中。我试图从数组中获取每个这些值,每隔一定的时间记录一次该值(例如,为了清晰起见,每秒记录一次),然后每秒钟将每个数据导出到CSV文件。甚至不知道该去哪里。这是我剩下的代码,但是我觉得它不必要地复杂?

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_);

我不确定该代码在哪里。它确实创建了一个CSV文件,但是我一直希望能够每秒为一段数据创建一个CSV文件吗?如果有人有任何想法或资源,我可以检查出来,这很棒。

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.

正确答案

#1

如何调用此例程的基本示例每秒可能是以下内容:

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

1)

您创建了一个FuncBlock来调用记录器块。
假设您称它为 LoggerTask

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)

之后,创建一个简单的步骤链:
(显然,您可以随意扩展和自定义它,例如在FileWrite无法写入文件或写入次数少于预期的情况下,应添加错误处理。)

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.)

实施部分:

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)

如您所见,只要xExecute设置为 true ,该块就会被执行。
为了重置步骤链,将xExecute设置为 false
只需周期性地运行此块,例如 fbLoggerTask(xExecute:= TRUE);
我不认为您发布了FileWrite块的所有代码,因为xDone不是set和xWrite不在任何地方检查。
因此,请确保在将String写入文件后(如果尚未实现)在一个周期内将xDone设置为true。

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).

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /reply/detail/tanhcfgaak
系列文章
更多 icon
同类精品
更多 icon
继续加载