EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  2025  <2026 Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  2025  <2026
<== Date ==> <== Thread ==>

Subject: Modbus Module Error
From: Luis Alberto De Sousa Moreira via Tech-talk <tech-talk at aps.anl.gov>
To: tech-talk at aps.anl.gov
Date: Wed, 22 Jul 2026 10:26:16 +0200
Hi All,
I'm looking into the Modbus Module at the moment. I'm using one of my Beckhoff PLC's as the server. this server is running and is connected to another client, so I know that it is working correctly.

The module is running but it fails to connect and my variables return 0.
I'm running on windows 11.

at this point I'm just reading 11 input registers.

I attach my .db and my st.cmd files.

this is what I get when I start the IOC:

D:\FalconDev\EPICS\modbus\iocBoot\iocTest>..\..\bin\windows-x64-mingw\modbusApp.exe BPS_Beck.cmd
# BPS_Beck.cmd
# Just testing the modbus module with my BPS Beckhoff PLC.
# 1. Cleanly lock network routing automatically at boot
epicsEnvSet("EPICS_CA_ADDR_LIST", "10.136.0.255")
epicsEnvSet("EPICS_CA_AUTO_ADDR_LIST", "NO")
epicsEnvSet("EPICS_CAS_INTF_ADDR_LIST", "10.136.0.34")
# gvl.mb_Input_Registers[10] := GVL.d_setpoint_T1;              // T1                   mS # gvl.mb_Input_Registers[11] := GVL.d_setpoint_TRamp1;  // Ramp1             uS # gvl.mb_Input_Registers[12] := GVL.d_setpoint_v1;              // V1                   10V # gvl.mb_Input_Registers[13] := GVL.d_setpoint_T2;              // T2                   mS # gvl.mb_Input_Registers[14] := GVL.d_setpoint_TRamp2;  // Ramp2             uS # gvl.mb_Input_Registers[15] := GVL.d_setpoint_V2;              // V2                   10V # gvl.mb_Input_Registers[16] := GVL.d_setpoint_T3;              // T3                   mS # gvl.mb_Input_Registers[17] := GVL.d_setpoint_TRamp3;  // Ramp3             uS # gvl.mb_Input_Registers[18] := GVL.d_setpoint_V3;              // V3                   10V # gvl.mb_Input_Registers[19] := GVL.d_setpoint_pulseLength;     // PulseLength  S /mS # gvl.mb_Input_Registers[20] := GVL.d_setpoint_TRampDown;       // RampDown             uS
dbLoadDatabase("../../dbd/modbusApp.dbd")
modbusApp_registerRecordDeviceDriver(pdbbase)
# Get the connection going
drvAsynIPPortConfigure("BPS_Beck", "10.136.0.30:502", 0, 0, 0)
2026/07/22 10:14:22.297 BPS_Beck -1 autoConnect could not connect: Can't connect to 10.136.0.30:502: Unknown error
modbusInterposeConfig("BPS_Beck", 0, 5000, 0)
asynSetOption("BPS_Beck",0, "disconnectOnReadTimeout", "Y")
# =========================================================================
# Configure Modbus Drivers Memory Blocks
# =========================================================================
# Syntax:
# drvModbusAsynConfigure("portName", "tcpPortName", slaveAddress, modbusFunction, modbusStartAddress, modbusLength, dataType, pollMsec, "plcType") # drvModbusAsynConfigure("modbusPortName", "asynPortName", slaveAddress, modbusFunction, startAddress, length, dataType, pollMsec, "plcType")
# Read Coils (Function Code 1)
# Reads 16 binary bits starting at offset 0, polling every 200 milliseconds.
# drvModbusAsynConfigure("READ_COILS", "PLC_NET", 0, 1, 0, 1, 0, 200, "OldPLC")
# Write Coils (Function Code 5)
# Configures a write-only path for coils. pollMsec is 0 because writes are instantaneous. # drvModbusAsynConfigure("WRITE_COILS", "PLC_NET", 0, 5, 0, 1, 0, 0, "OldPLC") # Reads 11 read-only 16-bit registers starting at offset 10, polling every 500 milliseconds.
# dataType=0 specifies standard 16-bit unsigned integers (UINT_16).
drvModbusAsynConfigure("READ_INPUTS", "BPS_Beck", 1, 4, 10, 11, 0, 500, "Beckhoff")
# Read Holding Registers (Function Code 3)
# Reads 1 read/write 16-bit register starting at offset 0, polling every 500 milliseconds.
# dataType=0 specifies standard 16-bit unsigned integers (UINT_16).
# drvModbusAsynConfigure("READ_HOLDING", "PLC_NET", 0, 3, 0, 1, 0, 500, "OldPLC")
# Block E: Write Holding Registers (Function Code 6)
# Configures a write-only path for single registers. pollMsec is 0 for on-demand writing. # drvModbusAsynConfigure("WRITE_HOLDING", "PLC_NET", 0, 6, 0, 1, 0, 0, "OldPLC")
# Enable ASYN_TRACEIO_HEX on octet server
 asynSetTraceIOMask("BPS_Beck",0,4)
