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: Re: Proposed support for additional Modbus data types
From: haquin <haquin@ganil.fr>
To: <tech-talk@aps.anl.gov>
Date: Wed, 28 Mar 2012 10:09:48 +0200
Hi Mark,

I Use Hazemeyer and soon Brucker current supply, wich are of course Modbus/TCP server.
I am interested in testing your new driver, you talked only about read 32-bit float or integer, what about writting ?

for example, in my current supply, Current consign is written as float too

Best Regards

Le 27/03/2012 21:53, Mark Rivers a écrit :
Folks,



I have added support for 7 new data types to the Modbus module.



This is from the new documentation:



********************************************************************

Modbus register data types

Modbus function codes 3, 4, 6, and 16 are used to access 16-bit registers. The Modbus specification does not define how the data in these registers is to be interpreted, for example as signed or unsigned numbers, binary coded decimal (BCD) values, etc. In fact many manufacturers combine multiple 16-bit registers to encode 32-bit integers, 32-bit or 64-bit floats, etc. The following table lists the data types supported by modbus. The default data type for the port is defined with the modbusDataType parameter described above. The data type for particular record can override the default by specifying a different data type with the drvUser field in the link. The driver uses this information to convert the number between EPICS device support and Modbus. Data is transferred to and from EPICS device support as epicsUInt32, epicsInt32, and epicsFloat64 numbers. Note that the data type conversions described in this table only apply for records using the asynInt32 or asynFloat64 inter!
  faces, they do not apply when using the asynUInt32Digital interface. The asynUInt32Digital interface always treats the registers as unsigned 16-bit integers.



Supported Modbus data types
modbusDataType value    drvUser field   Description
0       UINT16  Unsigned 16-bit binary integers
1       INT16SM 16-bit binary integers, sign and magnitude format. In this format bit 15 is the sign bit, and bits 0-14 are the absolute value of the magnitude of the number. This is one of the formats used, for example, by Koyo PLCs for numbers such as ADC conversions.
2       BCD_UNSIGNED    Binary coded decimal (BCD), unsigned. This data type is for a 16-bit number consisting of 4 4-bit nibbles, each of which encodes a decimal number from 0-9. A BCD number can thus store numbers from 0 to 9999. Many PLCs store some numbers in BCD format.
3       BCD_SIGNED      4-digit binary coded decimal (BCD), signed. This data type is for a 16-bit number consisting of 3 4-bit nibbles, and one 3-bit nibble. Bit 15 is a sign bit. Signed BCD numbers can hold values from -7999 to +7999. This is one of the formats used by Koyo PLCs for numbers such as ADC conversions.
4       INT16   16-bit signed (2's complement) integers. This data type extends the sign bit when converting to epicsInt32.
5       INT32_LE        32-bit integers, little endian (least significant word at Modbus address N, most significant word at Modbus address N+1)
6       INT32_BE        32-bit integers, big endian (most significant word at Modbus address N, least significant word at Modbus address N+1)
7       FLOAT32_LE      32-bit floating point, little endian (least significant word at Modbus address N, most significant word at Modbus address N+1)
8       FLOAT32_BE      32-bit floating point, big endian (most significant word at Modbus address N, least significant word at Modbus address N+1)
9       FLOAT64_LE      64-bit floating point, little endian (least significant word at Modbus address N, most significant word at Modbus address N+1)
10      FLOAT64_BE      64-bit floating point, big endian (most significant word at Modbus address N, least significant word at Modbus address N+1)



Note that if it is desired to transmit BCD numbers untranslated to EPICS over the asynInt32 interface, then data type 0 should be used, because no translation is done in this case.



The following is an example ai record using 32-bit floating point values:


# ai record template for register inputs
record(ai, "$(P)$(R)") {
     field(DTYP,"asynFloat64")
     field(INP,"@asyn($(PORT) $(OFFSET))FLOAT32_LE")
     field(HOPR,"$(HOPR)")
     field(LOPR,"$(LOPR)")
     field(PREC,"$(PREC)")
     field(SCAN,"$(SCAN)")
}




********************************************************************



The release notes are here:

http://cars9.uchicago.edu/software/epics/modbusReleaseNotes.html



The new documentation is here:

http://cars9.uchicago.edu/software/epics/modbusDoc.html





I have tested this with a nice inexpensive ($99) Modbus Slave simulator:

http://www.modbustools.com/modbus_slave.asp



But I hope that others can test it with real devices before I officially release R2-4.



It can be downloaded from the Subversion repository here:



https://subversion.xor.aps.anl.gov/synApps/modbus/trunk/



Or from this tar file:



http://cars.uchicago.edu/software/pub/modbusR2-4beta1.tgz





Cheers,

Mark





-----Original Message-----
From: Mark Rivers
Sent: Friday, March 23, 2012 11:16 AM
To: 'Andrew Johnson'; Eric Norum; tech-talk@aps.anl.gov
Subject: Proposed support for additional Modbus data types



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

begin:vcard
fn:Christophe Haquin
n:Haquin;Christophe
email;internet:haquin@ganil.fr
tel;work:02 31 45 46 61
x-mozilla-html:FALSE
version:2.1
end:vcard


Replies:
RE: Proposed support for additional Modbus data types Mark Rivers
Re: Proposed support for additional Modbus data types Eric Norum
References:
Proposed support for additional Modbus data types Mark Rivers
RE: Proposed support for additional Modbus data types Mark Rivers

Navigate by Date:
Prev: Re: Build problem with db dependencies Bruce Hill
Next: Extract a column of data from 2D Waveform Record Peter Milne
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: Proposed support for additional Modbus data types Eric Norum
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 ·