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 );
我发现了错误。
我的错误是,我从 start 变量的正边缘启动了状态机。由于我是 运行 1ms 周期内的任务,所以整个事情需要在 1ms 内完成。
我正在尝试进入 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 );
我发现了错误。 我的错误是,我从 start 变量的正边缘启动了状态机。由于我是 运行 1ms 周期内的任务,所以整个事情需要在 1ms 内完成。