# Enable ASYN_TRACE_ERROR and ASYN_TRACEIO_DRIVER on octet server
asynSetTraceMask("BPS_Beck",0,9)
dbLoadRecords("../../db/BPS_Beck.db")
iocInit
Starting iocInit
############################################################################
## EPICS R7.0.10
## Rev. 2026-07-01T08:47+0200
## Rev. Date build date/time:
############################################################################
2026/07/22 10:14:23.334 drvModbusAsyn::doModbusIO port READ_INPUTS error calling writeRead, error=asynManager::queueLockPort queueRequest failed: port BPS_Beck not connected, nwrite=0/6, nread=0
iocRun: All initialization complete
epics> ^C
D:\FalconDev\EPICS\modbus\iocBoot\iocTest>

Any assistance would be appreciated.
Thank you.
Kind Regards
               Luis

--
Luis Moreira
EPFL SB SPC-II, PPH241 (Batiment PPH) Station 13
CH-1015 Lausanne, Switzerland
Tel.    (+41) 21 693 58 37
E-Mail  luis.moreira at epfl.ch
# BPS_Beck.cmd
# Just testing the modbus module with my BPS Beckhoff PLC.

# 1. Cleanly lock network routing automatically at boot
epicsEnvSet("EPICS_CA_ADDR_LIST", "10.136.0.255")
epicsEnvSet("EPICS_CA_AUTO_ADDR_LIST", "NO")
epicsEnvSet("EPICS_CAS_INTF_ADDR_LIST", "10.136.0.34")

# gvl.mb_Input_Registers[10] := GVL.d_setpoint_T1;		// T1 			mS
# gvl.mb_Input_Registers[11] := GVL.d_setpoint_TRamp1;	// Ramp1 		uS
# gvl.mb_Input_Registers[12] := GVL.d_setpoint_v1;		// V1 			10V
# gvl.mb_Input_Registers[13] := GVL.d_setpoint_T2;		// T2			mS
# gvl.mb_Input_Registers[14] := GVL.d_setpoint_TRamp2;	// Ramp2		uS
# gvl.mb_Input_Registers[15] := GVL.d_setpoint_V2;		// V2			10V
# gvl.mb_Input_Registers[16] := GVL.d_setpoint_T3;		// T3			mS
# gvl.mb_Input_Registers[17] := GVL.d_setpoint_TRamp3;	// Ramp3		uS
# gvl.mb_Input_Registers[18] := GVL.d_setpoint_V3;		// V3		 	10V
# gvl.mb_Input_Registers[19] := GVL.d_setpoint_pulseLength;	// PulseLength	S /mS
# gvl.mb_Input_Registers[20] := GVL.d_setpoint_TRampDown;	// RampDown		uS

dbLoadDatabase("../../dbd/modbusApp.dbd")
modbusApp_registerRecordDeviceDriver(pdbbase)

# Get the connection going
drvAsynIPPortConfigure("BPS_Beck", "10.136.0.30:502", 0, 0, 0)
modbusInterposeConfig("BPS_Beck", 0, 5000, 0)					   
asynSetOption("BPS_Beck",0, "disconnectOnReadTimeout", "Y")

# =========================================================================
# Configure Modbus Drivers Memory Blocks 
# =========================================================================
# Syntax: 
# drvModbusAsynConfigure("portName", "tcpPortName", slaveAddress, modbusFunction, modbusStartAddress, modbusLength, dataType, pollMsec, "plcType")
# drvModbusAsynConfigure("modbusPortName", "asynPortName", slaveAddress, modbusFunction, startAddress, length, dataType, pollMsec, "plcType")

# Read Coils (Function Code 1)
# Reads 16 binary bits starting at offset 0, polling every 200 milliseconds.
# drvModbusAsynConfigure("READ_COILS", "PLC_NET", 0, 1, 0, 1, 0, 200, "OldPLC")

# Write Coils (Function Code 5)
# Configures a write-only path for coils. pollMsec is 0 because writes are instantaneous.
# drvModbusAsynConfigure("WRITE_COILS", "PLC_NET", 0, 5, 0, 1, 0, 0, "OldPLC")

# Reads 11 read-only 16-bit registers starting at offset 10, polling every 500 milliseconds.
# dataType=0 specifies standard 16-bit unsigned integers (UINT_16).
drvModbusAsynConfigure("READ_INPUTS", "BPS_Beck", 1, 4, 10, 11, 0, 500, "Beckhoff")

# Read Holding Registers (Function Code 3)
# Reads 1 read/write 16-bit register starting at offset 0, polling every 500 milliseconds.
# dataType=0 specifies standard 16-bit unsigned integers (UINT_16).
# drvModbusAsynConfigure("READ_HOLDING", "PLC_NET", 0, 3, 0, 1, 0, 500, "OldPLC")

# Block E: Write Holding Registers (Function Code 6)
# Configures a write-only path for single registers. pollMsec is 0 for on-demand writing.
# drvModbusAsynConfigure("WRITE_HOLDING", "PLC_NET", 0, 6, 0, 1, 0, 0, "OldPLC")

