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  <20082009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  <20082009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: RE: Use of waveform records
From: "Mark Rivers" <[email protected]>
To: <[email protected]>, "tech-talk" <[email protected]>
Date: Sat, 29 Nov 2008 21:37:08 -0600
Hi,
 
I have not used the gensub record, so I can't give you the exact code, but here is the idea.
 
gensub input link A is a 2-element waveform record with FTVL=LONG (because it uses the asynInt32 interface).  When the float is read from the PLC the first 16-bit word (0xC148 in your example) will be placed in the low-order 16-bits of the first array elements, and the second 16-bit work (0x0000 in your example will be placed in the low-order 16-bits of the second array element.  You want to combine these into a single 32-bit word which you place in the VAL field of an ai record, which is output  link A.
 
Here is the pseudo-code:
 
epicsInt16 lowBits, highBits;
 
lowBits = (epicsInt16)inpA[0];
highBits = (epicsInt16)inpA[1];
 
outA = (highBits<<16) | lowBits;
 
Note that depending on the word order of your PLC relative to the host you may need to reverse the [0] and [1] subscripts in the assignments to lowBits and highBits.
 
Mark
 

________________________________

From: [email protected] on behalf of Silver
Sent: Sat 11/29/2008 7:48 PM
To: tech-talk
Subject: Re: RE: RE: Use of waveform records



hi, Mark:

  I have done this as same as your suggestions before I found this topic. also I tried to just use records to implement it. it's easy to seperate a 32 bit data to two 16 bit data in record, but I failed to combine two 16 bit data to a 32 bit float in db file. for example: the float -12.5 is stored as 0xC1480000. when it's transfered, IOC get 0xc148 and 0x0000. how to convert it back to -12.5?
or see this record:
record(calc, "calc1") {                                                                
    field(INPA, "0xc1480000")                                                          
    field(INPB, "-12.5")                                                               
    field(CALC, "A")                                                                   
    field(SCAN, "1 second")                                                            
}
caget will get the value 3.24272e+09. In fact, it's knowledge about record, a bit far from modbus driver.
thanks for your reply.

======= At 2008-11-29, 23:06:38 you wrote: =======

>You could use a 2-element waveform to read the 2 16-bit words, and then use a gensub to combine these into a 32-bit float.  You will need to worry about byte order, since that might not be the same on the PLC and the IOC host.  The Modbus specification only describes 16-bit words, anything done with floats or other data types is vendor-specific.
>
>Mark
>
>
>________________________________
>
>From: [email protected] on behalf of marco_hair
>Sent: Sat 11/29/2008 8:47 AM
>To: tech-talk
>Subject: Re:RE: Use of waveform records
>
>
>hi,Mark:
>
>I searched the tech-talk and found this topic before. My situation is on the contrary: the device need to send a 32 bit float to IOC. since modbus tcp only support 16 bit data, this 32 bit float will be seperated to two 16 bit data and sent. I can use gensub to implement it. If I want to just use record to implement it, how to do this? would you give me some suggestions? Surely I am using your latest modbus tcp device.
>Thanks a lot in advance.
>
>?2007-10-16,"Mark Rivers" <[email protected]> ??:
>
>Hi Dominique,
>
>I just put together a test database to convert a 32-bit ao record to 2 16-bit ao records.  Here is the database:
>
>record(ao, "test:ao") {
>    field(FLNK, "test:calcLSW.PROC")
>}
>
>record(calcout, "test:calcLSW") {
>    field(INPA, "test:ao.VAL  NPP NMS")
>    field(CALC, "A&65535")
>    field(OUT, "test:aoLSW")
>    field(FLNK, "test:calcMSW.PROC")
>}
>
>record(calcout, "test:calcMSW") {
>    field(INPA, "test:ao.VAL  NPP NMS")
>    field(CALC, "(A>>16)&65535")
>    field(OUT, "test:aoMSW")
>}
>
>record(ao, "test:aoLSW") {
>}
>
>record(ao, "test:aoMSW") {
>}
>
>I then tested this database with various 32-bit input values to test:ao, and looked at the 16-bit output values in test:aoLSW and test:aoMSW.
>
>Here are the results:
>
>corvette> caput -s test:ao "0x1"
>Old : test:ao                        2.41592e+09
>New : test:ao                        1
>corvette> caget test:ao test:aoLSW test:aoMSW
>test:ao                        1
>test:aoLSW                     1
>test:aoMSW                     0
>
>corvette> caput -s test:ao "0xffff"
>Old : test:ao                        1
>New : test:ao                        65535
>corvette> caget test:ao test:aoLSW test:aoMSW
>test:ao                        65535
>test:aoLSW                     65535
>test:aoMSW                     0
>
>corvette> caput -s test:ao "0x7fffffff"
>Old : test:ao                        2.68435e+08
>New : test:ao                        2.14748e+09
>corvette> caget test:ao test:aoLSW test:aoMSW
>test:ao                        2.14748e+09
>test:aoLSW                     65535
>test:aoMSW                     32767
>
>corvette> caput -s test:ao "0x8fffffff"
>Old : test:ao                        2.14748e+09
>New : test:ao                        2.41592e+09
>corvette> caget test:ao test:aoLSW test:aoMSW
>test:ao                        2.41592e+09
>test:aoLSW                     0
>test:aoMSW                     32768
>
>I conclude that the database works OK until the most-significant bit in the 32-bit test:ao record is set.  The database then fails, probably because the calc parser is converting to a 32-bit signed integer, rather than unsigned.  For numbers up to 0x7fffffff ( 2147483647 decimal) it works OK.
>
>Mark
>
>
>
>
>
>From: Touchard Dominique [mailto:[email protected]]
>Sent: Thursday, October 11, 2007 3:46 AM
>To: Mark Rivers
>Cc: [email protected]
>Subject: Re: Use of waveform records
>
>
>
>
>Mark Rivers a ?rit :
>Hi Dominique,
>
> 
>Perhaps I discovered a  modbus driver "feature"  ?
>I created one modbus number 4 read function which read 11 bytes. I tested three waveform input records.
>These three records read 3 different values on different offsets. These 3 records read the offset 0 ???!!!
>   
>
>That is the documented behavior for asynInt32Array support.  Look at
>
>http://cars9.uchicago.edu/software/epics/modbusDoc.html#EPICS%20device%20support
>
>in the section on asynInt32Array support.  You will see that the "offset" field is NA (not applicable) for all Modbus functions for asynInt32Array. 
> 
>You are totally right. Thanks. I'll take back my glasses. ;-)
>
>
> 
>About ai/ao records, I will need to write and read float values with the Modbus driver.
>I saw integer examples. Ai/ao examples work with asyn32int type.
>Did you test asynFloat64 values ?
>Do I have to use waveform records (ie 32bits : sign:1bit exponent:8bits fraction:23bits) ?
>   
>
>Float values are not a standard Modbus data type; they are not documented in the Modbus standard.  Again, because they are more than 16 bits long, they require multiple Modbus words.  I think you need to do the same thing you do for 32-bit integers, i.e. use a calc, Gensub or SNL code to convert to two 16-bit integers and then use two longout records or a waveform record.
>
> 
>I have a beginner's question : does the bit left shift work like C code?
>Can I write something like A << 16 in the calc expression?
>   
>
>Yes, that is documented under Bitwise Operators here:
>http://www.aps.anl.gov/epics/EpicsDocumentation/AppDevManuals/RecordRef/Recordref-13.html#HEADING13-0
>
> 
>I tried to convert the 32 bit integer value into 2 16 bits values with a calc record.
>Because of float conversion troubles, I don't  get through to get the right values.
>   
>It seems to me like it should work, since I think any 32-bit integer can be represented exactly in a 64-bit double.  Can you send an example that did not seem to work?
> 
>I broke the EPICS database to make a SNL code. I haven't got any example. I tried to use the 0x0000FFFF bit mask. I thought this value was converted  in a float value and the bitwise operation didn't give the right result when it was converted back to an integer.  The 0x0001000 bit mask worked. Perhaps I made a mistake.
>
>I will tried again with two shifts (one 16 bits left shift to lose MS bits and and one right to give back the right bit position).
>
>Thanks again for your help.
>Dominique.
>
>
>Mark
>
>
>
>________________________________
>
>From: Touchard Dominique [mailto:[email protected]]
>Sent: Tue 10/9/2007 3:50 AM
>To: Mark Rivers
>Cc: [email protected]
>Subject: Re: Use of waveform records
>
>
>Hi Mark,
>
>Thanks for your answer. I agree with you. We mustn't modify the driver.
>
>The power supply could work with two longout records. In the future, I will need to know how to work with a waveform, an SNL or Gensub code. So I decided to try these tools. I have written an SNL code which does this conversion. I know this is not the best solution. I will try a gensub record soon.
>I tried to convert the 32 bit integer value into 2 16 bits values with a calc record. Because of float conversion troubles, I don't  get through to get the right values. I have a beginner's question : does the bit left shift work like C code? Can I write something like A << 16 in the calc expression?
>
>Perhaps I discovered a  modbus driver "feature"  ? I created one modbus number 4 read function which read 11 bytes. I tested three waveform input records. These three records read 3 different values on different offsets. These 3 records read the offset 0 ???!!!
>
>So I decided to create only one input waveform which read the whole bytes. It works fine. At present, the SNL code converts the values.
>
>About ai/ao records, I will need to write and read float values with the Modbus driver. I saw integer examples. Ai/ao examples work with asyn32int type. Did you test asynFloat64 values ? Do I have to use waveform records (ie 32bits : sign:1bit exponent:8bits fraction:23bits) ?
>
>Thanks for your help.
>
>Dominique.
>
>
>Mark Rivers a ?rit :
>
>One thought on this.
>
>Because you must do 2 Modbus operations to write a 32-bit value with
>Modbus, I suspect that the power supply only updates the value when you
>write one of the 16-bit words, i.e. either the most-significant or
>least-significant 16 bits.  You should read the documentation to find
>out which one actually updates the power supply and make your database
>write that value last.  Otherwise you will get a momentary garbage
>output if you do it in the wrong order.
>
>Mark
>
>
> 
>
>-----Original Message-----
>From: [email protected]
>[mailto:[email protected]] On Behalf Of Mark Rivers
>Sent: Friday, October 05, 2007 11:23 AM
>To: Touchard Dominique; [email protected]
>Subject: RE: Use of waveform records
>
>Hi Dominique,
>
>Sorry for the delay in replying to this, I was on vacation.
>
>I think an easier solution to this problem is to use 2 calc records to
>convert the 32-bit integer to 2 16-bit integers, and write
>those to the
>Modbus driver using function 6.  Then you don't have to write any C
>code, just a simple database.
>
>PowerSupply (longout) -> calc1 (16 LSB) -> longout1 -> Modbus
>                      -> calc2 (16 MSB) -> longout2 -> Modbus
>
>I don't recommend modifying the driver, because a 32-bit
>integer is not
>a standard Modbus data type, and we could end up with all sorts of
>modifications for non-standard data types.
>
>Mark
>
>
>   
>
>-----Original Message-----
>From: [email protected]
>[mailto:[email protected]] On Behalf Of
>     
>
>Touchard Dominique
>   
>
>Sent: Wednesday, September 19, 2007 8:44 AM
>To: [email protected]
>Subject: Use of waveform records
>
>Hi,
>
>we are working on/with the Epics modbus tcp driver written by Mark
>Rivers. We need to write a 32 bits integer value in a power supply
>command control interface.  First we thought to write an asyn32Int
>record with the number 6 modbus function.  Immediatly, we
>     
>
>saw that the
>   
>
>driver uses the number 6 modbus function which works only on
>a 16 bits word.
>
>After reading the Modbus Driver Support documentation, we
>     
>
>saw that we
>   
>
>have to use a two value length waveform record.
>
>First question : is this correct ?
>
>Second question : do we have to use the gensub record to manipulate
>values inside a waveform record ? In this case, is there any example
>that shows how to do this ? Could somebody send us an example
>on this ?
>
>Third question : Is a bad idea to modify the modbus driver
>     
>
>in the goal
>   
>
>to write a asyn32Int 32 bits integer record with the 
>     
>
>number 16 modbus
>   
>
>function ?
>
>Thanks for your help .
>
>Dominique Touchard.
>
>
>     
>
>   
>
> 
>
>
> 
>
>
>________________________________
>
>?????,??????????? <http://www.yeah.net/> 

= = = = = = = = = = = = = = = = = = = =
                       

Best regards                            
Geyang 2008-11-30






References:
Re:RE: Use of waveform records marco_hair
RE: RE: Use of waveform records Mark Rivers
Re: RE: RE: Use of waveform records Silver

Navigate by Date:
Prev: Re: RE: RE: Use of waveform records Silver
Next: RE: RE: RE: Use of waveform records Mark Rivers
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  <20082009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: Re: RE: RE: Use of waveform records Silver
Next: RE: RE: RE: Use of waveform records Mark Rivers
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  <20082009  2010  2011  2012  2013  2014  2015  2016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 02 Sep 2010 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·