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  <20202021  2022  2023  2024  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  <20202021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: Modbus port driver processing record with new value call back without a new value
From: Mark Rivers via Tech-talk <tech-talk at aps.anl.gov>
To: Tobin R Weber <webert2 at uw.edu>
Cc: "tech-talk at aps.anl.gov" <tech-talk at aps.anl.gov>
Date: Mon, 12 Oct 2020 19:38:35 +0000
Hi Toby,


What you are seeing reflects a design decision in the Modbus driver.  These are the relevant comments in the code:


        /* Process callbacks to device support. */

        /* See if there are any asynUInt32Digital callbacks registered to be called
         * when data changes.  These callbacks only happen if the value has changed */

...
        /* See if there are any asynInt32 callbacks registered to be called.
         * These are called even if the data has not changed, because we could be doing
         * ADC averaging */

So for asynUInt32 it only does the callbacks if the value has changed.  For asynInt32 it always does the callbacks, even if the value has not changed.  The reasoning is that the asynInt32 support can be used for ADCs which may use the asynInt32Average device support which does averaging, and so needs a callback for every value.

I understand that this is not a very good design.  What we would like is to have the behavior configurable per parameter or even per record.  But the asyn interfaces do not currently have a way to communicate that to the driver.

I think you can use the MDEL field of the ai record to prevent it from sending monitors when the difference from the previous value is less than MDEL.  But you cannot prevent the record from processing on each callback.

One option would be to put this check in the device support callback routine.  The driver would always call device support, but device support could decide whether to process the record or not.  The question is what record field would we use?  We should not use MDEL, because some users may be counting on the record to process on each callback but only send monitors if the delta is greater than or equal to MDEL.

This issue arises in the opposite sense for drivers written using asynPortDriver callbacks.  It never does callbacks if the value has not changed, but there are cases (like ADC averaging) where one does want a callback on every value.

Mark


________________________________
From: Tech-talk <tech-talk-bounces at aps.anl.gov> on behalf of Tobin R Weber via Tech-talk <tech-talk at aps.anl.gov>
Sent: Monday, October 12, 2020 2:04 PM
To: tech-talk at aps.anl.gov
Subject: Modbus port driver processing record with new value call back without a new value

Hello Ladies and Gentleman,

I have been reading 16-bit holding registers using modbus (function code 3) from an acromag device (XT-1541) and a DirectLogic DL 205 Modular PLC. Using the "ai" record, and "asynInt32" for the "DTYP" field, I am able to correctly read the 16-bit values. However, the "SCAN" field is set to "I/O Intr", and the record processes every time the modbus port driver is polled (every 100 msec, in my case) regardless of the status of the value (i.e., even if the value has not changed). I see an identical issue with the "longin" record. I have tried many different things, and it appears using the "asynUInt32Digital" for the "DTYP" field with the "longin" record fixes the problem. Unfortunately, this device support is not available for the "ai" record with modbus.

My question: Is this the specified behavior? I'm sure I'm doing something wrong, but I have no idea what at this point. Below is one simple example of the issue:

Here is the st.cmd file:
st.cmd: Modbus TPC/IP communication with a Acromag XT-1541.
---------------------------------------------------------------------------------------------------------
drvAsynIPPortConfigure("AcromagHVPS","10.10.10.176:502<http://10.10.10.176:502/>",0,0,1)
modbusInterposeConfig("AcromagHVPS", 0, 1000, 0)
drvModbusAsynConfigure("HVPSRead", "AcromagHVPS",0,3,0,9,1,100,"AcromagHVPS")

dbLoadRecords "db/test.db"

cd "${TOP}/iocBoot/${IOC}"
iocInit

asynSetTraceIOMask "HVPSRead",1,4
asynSetTraceMask "HVPSRead",1,0x000b
---------------------------------------------------------------------------------------------------------

