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  <20122013  2014  2015  2016  2017  2018  2019  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  <20122013  2014  2015  2016  2017  2018  2019 
<== Date ==> <== Thread ==>

Subject: Proposed support for additional Modbus data types
From: Mark Rivers <rivers@cars.uchicago.edu>
To: "'Andrew Johnson'" <anj@aps.anl.gov>, Eric Norum <eric@norum.ca>, "tech-talk@aps.anl.gov" <tech-talk@aps.anl.gov>
Date: Fri, 23 Mar 2012 16:16:10 +0000
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:anj@aps.anl.gov] 
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  <20122013  2014  2015  2016  2017  2018  2019 
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  <20122013  2014  2015  2016  2017  2018  2019 
ANJ, 18 Nov 2013 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·