Twincat 3 使用 FB_MBReadRegs Modbus
Twincat 3 Using FB_MBReadRegs Modbus
当 Factory IO 是 sending/receiving 输入和保持寄存器时,我无法 FB_MBReadinputs 在 Twincat 中工作。
首先,这是我目前正在使用的从 Factory IO 处理 Modbus 的片段:
VAR
GAB_FactoryIO_Inputs AT %I* : ARRAY [0..15] OF BYTE;
...
END_VAR
LFB_MBReadInputs(
sIPAddr := '192.168.0.109',
nTCPPort := 505,
nUnitID := 255,
nQuantity := 64,
nMBAddr := 0,
cbLength := SIZEOF(IO.GAB_FactoryIO_Inputs),
pDestAddr := ADR(IO.GAB_FactoryIO_Inputs),
bExecute := TRUE,
tTimeout := T#1S,
bBusy => ,
bError => ,
nErrId => ,
cbRead => ,
);
LFB_MBReadInputs(bExecute := FALSE);
它在状态机中运行并愉快地产生字节,由 MBWriteCoils 再次写入。
但我无法开始工作的是 FB_MBReadRegs。
Beckhoff 的示例在 MBReadInputs 和 MBReadRegs 之间看起来几乎相同,我首先得到 ADS 错误 1794 并将 VAR 更改为 DINT 和 WORD,但现在除了错误之外没有任何反应。
我期待 X、Y 和 Z 坐标到寄存器上的任何字节、位或整数,但绝对没有任何反应。
我已经尝试简化并找出问题所在,这是当前发生的事情:
VAR
GAB_FactoryIO_RegsIN AT %I* : ARRAY [0..5] OF DINT;
LFB_MBReadRegs(
sIPAddr := '192.168.0.109',
nTCPPort := 505,
nUnitID := 255,
nQuantity := 16,
nMBAddr := 0,
cbLength := 100,
pDestAddr := ADR(IO.GAB_FactoryIO_RegsIN),
bExecute := TRUE,
tTimeout := T#1S,
bBusy => ,
bError => ,
nErrId => ,
cbRead => ,
);
LFB_MBReadRegs(bExecute := FALSE);
根据我的理解添加@kolyur 的建议作为状态机的一部分。
显然,现在我已经重新尝试过了,IF FB_MBReadRegs=bBusy THEN... 不起作用。 “必须实例化错误功能块 'FB_MBReadRegs' 才能访问”。这就是明天要解决的项目。
玩了一段时间后,我仍然没有完全掌握使用或不使用 %I*,但 %M*(或 %MB0 和 %MB64)确实做到了。在 https://forge.codesys.com/forge/talk/CODESYS-V2/thread/cc22cd1dc1/ 中找到部分解决方案
无论如何,我误解了 MBReadRegs 的作用,因为 MBReadInputRegs 是从 Factorio 接收位置 info/whatever 时的位置。
下面显然是工作代码片段:
VAR_GLOBAL
GAB_FactoryIO_Inputs AT %I* : ARRAY [0..15] OF BYTE; //I/O between Factory IO and TC
GAB_FactoryIO_Outputs AT %Q* : ARRAY [0..15] OF BYTE;
GAB_FactoryIO_RegsIN AT %MB0 : ARRAY [0..5] OF WORD; // %M* on both didnt work, coordinates spiraled to thousands
GAB_FactoryIO_RegsOUT AT %MB32 : ARRAY [0..5] OF WORD;
END_VAR
VAR;
LFB_MBReadInputRegs : FB_MBReadInputRegs ;
END_VAR
CASE iState OF
//...other states in between
10: //next is in its own file
LFB_MBReadInputRegs(
sIPAddr := '192.168.0.109',
nTCPPort := 505,
nUnitID := 255,
nQuantity := 12,
nMBAddr := 0,
cbLength := 100,
pDestAddr := ADR(IO.GAB_FactoryIO_RegsIN),
bExecute := TRUE,
tTimeout := T#1S,
bBusy => ,
bError => ,
nErrId => ,
cbRead => ,
);
LFB_MBReadInputRegs(bExecute := FALSE);
//5ms wait routine and jump to next iState
稍后再编辑:
bErr 1794 不会消失的新情况。
- 出于某种原因,cbLength 不再喜欢 100,但必须读取其大小
- 也重启。如果我只是切断 PLC 电源开关的电源,就可以避免无用的故障排除。尽管逻辑上认为软件重启也一样好,但内存问题还是通过硬重置得到了改善。
IF NOT bModbusBusy4 THEN
bModbusBusy4 := TRUE;
fbMBReadInputRegs (
sIPAddr := ipAddr,
nTCPPort := 506,
nUnitID := 255,
nQuantity := 32,
nMBAddr := 0,
cbLength := SIZEOF(TIO.GAB_FactoryIO_RegsIN),
pDestAddr := ADR(TIO.GAB_FactoryIO_RegsIN),
bExecute := TRUE,
tTimeout := T#1S,
bBusy => ,
bError => ,
nErrId => ,
cbRead => ,
);
ELSE
IF NOT fbMBReadInputRegs.bBusy THEN
bModbusBusy4 := FALSE;
END_IF
fbMBReadInputRegs(bExecute := FALSE);
END_IF
我注意到的几件事:
- MBReadRegs 将写入您的数组 GAB_FactoryIO_RegsIN 但您已在输入 space %I* 中配置此变量。这有什么原因吗?
- 在您的第二个示例中,您正在读取 16 个字,但目标变量只有 12 个字(ARRAY [0..5] OF DINT)。这可能是 ADS 错误 1794“无效索引组”的原因。对于 MBReadRegs,nQuantity 指的是 16 位字,而 MBReadInputs 指的是位。
- 您在每次扫描时都触发了 bExecute 位。通常你应该触发一次并等待 bBusy 位变为假再触发。
当 Factory IO 是 sending/receiving 输入和保持寄存器时,我无法 FB_MBReadinputs 在 Twincat 中工作。
首先,这是我目前正在使用的从 Factory IO 处理 Modbus 的片段:
VAR
GAB_FactoryIO_Inputs AT %I* : ARRAY [0..15] OF BYTE;
...
END_VAR
LFB_MBReadInputs(
sIPAddr := '192.168.0.109',
nTCPPort := 505,
nUnitID := 255,
nQuantity := 64,
nMBAddr := 0,
cbLength := SIZEOF(IO.GAB_FactoryIO_Inputs),
pDestAddr := ADR(IO.GAB_FactoryIO_Inputs),
bExecute := TRUE,
tTimeout := T#1S,
bBusy => ,
bError => ,
nErrId => ,
cbRead => ,
);
LFB_MBReadInputs(bExecute := FALSE);
它在状态机中运行并愉快地产生字节,由 MBWriteCoils 再次写入。
但我无法开始工作的是 FB_MBReadRegs。 Beckhoff 的示例在 MBReadInputs 和 MBReadRegs 之间看起来几乎相同,我首先得到 ADS 错误 1794 并将 VAR 更改为 DINT 和 WORD,但现在除了错误之外没有任何反应。 我期待 X、Y 和 Z 坐标到寄存器上的任何字节、位或整数,但绝对没有任何反应。
我已经尝试简化并找出问题所在,这是当前发生的事情:
VAR
GAB_FactoryIO_RegsIN AT %I* : ARRAY [0..5] OF DINT;
LFB_MBReadRegs(
sIPAddr := '192.168.0.109',
nTCPPort := 505,
nUnitID := 255,
nQuantity := 16,
nMBAddr := 0,
cbLength := 100,
pDestAddr := ADR(IO.GAB_FactoryIO_RegsIN),
bExecute := TRUE,
tTimeout := T#1S,
bBusy => ,
bError => ,
nErrId => ,
cbRead => ,
);
LFB_MBReadRegs(bExecute := FALSE);
根据我的理解添加@kolyur 的建议作为状态机的一部分。
显然,现在我已经重新尝试过了,IF FB_MBReadRegs=bBusy THEN... 不起作用。 “必须实例化错误功能块 'FB_MBReadRegs' 才能访问”。这就是明天要解决的项目。
玩了一段时间后,我仍然没有完全掌握使用或不使用 %I*,但 %M*(或 %MB0 和 %MB64)确实做到了。在 https://forge.codesys.com/forge/talk/CODESYS-V2/thread/cc22cd1dc1/ 中找到部分解决方案 无论如何,我误解了 MBReadRegs 的作用,因为 MBReadInputRegs 是从 Factorio 接收位置 info/whatever 时的位置。
下面显然是工作代码片段:
VAR_GLOBAL
GAB_FactoryIO_Inputs AT %I* : ARRAY [0..15] OF BYTE; //I/O between Factory IO and TC
GAB_FactoryIO_Outputs AT %Q* : ARRAY [0..15] OF BYTE;
GAB_FactoryIO_RegsIN AT %MB0 : ARRAY [0..5] OF WORD; // %M* on both didnt work, coordinates spiraled to thousands
GAB_FactoryIO_RegsOUT AT %MB32 : ARRAY [0..5] OF WORD;
END_VAR
VAR;
LFB_MBReadInputRegs : FB_MBReadInputRegs ;
END_VAR
CASE iState OF
//...other states in between
10: //next is in its own file
LFB_MBReadInputRegs(
sIPAddr := '192.168.0.109',
nTCPPort := 505,
nUnitID := 255,
nQuantity := 12,
nMBAddr := 0,
cbLength := 100,
pDestAddr := ADR(IO.GAB_FactoryIO_RegsIN),
bExecute := TRUE,
tTimeout := T#1S,
bBusy => ,
bError => ,
nErrId => ,
cbRead => ,
);
LFB_MBReadInputRegs(bExecute := FALSE);
//5ms wait routine and jump to next iState
稍后再编辑:
bErr 1794 不会消失的新情况。
- 出于某种原因,cbLength 不再喜欢 100,但必须读取其大小
- 也重启。如果我只是切断 PLC 电源开关的电源,就可以避免无用的故障排除。尽管逻辑上认为软件重启也一样好,但内存问题还是通过硬重置得到了改善。
IF NOT bModbusBusy4 THEN
bModbusBusy4 := TRUE;
fbMBReadInputRegs (
sIPAddr := ipAddr,
nTCPPort := 506,
nUnitID := 255,
nQuantity := 32,
nMBAddr := 0,
cbLength := SIZEOF(TIO.GAB_FactoryIO_RegsIN),
pDestAddr := ADR(TIO.GAB_FactoryIO_RegsIN),
bExecute := TRUE,
tTimeout := T#1S,
bBusy => ,
bError => ,
nErrId => ,
cbRead => ,
);
ELSE
IF NOT fbMBReadInputRegs.bBusy THEN
bModbusBusy4 := FALSE;
END_IF
fbMBReadInputRegs(bExecute := FALSE);
END_IF
我注意到的几件事:
- MBReadRegs 将写入您的数组 GAB_FactoryIO_RegsIN 但您已在输入 space %I* 中配置此变量。这有什么原因吗?
- 在您的第二个示例中,您正在读取 16 个字,但目标变量只有 12 个字(ARRAY [0..5] OF DINT)。这可能是 ADS 错误 1794“无效索引组”的原因。对于 MBReadRegs,nQuantity 指的是 16 位字,而 MBReadInputs 指的是位。
- 您在每次扫描时都触发了 bExecute 位。通常你应该触发一次并等待 bBusy 位变为假再触发。