Search code examples
pythonjupyter-notebookhexdecode

Can't decode values of thermometer, because 2 bytes become 1


I want to acquire data from a thermometer, which should give me the data in hex, but isn't always hex (somehow). ascii doesn't work, because the values are greater than 128. This is the sheet of the thermometer: https://asset.conrad.com/media10/add/160267/c1/-/en/000100518DS01/datenblatt-100518-voltcraft-k204-temperatur-messgeraet-200-1370-c-fuehler-typ-k-datenlogger-funktion.pdf

I want to decode the bytes, but because it isn't really hex and switches to something "weird" in between, I am not sure what to use

My code:

import serial

ser = serial.Serial('COM1',
                baudrate=9600,
                parity='N',
                bytesize=8,
                stopbits=1,
                rtscts=True,
                dsrdtr=True,
                timeout=1) # open serial port


ser.write(b'A') # send command 'A' to be able to receive data from VOLTCRAFT K204, see sheet
bytes=ser.readline() # read all 45 bytes
print(bytes)
selected_bytes=s[7:9]# slice to get the 8th and 9th value, see sheet
print(selected_bytes)
value= selected_bytes.decode('ascii') #doesn't work, because the value is out of range
print(value)
ser.close() 

Output for 23.2°C, which is also shown on the thermometer: b'\x02\x80\x80\x01\x02\x02\x02\x00\xe8\x7f\xff\x7f\xff\x7f\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x0e\x03'

b'\x00\xe8'

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 1: ordinal not in range(128)

Output for ~30.5°C, which is also shown on the thermometer: b'\x02\x80\x80\x01\x02\x02\x02\x012\x7f\xff\x7f\xff\x7f\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0e\x00\x00\x00\x0e\x03'

b'\x012'

"unknown character"2

=> Not only did those 2 bytes become 1, but what exactly is b'\x012' and what can I use to decode both types of bytes?

If I only take one byte (because the other is 0) and let 'utf-8' decode it, I get values that are expected until I increase the temperature again and those 2 bytes become 1 again. Basically as soon as the thermometer uses the second byte I can't decode it


Solution

  • You are receiving raw binary data. b'\x00\xe8' is merely the text representation of that binary value.

    The binary value in bytes can be converted to an integer using the int.from_bytes method:

    raw  = b'\x00\xe8'
    temp = int.from_bytes(raw,'big') / 10  # 23.9
    

    Since those are temperatures, unless they are in Kelvin, I would expect that they can be negatives so you may want to use the signed option:

    raw  = b'\xff\xef'
    temp = int.from_bytes(raw,'big', signed=True) / 10  # -27.3