# Enable ASYN_TRACEIO_HEX on octet server
# asynSetTraceIOMask("BPS_Beck",0,4)
# Enable ASYN_TRACE_ERROR and ASYN_TRACEIO_DRIVER on octet server
# asynSetTraceMask("BPS_Beck",0,9)

dbLoadRecords("../../db/BPS_Beck.db")

iocInit

# =========================================================================
# EPICS Database for 11 Input Registers (Starting at Wire Offset 10)
# Driver Block Name: READ_INPUTS
# All values are processed as 16-bit Unsigned Integers (UINT_16)
# =========================================================================

# 1. d_setpoint_T1 (Wire Offset 10)
record(ai, "TEST:d_setpoint_T1") {
    field(DTYP, "asynInt32")
    field(INP,  "@asyn(READ_INPUTS, 0)UINT16")
    field(SCAN, "I/O Intr")
    field(DESC, "Setpoint T1")
}

# 2. d_setpoint_TRamp1 (Wire Offset 11)
record(ai, "TEST:d_setpoint_TRamp1") {
    field(DTYP, "asynInt32")
    field(INP,  "@asyn(READ_INPUTS, 1)UINT16")
    field(SCAN, "I/O Intr")
    field(DESC, "Setpoint TRamp1")
}

# 3. d_setpoint_v1 (Wire Offset 12)
record(ai, "TEST:d_setpoint_v1") {
    field(DTYP, "asynInt32")
    field(INP,  "@asyn(READ_INPUTS, 2)UINT16")
    field(SCAN, "I/O Intr")
    field(DESC, "Setpoint v1")
}

# 4. d_setpoint_T2 (Wire Offset 13)
record(ai, "TEST:d_setpoint_T2") {
    field(DTYP, "asynInt32")
    field(INP,  "@asyn(READ_INPUTS, 3)UINT16")
    field(SCAN, "I/O Intr")
    field(DESC, "Setpoint T2")
}

# 5. d_setpoint_TRamp2 (Wire Offset 14)
record(ai, "TEST:d_setpoint_TRamp2") {
    field(DTYP, "asynInt32")
    field(INP,  "@asyn(READ_INPUTS, 4)UINT16")
    field(SCAN, "I/O Intr")
    field(DESC, "Setpoint TRamp2")
}

# 6. d_setpoint_V2 (Wire Offset 15)
record(ai, "TEST:d_setpoint_V2") {
    field(DTYP, "asynInt32")
    field(INP,  "@asyn(READ_INPUTS, 5)UINT16")
    field(SCAN, "I/O Intr")
    field(DESC, "Setpoint V2")
}

# 7. d_setpoint_T3 (Wire Offset 16)
record(ai, "TEST:d_setpoint_T3") {
    field(DTYP, "asynInt32")
    field(INP,  "@asyn(READ_INPUTS, 6)UINT16")
    field(SCAN, "I/O Intr")
    field(DESC, "Setpoint T3")
}

# 8. d_setpoint_TRamp3 (Wire Offset 17)
record(ai, "TEST:d_setpoint_TRamp3") {
    field(DTYP, "asynInt32")
    field(INP,  "@asyn(READ_INPUTS, 7)UINT16")
    field(SCAN, "I/O Intr")
    field(DESC, "Setpoint TRamp3")
}

# 9. d_setpoint_V3 (Wire Offset 18)
record(ai, "TEST:d_setpoint_V3") {
    field(DTYP, "asynInt32")
    field(INP,  "@asyn(READ_INPUTS, 8)UINT16")
    field(SCAN, "I/O Intr")
    field(DESC, "Setpoint V3")
}

# 10. d_setpoint_pulseLength (Wire Offset 19)
record(ai, "TEST:d_setpoint_pulseLength") {
    field(DTYP, "asynInt32")
    field(INP,  "@asyn(READ_INPUTS, 9)UINT16")
    field(SCAN, "I/O Intr")
    field(DESC, "Setpoint Pulse Length")
}

# 11. d_setpoint_TRampDown (Wire Offset 20)
record(ai, "TEST:d_setpoint_TRampDown") {
    field(DTYP, "asynInt32")
    field(INP,  "@asyn(READ_INPUTS, 10)UINT16")
    field(SCAN, "I/O Intr")
    field(DESC, "Setpoint TRamp Down")
}




Navigate by Date:
Prev: Re: Pva-ify questions Kasemir, Kay via Tech-talk
Next: Release 2.4.1 of Archiver Appliance Sky Brewer via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  2025  <2026
Navigate by Thread:
Prev: Re: Pva-ify questions Kasemir, Kay via Tech-talk
Next: Release 2.4.1 of Archiver Appliance Sky Brewer via Tech-talk
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  2025  <2026
ANJ, 22 Jul 2026 · Home · News · About · Talk · Base · Modules · Extensions ·
· Distributions · Download · Documents · Links · Licensing ·