FB_FileOpen 保持忙碌,状态机不工作 - TwinCat 3

FB_FileOpen stays busy, Statemachine not working - TwinCat3

我正在尝试进入 beckhoff/twincat 宇宙,因此我正在学习一些 twincat 教程。在编写一个简单的事件记录器时,我遇到了以下问题:

执行 FB_FileOpen 后,它的 bBusy 变量保持为 True - 因此我的状态机不会进一步执行并卡在 FILE_OPEN。任何想法,我做错了什么?这是我的代码:

VAR
    
FileOpen : FB_FileOpen := (sPathName := 'C:\Events-log.txt', nMode := FOPEN_MODEAPPEND OR FOPEN_MODETEXT);
FileClose :FB_FileClose;
FilePuts : FB_FilePuts;
stEventWrittenToFile : ST_Event;
CsvString : T_MaxString;

eWriteState :(TRIGGER_FILE_OPEN, FILE_OPEN, WAIT_FOR_EVENT,TRIGGER_WRITE_EVENT, WRITE_EVENT, FILE_CLOSE, ERROR);

END_VAR


CASE eWriteState OF 

    TRIGGER_FILE_OPEN : 
        FileOpen(bExecute := TRUE); 
        eWriteState := FILE_OPEN;
        

    FILE_OPEN :
            
        FileOpen(bExecute := FALSE);
        IF FileOpen.bError THEN
            eWriteState := ERROR;
        ELSIF NOT FileOpen.bBusy AND FileOpen.hFile <> 0 THEN
            eWriteState := WAIT_FOR_EVENT;
        END_IF
            
    WAIT_FOR_EVENT :

        //Do nothing, triggered externally by method
        
    TRIGGER_WRITE_EVENT :
            CsvString := ConvertStructureToString(stEvent := stEventWrittenToFile); 
            FilePuts(   sLine:= CsvString,
                        hFile := FileOpen.hFile,
                                bExecute := TRUE,); 
            eWriteState := WRITE_EVENT;
        
    WRITE_EVENT : 
        FilePuts(bExecute := FALSE);
        IF FilePuts.bError THEN
            eWriteState := ERROR;
        ELSIF NOT FilePuts.bBusy THEN
            eWriteState := FILE_CLOSE;
        END_IF
    

    FILE_CLOSE :
        FileClose(  hFile := FileOpen.hFile,
                    bExecute := TRUE);
        IF FileClose.bError = TRUE THEN
            FileClose.bExecute := FALSE;
            eWriteState := ERROR;
        ELSIF NOT FileClose.bBusy THEN
            FileClose.bExecute := FALSE;
            eWriteState := TRIGGER_FILE_OPEN;
        END_IF          
    
    ERROR : // Do nothing





END_CASE

问题可能在于您如何调用功能块。您需要确保使用输入 bExecute := FALSE 调用功能块,并且只有在使用 bExecute := TRUE 调用它之后才会触发功能块执行。将 fb 的“执行”输入设置为 false 触发输入后,它将始终有效,因此只需反转 TRUE 和 FALSE 的顺序即可对所有状态执行。

TRIGGER_FILE_OPEN:
    fileOpen(bExecute := FALSE);
    eWriteState := FILE_OPEN;

FILE_OPEN:
    fileOpen(bExecute := TRUE);
...

您也可以按照他们网站上提供的 Beckhoff 示例进行操作,但不喜欢这个,而是调用功能块两次,在一个 PLC 循环中背靠背调用:

  (* Open source file *) 
          fbFileOpen( bExecute := FALSE ); 
          fbFileOpen( sNetId := sSrcNetId, 
                      sPathName := sSrcPathName, 
                      nMode := FOPEN_MODEREAD OR FOPEN_MODEBINARY, 
                      ePath := PATH_GENERIC, 
                      tTimeout := tTimeOut, 
                      bExecute := TRUE ); 

完整示例可在此处找到:https://infosys.beckhoff.com/english.php?content=../content/1033/tcplclib_tc2_system/30977547.html&id=

我发现了错误。 我的错误是,我从 start 变量的正边缘启动了状态机。由于我是 运行 1ms 周期内的任务,所以整个事情需要在 1ms 内完成。