Hm,
Not (yet) being a modbus expert, and fumbling in the dark:
There are 7 bytes send, and 5 received, right ?
That is all good, or ?
It looks as if the CRC send from the device is not matching what
the IOC code in modbusInterpose::readIt() expects.
What is wrong here ?
The CRC from the device, or the IOC code ?
Or does somebody have a better explanation ?
On 2026-02-03 14:16, William Jamieson wrote:
Thank you for the information. I have implemented everything across the
same virtual and physical port using the below settings in st.cmd:
/drvAsynSerialPortConfigure("rs485_port", "/dev/ttyUSB0", 0, 0, 0)
asynSetOption("rs485_port",0,"baud","19200")
asynSetOption("rs485_port",0,"parity","even")
asynSetOption("rs485_port",0,"bits","8")
asynSetOption("rs485_port",0,"stop","1")
modbusInterposeConfig("rs485_port",1,1000,0)/
The below commands are used to read in data via function 3 (st.cmd):
/drvModbusAsynConfigure("oxigraf_data_1", "rs485_port", 230, 3, 0, 7, 0,
200, "oxigraf")
drvModbusAsynConfigure("channel_o2_readings", "rs485_port", 230, 3, 35,
4, 0, 200, "oxigraf")
drvModbusAsynConfigure("pump_drive_level", "rs485_port", 230, 3, 10, 1,
0, 200, "oxigraf")
drvModbusAsynConfigure("command_codes", "rs485_port", 230, 3, 97, 3, 0,
200, "oxigraf")
/
I also began tracing the port to a file (st.cmd):
/asynSetTraceMask("rs485_port", 0, 0x09)
asynSetTraceIOMask("rs485_port", 0, 0x04)
asynSetTraceFile("rs485_port",0,"rs485_port-trace.txt")/
For the streamDevice portion of the communication, I am using one simple
proto file that directly sends binary to the serial and waits for a
reply. It is following the command structure specified in Section 3.3
of Modbus User Defined Command Format of the "MODBUS INTERFACE GUIDE
OXIGRAF MO2i FAMILY OXYGEN SENSORS" Manual, dated January 8, 2008. User-
defined command 100 is used.
Format of message specified by manual:
/Command: Addr 100 1 O2.H O2.L CRC.L CRC.H/
/Response: Addr 228 5 CRC.L CRC.H /
My proto file:
/Terminator = ;
ReplyTimeout = 200; # milliseconds
ReadTimeout = 2000;
calibrateLow{
out "\xe6\x64\x01\x08\x2a"; #e6 is the modbus slave address, 64
is user-defined command 100, 01 is the command specific to the device
"low end calibration", 08 2a is an integer describing cal gas
concentration (2090 for 20.90% O2). When I enable modbus interpose
config, the CRC is calculated and sent automatically as the trace below
shows.
in "\xe6\xe4\x05\x1b\x34"; # e6 is the modbus slave address, e4
is the expected response 228, 05 is the expected response 05, and 1b 34
are the expected CRC from the slave device
}/
When I process the stream record that calls the calibrateLow section of
the above proto file, the below trace happens:
/2026/02/03 07:59:40.410 /dev/ttyUSB0 write 7
e6 64 01 08 2a e5 39
/
/2026/02/03 07:59:40.434 /dev/ttyUSB0 read 5
e6 e4 05 1b 34
2026/02/03 07:59:40.435 modbusInterpose::readIt, CRC error/
The following errors also appear in the IOC shell:
/2026/02/03 07:59:40.434526 rs485_port lowCalibrate_BO: asynError in read:
2026/02/03 07:59:40.434555 rs485_port lowCalibrate_BO: I/O error after
reading 0 bytes: ""
2026/02/03 07:59:40.434568 rs485_port lowCalibrate_BO: Protocol aborted
2026/02/03 07:59:41.383 drvModbusAsyn::doModbusIO port
channel_o2_readings error calling writeRead,
error=asynManager::queueLockPort queueRequest timed out, nwrite=0/6, nread=0
2026/02/03 07:59:41.415 drvModbusAsyn::doModbusIO port pump_drive_level
error calling writeRead, error=asynManager::queueLockPort queueRequest
timed out, nwrite=0/6, nread=0
2026/02/03 07:59:41.447 drvModbusAsyn::doModbusIO port command_codes
error calling writeRead, error=asynManager::queueLockPort queueRequest
timed out, nwrite=0/6, nread=0
2026/02/03 07:59:41.562 drvModbusAsyn::doModbusIO port oxigraf_data_1
error calling writeRead, error=, nwrite=6/6, nread=5
2026/02/03 07:59:43.935 drvModbusAsyn::doModbusIO port
channel_o2_readings writeRead status back to normal having had 2 errors,
nwrite=6/6, nread=10
2026/02/03 07:59:44.862 drvModbusAsyn::doModbusIO port command_codes
writeRead status back to normal having had 2 errors, nwrite=6/6, nread=8
2026/02/03 07:59:44.990 drvModbusAsyn::doModbusIO port oxigraf_data_1
writeRead status back to normal having had 2 errors, nwrite=6/6, nread=16
2026/02/03 07:59:45.118 drvModbusAsyn::doModbusIO port pump_drive_level
writeRead status back to normal having had 2 errors, nwrite=6/6, nread=4/
The slave device accepts the command and behaves as expected, but
modbusInterpose throws the above CRC error. In addition, some nuisance
errors seem to appear from the brief break in modbus polling.
I think that modbusInterpose is interfering with what the stream expects
to see on its "in" line. I am not sure how to mend this. I have tried
getting rid of the CRC (\x1b\x34) on the "In" line of the proto file as
well, but that still results in the same "2026/02/03 07:59:40.435
modbusInterpose::readIt, CRC error."
William Jamieson
On Tue, Feb 3, 2026 at 2:32 AM Torsten Bögershausen <tboegi at edom.se
<mailto:tboegi at edom.se>> wrote:
On 2026-02-02 18:54, William Jamieson via Tech-talk wrote:
> Does anyone have experience using user-defined function codes
alongside
> the standard function codes that can be handled by the asyn MODBUS
> driver? I am currently using the MODBUS driver for the standard
03 "READ
> HOLDING REGISTERS" function while simultaneously using streamDevice
> driver for executing user-defined functions. This is resulting in
> conflicts between the MODBUS and streamDevice driver. I have tried
> setting up two virtual ports pointing to the same serial port:
> drvAsynSerialPortConfigure("rs485_modbus", "/dev/ttyUSB0", 0, 1, 0)
> drvAsynSerialPortConfigure("rs485_stream", "/dev/ttyUSB0", 0, 1, 0)
I think that this is the wrong approach - according to my understanding.
Both the modbus and streamdevice should lock the asynport.
("rs485_port")
Which should the lock the underlying device, "/dev/ttyUSB0".
If you enable all asyn traces (and direct them to a file)
there should be some light comming up, if there is a problem
here in synchronizing things.
Or if there is a problem with the hardware ?
>
> Then using a SEQ record that disables the rs485_modbus port then
enables
> the rs485_stream port before processing the stream record. after
> processing, it disables the rs485_stream port and re-enables the
> rs485_modbus port.
>
> I disable and enable ports by writing a 0 (disable) or 1 (enable) to
> the CNCT field of an ASYN record for each port. Example record:
> record (asyn, "modbusPort_ASYN")
> {
> field (PORT, "rs485_modbus")
> }
>
> Not only does this switchover create a lot of I/O Error messages
in the
> IOC shell, but this still results in a garbled data readback from
the
> stream record.
>
> Does anyone have a successful method of making these two methods
work in
> parallel? (or some other tools that make it work) Or should I
just give
> up and use deviceStream reads/writes instead of just the custom
ones. I
> prefer to use the MODBUS driver if possible for the standard MODBUS
> function codes.
>
> Thanks for any help!
>
> William Jamieson
> PPPL I&C Engineer
>
>
- Replies:
- Re: [External] Re: MODBUS User-Defined Function Codes Torsten Bögershausen via Tech-talk
- References:
- MODBUS User-Defined Function Codes William Jamieson via Tech-talk
- Re: MODBUS User-Defined Function Codes Torsten Bögershausen via Tech-talk
- Re: [External] Re: MODBUS User-Defined Function Codes William Jamieson via Tech-talk
- Navigate by Date:
- Prev:
Re: [External] Re: MODBUS User-Defined Function Codes William Jamieson via Tech-talk
- Next:
EPICS support for Micro4 controller from World Precision Instruments Neuman, Urszula (DLSLtd, RAL, CEO) 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: [External] Re: MODBUS User-Defined Function Codes William Jamieson via Tech-talk
- Next:
Re: [External] Re: MODBUS User-Defined Function Codes Torsten Bögershausen 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>
|