Folks,
The current asyn Modbus driver supports the following data types:
typedef enum {
dataTypeBinary,
dataTypeSignedBinary,
dataTypeBCD,
dataTypeSignedBCD
} modbusDataType;
The current driver has the following limitations:
- It does not support floating point or 32-bit integers, because these are not defined in the Modbus specification. However, many vendors use Modbus for such data, and it seems reasonable to support this directly in the driver, rather than having to do conversions with CALC records in the database.
- It does not support 16-bit 2's complement numbers, because type dataTypeBinary assumes unsigned 16-bit integers and does not do sign extension when converting to epicsInt32.
- All addresses in the register block for a single asyn port driver must be the same data type. It would be better to be able to mix data types in the register block, since this can reduce the required number of port drivers.
I thus propose to make the following changes:
- For backwards compatibility keep the modbusDataType argument to drvModbusAsynConfigure. If the user omits the drvUser string in the link specification, or uses the current default of MODBUS_DATA it will use the modbusDataType defined in drvModbusAsynConfigure for all registers in the block for that port. Thus, existing IOCs will continue to work with no changes to databases or startup scripts.
- Extend the current definition of modbusDataType as follows. The first 4 entries have the same meaning as at present. There is a new 16-bit 2's complement type, which will do sign extension when converting to epicsInt32. There are new types for 32-bit integers and 32-bit floats, with little-endian and big-endian versions of each. The data type to be used for a particular record (i.e. offset in the register block) can be defined using the drvUser strings shown below in the INP or OUT link specification of the record. When using 32-bit values the "offset" in the link will point to the smaller address. So the 32-bit value will be built from offset and offset+1.
typedef enum {
dataType2sComplement16, /* 16-bit unsigned drvUser=UINT16 */
dataTypeSigned16, /* 16-bit sign and magnitude drvUser=INT16SM */
dataTypeUnsignedBCD, /* 16-bit unsigned BCD drvUser=BCD_SIGNED */
dataTypeSignedBCD, /* 16-bit signed BCD drvUser=BCD_UNSIGNED */
dataTypeUnsigned16, /* 16-bit 2's complement drvUser=INT16 */
dataTypeInt32LE, /* 32-bit integer little-endian drvUser=INT32_LE */
dataTypeInt32BE /* 32-bit integer big-endian drvUser=INT32_BE */
dataTypeFloat32LE, /* 32-bit float little-endian drvuser=FLOAT32_LE */
dataTypeFloat32BE /* 32-bit float big-endian drvUser=FLOAT32_BE */
} modbusDataType;
Does this proposal sound reasonable?
I don't have any Modbus devices I can test with that support 32-bit integers or floating point values. Are there volunteers to test the new version before I release it? I plan to work on it in the next week or so.
Mark
-----Original Message-----
From: Andrew Johnson [mailto:[email protected]]
Sent: Monday, March 19, 2012 10:04 AM
To: Eric Norum
Cc: Mark Rivers
Subject: Re: CALC cast operators
Hi Mark,
On 2012-03-14 Eric Norum wrote:
> On Mar 14, 2012, at 3:54 PM, Mark Rivers wrote:
> > The Modbus standard does not describe IEEE floats at all, any vendor who
> > uses them is operating outside of the standard. Eric provided for 2
> > cases: low-order 16-bits first, or high-order 16-bits first. But what
> > defines the byte order within the 16-bit words, couldn't they be
> > big-endian or little-endian? That gives us 4 cases. Now how about
> > 64-bit floats?
>
> I've only seen PLCs with the two cases I've mentioned.
> Most real-world data can be represented with 24 bits of resolution so I
> suspect that 32-bit floats are good enough for now.
The byte order within the words will have already been taken care of by the
standard MODbus protocol in creating the 16-bit word. I have not seen a PLC
that supports 64-bit float values yet, so don't worry about them for now.
> >> but it's kind of annoying to have to
> >> configure a different port for each data type, especially if you already
> >> have to read the same data range for a different port/type.
> >
> > Well you should never be reading exactly the same range for a different
> > data type; either the number is an integer or a float, it's never both.
>
> Right, but a block of registers can easily contain some 16-bit integer
> values and some 32-bit float values (sent as pairs of 16-bit integers).
In Jim's case he had several simple 32-bit values where so he had to combine 2
16-bit integers into 1 32-bit integer and then divide that by 10 to get the
engineering units value, and one other type which was rather obscure and I
forget how it was actually encoded, but after you pointed out the right block
type we could use a CALC to handle that.
> > I'll think about how this could be made simpler, but I'm very reluctant
> > to write device support, I want to use standard asyn device support and
> > do it in the driver. The drvUser field could possibly be used for this:
> >
> > field(INP, @asyn(port, offset, timeout))INT16 (the default)
> > field(INP, @asyn(port, offset, timeout))BCD_SIGNED
> > field(INP, @asyn(port, offset, timeout))FLOAT32_HI
> > field(INP, @asyn(port, offset, timeout))FLOAT32_LO
>
> …..this looks like a better approach!
That's the kind of thing I was thinking about. You should probably make
omitting the drvUser field also the same as the default, and add an INT32
option.
Thanks,
- Andrew
--
Never interrupt your enemy when he is making a mistake.
-- Napoleon Bonaparte
- Replies:
- RE: Proposed support for additional Modbus data types Mark Rivers
- Navigate by Date:
- Prev:
9th NOBUGS conference announcement Tobias.Richter
- Next:
Re: 32-bit TIFFs and PIL Ross Harder
- 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
- Navigate by Thread:
- Prev:
Re: 9th NOBUGS conference announcement Hartman, Steven M.
- Next:
RE: Proposed support for additional Modbus data types Mark Rivers
- 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
|