0

I am sending one byte ("\x2b") to a device and will be receiving 1 echo byte plus 3 bytes of data("\x2b\x??\x??\x??").I am using .replace("2b","",4) to get rid of the echo byte.I need to change the 3 bytes of hex received to int(16) and name them 3 different variables that I can call separately one at a time in a calculation. Here is what I have so far.

    import serial
    import os

    ser = serial.Serial(port="COM17", baudrate=9600)
    ser.open()
    ser.write("\x2b")
    print int(ser.readline(4).encode("hex").replace("2b", "", 4), 16)
    ser.close()

    os.system("pause")
6
  • 1
    It's a bit hard to get your English. Please point what should be the output of this piece of code - what should be written to the port and what should be printed. Commented Jan 2, 2017 at 20:22
  • I am sending ("0x2b") the device i am sending it to will echo the ("0x2b")+ it will send 3 bytes that will be different every time. I need to change them 3 bytes to int(16) numbers and enumerate them some how so I can call these 3 numbers separately to do a calculation on them. Commented Jan 2, 2017 at 20:32
  • So you get 4 bytes from the port- your original write, an 3 additional bytes. You want to split these 3 bytes in to 3 different variables? Commented Jan 2, 2017 at 20:34
  • Yes that is exactly what I need Commented Jan 2, 2017 at 20:48
  • str and bytes are sequences. Just unpack as a, b, c, d = 'abcd' Commented Jan 2, 2017 at 20:49

2 Answers 2

1

Use the struct module to retrieve arbitrary binary data from Byte strings:

import serial
import os
import struct

ser = serial.Serial(port="COM17", baudrate=9600)
ser.open()
ser.write("\x2b")
response = ser.readline(4)
echo, a, b, c = struct.unpack("4B", response)
print ("Response numbers: {:02x}, {:02x}, {:02x}".format(a, b, c))
ser.close()

On a side note: avoid using os.system("pause") as part of the program. That is a terrible habit of some so that the Windows DOS prompt stays open when the program is done running, but it is (1) WIndows only, for a program that otherwise would work on Mac OS X and Linux, and (2) involves creating an entire other process for an ordinary operation.

You can add a simple input call in Python, asking the user to press <enter> instead:

(last line):

 input("Press <enter> to close terminal")
Sign up to request clarification or add additional context in comments.

3 Comments

Worked great , Exactly what I was looking for.
why we need struct.unpack here for just bytes? why not a, b = b'ab'?
Yes, that would work - but truct.unpack will work forsomeone who has different sized integers as well. But more important - the OP is using Python2, where bytes are synonim to the "byte-string" used by default for text - the items of bytes in Python 2 are len-1 byte-strings, not numbers. (see the print statement instead of print-function to get it is Python2)
0

There is no "natural" conversion to convert a stream of 3 bytes into 3(?) int16 (aka short) numbers.

So you have to be more specific:

  • do you want to convert the bytes to int8 instead? it is of course entirely valid to regard the resulting numbers as int16 (as they will fit in)
  • do you want signed/unsigned output?
  • if you indeed have multibyte numbers (e.g. int16), are you using BIG_ENDIAN or LITTLE_ENDIAN?

in any case, the struct package can do the conversion for you:

import struct

# read 4 bytes, discard the first one, so we get a list of 3 bytes
inputdata = ser.readline(4)[1:]

# the following parses 'inputdata' as 3 `uint8` numbers
a,b,c = struct.unpack('BBB', inputdata)

3 Comments

I guess OP want hex, int(n, 16)
It is (uint 16), BIG_ENDIAN
From your question, I understand you want 3 one byte numbers you want to present in Hex. You are confounding the data soize of 2 byte (16bit) with the desried numeric base (16) .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.