How to convert a floaring value to two integers in DeltaV?

This is to write a command to a floboss computer, because the floboss reads in another way than deltaV, (Most and least words)

  • If you are using a serial card or VIM to write these values, I believe there is an option in some of these drivers from Mynah to convert from little Endian to Big Endian, or vice versa, and maybe that is all you need, and you can avoid thie mess below.  If so, I think you create a FP data set, and write the floating point number to the data set Register.  The driver takes care of sorting the two registers in the right Order.  As I recall there are options to change the order of the intgers and the order of the bits.  Hopefully this will work for you with no custom code in the control module.

    This sends me back a few years.  I'll preface this with "you need to test this out".

    First, you need to understand the structure of the 32 bit float number and how DeltaV uses internal parameters in calc blocks.  

    A float number is made up of several parts:  Sign of the number, signed logarithm portion and the mantissa.  DeltaV Float uses a 23 bit Mantissa (I think), an 8 bit signed logarithm and a sign bit for a total of 32 bits .  In reality, you need to use the Mantissa size in the Flow Bos.  you'll need to do some tests.   so if you break this up into two integers, one will have the 16 least significant bits of the mantissa, the other will have the sign bits, logarithm and remaining 7 bits of the mantissa.

    you cannot simply write the floating point number into a 32 bit integer as DeltaV will attempt to convert the float (say 1,341,560.0 to and integer 1342560, and these two numbers do not have the same bit pattern at all.

    floats are represented by the logarithm portion plus the mantissa portion.  As a number gets bigger, the sizeof the smallest possible increment changes.  For instance, a number between 1 and 2 can increment by (X/1)*mantissa.  Mantissa is 2^23= 8388608.  If the number is say 1000, the logarithm will be 9, (2^9= 512).  the logarithm therefore repressents 512 and the mantissa represents the balance of 488 for a total of 1000.  The value of the mantissa is the ratio of 488/512 * 2^23=11110100000000000000000.

    So the float bit pattern for 1000.0 is

    0   00001001    11110100000000000000000

     |            |                                  |

     |            |                                  - Mantissa - represents 488 in this example

     |            - Signed Logarithm - represents 512 in this example

     -   Sign of number  - is positive in this example.

    I think that a sign bit of 1 is negative.

    So to convert you need to evaluate the number and set the bits accordingly, and then combine them into the two 16 bit integers to send to the flow bos in the right order.

    Create three parameters:  Boolean for overall Sign, signed 8 bit integer for Log, and 32 bit integer for mantissa (this will store a 22 bit integer cleanly)

    In CALC block:

    set sign bit.(is number positive or negative)

    Determine log value. (2 ^ X) such that log is less than number and 2^ (X+1) is greater than number.  

       This also has to work from numbers smaller than 1.  The log number range from -127 to 128, with

       negative log used for numbers between -1 < y< 1.

    Once log is determined, use it to calculate mantissa.  (Number/Log)*Mantissa stored in 32 bit integer.  

    Now you can combine these numbers into the 2 integers.

    most significant:  start with sign, shift 9 spaces, bitwise OR with log, shift four more and and with 6 bits of mantissa.  Read the mantissa and shift right 16 spaces and OR with log and sign.  You need to be careful because all CALC block internal parameters are 32 bit floats.  I'd do this in one assignment statement, but if you store nothing greater than 22 bits, the float will return those same 23 bits in the float parameter.  

    INT_MSB := (SHR ((SHR ('^/SIGNBIT, 9) || ('^/LOG.CV'),7)) || SHL('^/MANTISSA.CV',16)

    INT_LSB= ('^/MANTISSA.CV) & 8388608)

    Now you can send the two integers in the required order.

    I am not 100% sure of the Mantissa size, but I think it needs to match the destination.  Since I'm starting with a float, I can do this conversion and get two integers that will convert back to the float.  IF I use the wrong Mantissa size (larger Log word), my result will lose on its resolution, but the float value will be accurate.   So make sure you use the correct Mantissa size for the Flow bos 32 bit float.  As long as your are using the same log/mantissa size when going back to Float, you'll be the right result.

    Disclaimer.  I did not prove this out.  There may be a better approach, but this is what I recall dowing 10 years ago to solve this problem.  

    Andre Dicaire

  • In reply to Andre Dicaire:

    This is a great answer, especially from memory! :-) I will only add that If you take the route of doing this all, you also need to watch out for a couple "special" numbers that floating point uses:

    [ S ] = Sign Bit
    [ X ] = Exponent
    [ M ] = Mantissa

    S X X X X X X X X M M M M M M M M M M M M M M M M M M M M M M M
    NaN (Not a Number) 1 1 1 1 1 1 1 1 1 Any of these bits are HIGH
    Infinity 0 1 1 1 1 1 1 1 1 All Mantissa bits are LOW
    Negative Infinity 1 1 1 1 1 1 1 1 1 All Mantissa bits are LOW



     To get even more information you can look up "Floating Point" or more specifically "IEEE 754" and there are a bunch of sites that can help out. Good luck!