3

I don't have much experience working with these low level bytes and numbers, so I've come here for help. I'm connecting to a bluetooth thermometer in my Flutter app, and I get an array of numbers formatted like this according to their documentation. enter image description here I'm attempting to convert these numbers to a plain temperature double, but can't figure out how. This is the "example" the company gives me. enter image description here However when I get a reading of 98.5 on the thermometer I get a response as an array of [113, 14, 0, 254]

Thanks for any help!

phuclv
  • 37,963
  • 15
  • 156
  • 475
Conner
  • 1,771
  • 11
  • 24

2 Answers2

10

IEEE-11073 is a commonly used format in medical devices. The table you quoted has everything in it for you to decode the numbers, though might be hard to decipher at first.

Let's take the first example you have: 0xFF00016C. This is a 32-bit number and the first byte is the exponent, and the last three bytes are the mantissa. Both are encoded in 2s complement representation:

  • Exponent, 0xFF, in 2's complement this is the number -1
  • Mantissa, 0x00016C, in 2's complement this is the number 364

(If you're not quite sure how numbers are encoded in 2's complement, please ask that as a separate question.)

The next thing we do is to make sure it's not a "special" value, as dictated in your table. Since the exponent you have is not 0 (it is -1), we know that you're OK. So, no special processing is needed.

Since the value is not special, its numeric value is simply: mantissa * 10^exponent. So, we have: 364*10^-1 = 36.4, as your example shows.

Your second example is similar. The exponent is 0xFE, and that's the number -2 in 2's complement. The mantissa is 0x000D97, which is 3479 in decimal. Again, the exponent isn't 0, so no special processing is needed. So you have: 3479*10^-2 = 34.79.

You say for the 98.5 value, you get the byte-array [113, 14, 0, 254]. Let's see if we can make sense of that. Your byte array, written in hex is: [0x71, 0x0E, 0x00, 0xFE]. I'm guessing you receive these bytes in the "reverse" order, so as a 32-bit hexadecimal this is actually 0xFE000E71.

We proceed similarly: Exponent is again -2, since 0xFE is how you write -2 in 2's complement using 8-bits. (See above.) Mantissa is 0xE71 which equals 3697. So, the number is 3697*10^-2 = 36.97.

You are claiming that this is actually 98.5. My best guess is that you are reading it in Fahrenheit, and your device is reporting in Celcius. If you do the math, you'll find that 36.97C = 98.55F, which is close enough. I'm not sure how you got the 98.5 number, but with devices like this, this outcome seems to be within the precision you can about expect.

Hope this helps!

alias
  • 28,120
  • 2
  • 23
  • 40
  • Yes, thank you! I got the 98.5 number because that was the number that the device was physically showing me after I switched it over to farenheit... but I guess that didn't switch the number it broadcasted – Conner Mar 25 '20 at 15:30
  • 1
    That is pretty typical, and for good reason! Otherwise the device would also have to send you the unit, and that'd just complicate things. Of course, you should double check with the manufacturer that this is indeed the case. – alias Mar 25 '20 at 17:44
1

Here is something that I used to convert sfloat16 to double in dart for our flutter app.

double sfloat2double(ieee11073) {
    var reservedValues = {
            0x07FE: 'PositiveInfinity',
            0x07FF: 'NaN',
            0x0800: 'NaN',
            0x0801: 'NaN',
            0x0802: 'NegativeInfinity'
        };
    var mantissa = ieee11073 & 0x0FFF;

    
    if (reservedValues.containsKey(mantissa)){
      return 0.0; // basically error
    }
  
    if ((ieee11073 & 0x0800) != 0){
       mantissa =  -((ieee11073 & 0x0FFF) + 1 );
    }else{
      mantissa = (ieee11073 & 0x0FFF);  
    }
    
    var exponent = ieee11073 >> 12;
    if (((ieee11073 >> 12) & 0x8) != 0){
      exponent = -((~(ieee11073 >> 12) & 0x0F) + 1 );
    }else{
      exponent = ((ieee11073 >> 12) & 0x0F); 
    }
    var magnitude = pow(10, exponent);
    return (mantissa * magnitude);  
}
Kiran Ruth R
  • 902
  • 1
  • 11
  • 28
  • this will decode a 16-bit SFLOAT value, but the question is asking about 32-bit FLOAT values – lukas Mar 04 '23 at 09:39