Here is the record that is scanned every 100 msec, despite the value not changing:
test.db: "ai" record to read modbus data.
---------------------------------------------------------------------------------------------------------
record(ai, "HVPSBOReadRecord") {
  field(SCAN, "I/O Intr")
  field(DTYP, "asynInt32")
  field(INP, "@asynMask(HVPSRead, 1, -16, 1000)MODBUS_DATA ")
  field(FLNK, "iocHeartbeat")
}
---------------------------------------------------------------------------------------------------------

epics shell: Shows that the modbus data read properly, but the "HVPSBOReadRecord" record is continually processed with a callback, despite it's value not changing. And I have verified that this record is actually being processed with FLNK's to other records as well as by setting the "TPRO" field.
---------------------------------------------------------------------------------------------------------
2020/09/10 16:03:21.561 HVPSBOReadRecord devAsynInt32::interruptCallbackInput new value=12750
2020/09/10 16:03:21.561 HVPSBOReadRecord devAsynInt32::getCallbackValue from ringBuffer value=12750
2020/09/10 16:03:21.662 HVPSBOReadRecord devAsynInt32::interruptCallbackInput new value=12750
2020/09/10 16:03:21.662 HVPSBOReadRecord devAsynInt32::getCallbackValue from ringBuffer value=12750
2020/09/10 16:03:21.764 HVPSBOReadRecord devAsynInt32::interruptCallbackInput new value=12750
2020/09/10 16:03:21.764 HVPSBOReadRecord devAsynInt32::getCallbackValue from ringBuffer value=12750
epics> 2020/09/10 16:03:21.865 HVPSBOReadRecord devAsynInt32::interruptCallbackInput new value=12750
2020/09/10 16:03:21.865 HVPSBOReadRecord devAsynInt32::getCallbackValue from ringBuffer value=12750
2020/09/10 16:03:21.966 HVPSBOReadRecord devAsynInt32::interruptCallbackInput new value=12750
2020/09/10 16:03:21.967 HVPSBOReadRecord devAsynInt32::getCallbackValue from ringBuffer value=12750
...
---------------------------------------------------------------------------------------------------------


Conversely, if I use this record, the record is only processed when the input data changes:
test.db: "longin" record to read modbus data.
---------------------------------------------------------------------------------------------------------
record(longin, "HVPSBOReadRecord") {
  field(SCAN, "I/O Intr")
  field(DTYP, "asynUInt32Digital")
  field(INP, "@asynMask(HVPSRead, 1, 0xFFFF, 5000)MODBUS_DATA ")
  field(FLNK, "iocHeartbeat")
}
---------------------------------------------------------------------------------------------------------

epics shell: Shows that the modbus read data properly, and not processing the "HVPSBOReadRecord" record continuously with a callback. I also verified that this record is only processed when the value changes via the .TPRO field, and FLNK's to other records.
---------------------------------------------------------------------------------------------------------
2020/09/10 16:01:35.160 HVPSBOReadRecord devAsynUInt32Digital::interruptCallbackInput new value=12750
2020/09/10 16:01:35.160 HVPSBOReadRecord devAsynInt32::getCallbackValue from ringBuffer value=12750
epics>
---------------------------------------------------------------------------------------------------------

I'm using:
EPICS: 3.15.6
Asyn: R4-32
Modbus: >= 2-10-2

However I have since tried EPICS base-3.15.7, modbus 3-0, and asyn R4-38.

Thanks very much for any help.

Toby

--
Tobin Weber
University of Washington
Department of Aeronautics and Astronautics
Research Scientist
Lab: 206-543-2108

References:
Modbus port driver processing record with new value call back without a new value Tobin R Weber via Tech-talk

Navigate by Date:
Prev: Modbus port driver processing record with new value call back without a new value Tobin R Weber via Tech-talk
Next: How can I use pvapy or p4p to monitor multiple PVS 秦天 via Tech-talk <tech-talk at aps.anl.go
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  <20202021  2022  2023  2024 
Navigate by Thread:
Prev: Modbus port driver processing record with new value call back without a new value Tobin R Weber via Tech-talk
Next: How can I use pvapy or p4p to monitor multiple PVS 秦天 via Tech-talk <tech-talk at aps.anl.go
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  <20202021  2022  2023  2024 
ANJ, 12 Oct 2020 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·