Hello everyone,
I am currently trying to connect a Belimo Energy Valve via Modbus TCP using Codesys 3.5 SP21 Patch 3 and the WagoAppPlcModbus Library version 1.1.5.13. Here is an excerpt from the Modbus interface description of the pump:
No distinction is made between data types (Discrete Inputs, Coils, Input Registers and Holding Registers). As a consequence, all data can be accessed with the two commands for Holding Register
All values in the register are unsigned integer data types. Exceptions are marked with **). Signed integers are represented as two’s complement
And here is an excerpt from the register list:
| No. | Address | Register | Access |
|---|---|---|---|
| 1 | 0 | Setpoint Relative [%] | R / W |
| 14 | 13 | Sensor 1 Temperature [°C] **) | R |
| 15 | 14 | Sensor 1 Temperature [°F] **) | R |
| 24 | 23 | Delta Temperature [K] | R |
| 25 | 24 | Delta Temperature [°F] | R |
**) → signed Integer
Currently, I am simulating a device (CODESYS Control Win V3 x64) on my computer, and later it will run on a PFC200.
I can ping the pump via Windows Terminal (PC and pump are in the same network), and I can also retrieve the pump values using the Mbpoll program. I have already successfully connected the pump via the device tree (Ethernet - Master - Slave) and read/write values. However, the requirements for the program are to dynamically add slaves at runtime through visualization configuration (e.g., specify slave IP address and port – registers for the device have already been pre-programmed in the background), similar to how the Wago WALM solution works.
My current program implementing this logic looks like this:
PROGRAM ModbusMasterTest
VAR_INPUT
Jobliste: ARRAY [0..1] OF typMbQuery := [
( //JOB 0, read inputs
bUnitId:= 1,
bFunctionCode:= 3,
uiReadAddress:= 0,
uiReadQuantity:= 30, // read the first 30 registers?
uiWriteAddress:= 0,
uiWriteQuantity:= 0,
awWriteData:= [125(0)]
),
( //JOB 1, write outputs (register access)
bUnitId:= 1,
bFunctionCode:= 16,
uiReadAddress:= 0,
uiReadQuantity:= 0,
uiWriteAddress:= 0,
uiWriteQuantity:= 1,
awWriteData:= [125(0)]
)];
END_VAR
VAR
iJobCounter : INT := 0;
xTrigger : BOOL := TRUE;
FB_F_Trig : F_Trig;
Responseliste : ARRAY [0..1] OF typMbResponse;
FB_ModbusMasterTCP: FbMbMasterTcp;
utKeepAlive : typKeepAlive := (
xEnable := TRUE,
tMaxIdleTime := T#5S, //TIME#5s0ms Maximum time of inactivity
tInterval := T#2S, //TIME#2s0ms Interval between two successive KA-Packets
udiProbes := 5 //5 Number of KA retry before giving up
);
END_VAR
// Call the communication block
FB_ModbusMasterTCP (xConnect := TRUE,
sHost := '192.168.4.112',
wPort := 502,
utKeepAlive := utKeepAlive,
eFrameType := eMbFrameType.Ethernet,
tTimeOut := T#2S,
utQuery := Jobliste[iJobCounter],
xTrigger := xTrigger,
utResponse := Responseliste[iJobCounter]);
// Wait for job completion
FB_F_Trig (clk:=xTrigger);
// Job completed, start next job
IF FB_F_Trig.Q THEN
xTrigger := TRUE;
iJobCounter := (iJobCounter+1) MOD 2;
END_IF
And this is my “Main” program:
PROGRAM PLC_PRG
VAR
Ain1 : WORD;
Ain2 : WORD;
AinArray : ARRAY [0..1] OF typMbResponse;
END_VAR
// Call the ModbusMaster subroutine
ModbusMasterTest();
Ain1 := ModbusMasterTest.Responseliste[0].awData[0];
Ain2 := ModbusMasterTest.Responseliste[0].awData[1];
AinArray := ModbusMasterTest.Responseliste;
This is what it looks like during execution:

Can someone help me? Because as I understand it, I am connected to the slave (pump) since xError is FALSE and oStatus shows nothing else. However, it still does not display any values. When I expand utResponse and the awData category in FB_ModbusMasterTCP, I only see zeros.
I also tried reading a specific register (e.g., uiReadAddress:= 13, uiReadQuantity:= 1), but had the same issue.
Thank you very much in advance!
