I am reading data from an AHRS / IMU sensor via USB with Python 2.7. To obtain the acceleration the manufacturer specifies according to the image below:
supplier's description IMU
My code in python is this, but when the acceleration is negative the values are wrong. I believe I need to check the first bit of the MSB (In this case, the AxH field), if 1 is negative, if 0 is positive.
#....
#data = serial.read(size=11)
#....
#
#Acceleration
elif data[1] == b'\x51':
AxL=int(data[2:3].encode('hex'), 16)
AxH=int(data[3:4].encode('hex'), 16)
AyL=int(data[4:5].encode('hex'), 16)
AyH=int(data[5:6].encode('hex'), 16)
AzL=int(data[6:7].encode('hex'), 16)
AzH=int(data[7:8].encode('hex'), 16)
x = (AxH<<8|AxL)/32768.0*16.0
y = (AyH<<8|AyL)/32768.0*16.0
z = (AzH<<8|AzL)/32768.0*16.0
Anyone have any suggestions?
The complete IMU sensor manual is this: http://wiki.wit-motion.com/english/lib/exe/fetch.php?media=module:wt901:docs:jy901usermanualv4.pdf
struct
The axes data are stored as a little-endian signed short (2 byte) integers, so we can use struct
to unpack the data. The struct
module will take care of the correct interpretation of the bytes
as short integers.
import struct
g = 9.81
conv = 16.0 / 32768.0 * g
# ...
elif data[1] == b'\x51':
axes = struct.unpack("<hhh", data[2:8])
x, y, z = [a*conv for a in axes]
If you want to do the conversion yourself, I'd assume that the representation of the signed number is two's complement:
def twos_complement(x, bytes=2):
maxnum = 2**(bytes*8) - 1
msb = 1 << (bytes*8 - 1)
return -((x^maxnum) + 1) if x&msb else x
AxL = data[2]
AxH = data[3]
Ax_unsigned = AxH << 8 | AxL
Ax = twos_complement(Ax_unsigned, 2)