Esoteric Tech
Esoteric Tech

Reputation: 31

Serial Port data

I am attempting to read the data from an Absolute Encoder with a USB interface using pyserial on the Raspberry. The datasheet for the encoder is below. The USB interface data is on page 22-23

https://www.rls.si/eng/fileuploader/download/download/?d=0&file=custom%2Fupload%2FData-sheet-AksIM-offaxis-rotary-absolute-encoder.pdf

I have successfully connected to the Encoder and I am able to send commands using

port = serial.Serial("/dev/serial/by-id/usb-RLS_Merilna_tehnkis_AksIM_encoder_3454353-if00")

port.write(b"x")

where x is any of the available Commands listed for the USB interface.

For example port.write(b"1") is meant to initiate a single position request. I am able to print the output from encoder with

x = port.read()

print(x)

The problem is converting the output into actual positiong data. port.write(b"1") outputs the following data:

b'\xea\xd0\x05\x00\x00\x00\xef'

I know that the first and last bytes are just the header and footer. Bytes 5 and 6 are the encoder status. Bytes 2-4 is the actual position data. The customer support has informed me that I need to take bytes 2 to 4, shift them into a 32 bit unsigned integer (into lower 3 bytes), convert to a floating point number, divide by 0xFF FF FF, multiply by 360. Result are degrees.

I'm not exactly sure how to do this. Can someone please let me know the python prgramming/functions I need to write in order to do this. Thank you.

Upvotes: 2

Views: 732

Answers (2)

quamrana
quamrana

Reputation: 39354

This is the way to extract the bytes and shift them into an integer and scale as a float:

x = b'\xea\xd0\x05\x00\x00\x00\xef'

print(x)

int_value = 0   # initialise shift register
for index in range(1,4):
    int_value *= 256          # shift up by 8 bits
    int_value += x[index]     # or in the next byte
print(int_value)

# scale the integer against the max value
float_value = 360 * float(int_value) / 0xffffff
print(float_value)

Output:

b'\xea\xd0\x05\x00\x00\x00\xef'
13632768
292.5274832563092

Upvotes: 0

Elis Byberi
Elis Byberi

Reputation: 1452

You have to use builtin from_bytes() method:

x = b'\xea\xd0\x05\x00\x00\x00\xef'

number = 360 * float(
    int.from_bytes(x[1:4], 'big')  # get integer from bytes
) / 0xffffff

print(number)

will print:

292.5274832563092

Upvotes: 1

Related Questions