Little endian to Float from Modbus RTU

2023-12-15
2024-01-08
  • solidlogicguy - 2023-12-15

    Hello, I got a device from which I require to read values from I am using a WAGO PLC 750-8212 and I am communicating through Modbus Master FUNCTION BLOCK from library WagoAppPLCModbus in Codesys 3.5 to this device. I already receive data from the device that is a CVM to monitor voltage from a fuel cell. The technical support of the company that makes these devices says that the data is sent in little endian form. And I want to convert it to a float value. The tech support sent me the next instructions of how to do it but I am new using codesys, so any advice or help I will really appreciate so much.

    Message from tech support:
    The process is complicated, better to do it with already implemented library in the language/program you use.

    Basically the process should be next:

    To convert the two Modbus registers containing parts of a 32-bit float in little-endian byte order to a floating-point number using mathematical operations, you first need to combine the two 16-bit integers (assuming reg1 is the lower word and reg2 is the higher word) and then interpret the result according to the IEEE 754 standard.

    Given:
    - Register 192 (reg1) = 4096
    - Register 193 (reg2) = 14884

    Step 1: Combine the two registers. Since we are dealing with little-endian byte order, reg2 is the high word, and reg1 is the low word:

    combined = reg2 * 2^16 + reg1
    combined = 14884 * 65536 + 4096
    combined = 975175680 + 4096
    combined = 975179776
    

    Step 2: Convert the combined value to binary:

    combined_binary = '1110101101011100000000000000000'
    

    Step 3: Split the binary into IEEE 754 components:

    • Sign bit (1 bit): 0
    • Exponent (8 bits): 11101011
    • Mantissa (23 bits): 01011100000000000000000

    Step 4: Convert the binary exponent to decimal and subtract the bias (127 for 32-bit floats):

    exponent = int('11101011', 2) - 127
    exponent = 235 - 127
    exponent = 108
    

    Step 5: Calculate the mantissa as a fraction:

    The mantissa in IEEE 754 format is the fractional part after the leading 1 (which is implicit). Therefore, we need to convert the binary mantissa to decimal and add the implicit leading 1:

    mantissa_fractional = 1 + int('01011100000000000000000', 2) / 2^23
    mantissa_fractional = 1 + 18688 / 8388608
    mantissa_fractional = 1 + 0.002227783203125
    mantissa_fractional β‰ˆ 1.002227783203125
    

    Step 6: Combine the sign, exponent, and mantissa to get the float value:

    float_value = (-1)^0 * mantissa_fractional * 2^exponent
    float_value = 1 * 1.002227783203125 * 2^108
    

    Because the exponent is quite large, the resulting float value is a very large number.

     
  • marekxc - 2023-12-28

    Maybe try going back to step one and:

    Var
        Reg1: WORD;
        Reg2: WORD;
        Reg12: DWORD;
        Value: REAL;
    end_var
    
    // program
    Reg1:= 4096;
    Reg2:= 14884;
    Reg12:= (reg2 * 65536) + reg1;
    Value:= DWORD_TO_REAL(Reg12);
    
     
    • solidlogicguy - 2024-01-08

      Just tried and returns the same value but in scientific notation.

       

Log in to post a comment.