1

Heyho,

i got a little question. So I got a measurement device and i retrieve the data via modbus. I usually check the values via "Simply Modbus TCP Client" which displays me the correct data. Now I want to automate this process which takes me into trouble.

I get the correct response but the tricky part seems to be the conversion. I get the same response in hex but when I convert it, I won't get the same result.

Take a look at the Screenshot Simply Modbus Client - Screenshot

There you can see the response on the left, the bytes (4175 AF8A) on the right and the corresponding value (22739113). I expect "bytes" to be a hex representation but I can't convert them into a decimal number.

I wrote a small java-program to display these numbers and their conversions.

public static void main(String[] args) {

    HashMap<String, Integer> values = new HashMap<>();
    values.put("4175AF52", 22738214);
    values.put("41D61FAC", 1484698204);
    values.put("419A08A0", 109193237);

    Iterator it = values.entrySet().iterator();
    while (it.hasNext()) {
        System.out.println("/************************************************/");
        Map.Entry pair = (Map.Entry) it.next();
        int hexIntepretation = (int) Long.parseLong((String) pair.getKey(), 16);

        // Print the result
        System.out.println(pair.getKey() + " = " + pair.getValue());
        System.out.println("Expected:\t" + pair.getValue());
        System.out.println("Hex to Int:\t" + hexIntepretation);
        System.out.println("Int to Hex:\t" + Integer.toHexString((int) pair.getValue()));
        System.out.println("Float to Hex:\t" + Float.toHexString((int) pair.getValue()));
        System.out.println("Hex to Int:\t" + Integer.parseInt((String) pair.getKey(), 16));

        it.remove(); // avoids a ConcurrentModificationException
    }
}

Running this snippet gives this output:

/*******************************************/
419A08A0 = 109193237
Expected:       109193237
Hex to Int:     1100613792
Int to Hex:     6822815
Float to Hex:   0x1.a08a06p26
Hex to Int:     1100613792
/*******************************************/
41D61FAC = 1484698204
Expected:       1484698204
Hex to Int:     1104551852
Int to Hex:     587eb25c
Float to Hex:   0x1.61facap30
Hex to Int:     1104551852
/*******************************************/
4175AF52 = 22738214
Expected:       22738214
Hex to Int:     1098231634
Int to Hex:     15af526
Float to Hex:   0x1.5af526p24
Hex to Int:     1098231634

No matter what I do, I can't get the values. BUT when I do "float-to-hex", I will find some of the initial values in there.

Example:

4175AF52 = 22738214

Float to Hex: 0x1.5af526p24

Yet I can't put the pieces together to solve this puzzle. Any help is appreciated!

Danny Fonk
  • 58
  • 1
  • 8

3 Answers3

2

As your image says "64 bit float", I would interpret the bytes as double.

https://en.wikipedia.org/wiki/Double-precision_floating-point_format

J Fabian Meier
  • 33,516
  • 10
  • 64
  • 142
  • Ah. Forgot to mention that. Tried that and also made no change. It will be the same value as the int-value. Edit: Not the same value but still not the correct answer. I took the snippet from http://stackoverflow.com/a/6416296/2295729 `long longBits = Long.valueOf("4175AF52",16); double doubleValue = Double.longBitsToDouble(longBits); System.out.println(doubleValue);` Gives me this output: 5.425985215E-315 – Danny Fonk Jul 05 '16 at 08:26
  • @DannyFonk Of course it did not. You are looking at not enough bytes ... – Fildor Jul 05 '16 at 08:28
  • It should be some kind of double. If you convert a double to hex and compare it to your input, you may find similarities (there may be also issues with bigEndian or the order of the bytes). Maybe you could save the expected number as double, convert it to hex and show the result here. – J Fabian Meier Jul 05 '16 at 08:28
  • Take a look at my edit. How to I look into enough bytes then? @Fildor – Danny Fonk Jul 05 '16 at 08:30
  • Why do you convert to long? This breaks the conversion. You have to convert the 8 bytes directly to double. – J Fabian Meier Jul 05 '16 at 08:31
  • `Double 22738214` in byte array `{ 00 00 00 60 52 AF 75 41 }` => You are missing some bytes. – Nam Tran Jul 05 '16 at 08:32
  • 1
    @DannyFonk I don't know. I cannot see where the register starts from that gui. The "bytes" column should be wider. – Fildor Jul 05 '16 at 08:32
  • @DannyFonk Try 0x176903144175AF8A ... That would be 4 bytes more in front of the red box. – Fildor Jul 05 '16 at 08:34
  • Holy guacamole! @Fildor - you're totally right! The GUI hid that from me. I can't get it to show up or make the column any wider but when I go into that and copy ALL that is in there I got 4175 AF8A 89ED F046 instead of 4175 AF8A - I will try and check if this worked out. – Danny Fonk Jul 05 '16 at 08:37
2

It says "64 bit float" but the GUI is only showing you 32 bits. Obviously the view cuts the other 4 bytes off but in the field on the left, you can see them.

As you already mentioned, when you copy all the content from the "bytes" column, you'll also get the "missing" ones.

Fildor
  • 14,510
  • 4
  • 35
  • 67
0

Unfortunately the display does not seem to show the floating point value:

    int bits = 0x4175_AF8A;
    float f = Float.intBitsToFloat(bits);
    System.out.println(f);

Gives:

15.355356

Thanks to @Fildor, the correct calculation:

    long nbits = 0x1769_0314_4175_AF8AL;
    nbits = 0x4175_AF8A_19ED_F046L;
    double d = Double.longBitsToDouble(nbits);
    System.out.println(d); // 2.273910562059047E7
Joop Eggen
  • 107,315
  • 7
  • 83
  • 138