This will not work:
record(calc, "calc1") {
field(INPA, "0xc1480000")
field(INPB, "-12.5")
field(CALC, "A")
field(SCAN, "1 second")
}
Because the constant in INPA constant 0xc148000 will be interpreted as an integer, not a bit pattern for a double, and 0xc148000 is the integer 3242721280.
>From Python:
>>> 0xc1480000
3242721280L
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: Use of waveform records Mark Rivers
- Next:
Re: Use of waveform records haquin
- 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: Use of waveform records Mark Rivers
- Next:
Re: Use of waveform records haquin
- 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
|