Skip to content

Commit 553d3ad

Browse files
committed
Fix parsing of signed values.
1 parent 48291f8 commit 553d3ad

File tree

1 file changed

+40
-34
lines changed

1 file changed

+40
-34
lines changed

adafruit_fxos8700.py

Lines changed: 40 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
3232
* Author(s): Tony DiCola
3333
"""
34+
import ustruct
35+
3436
import adafruit_bus_device.i2c_device as i2c_device
3537

3638

@@ -73,6 +75,15 @@
7375
ACCEL_RANGE_8G = 0x02
7476

7577

78+
def _twos_comp(val, bits):
79+
# Convert an unsigned integer in 2's compliment form of the specified bit
80+
# length to its signed integer value and return it.
81+
if val & (1 << (bits - 1)) != 0:
82+
return val - (1 << bits)
83+
else:
84+
return val
85+
86+
7687
class FXOS8700:
7788

7889
# Class-level buffer for reading and writing data with the sensor.
@@ -108,54 +119,49 @@ def __init__(self, i2c, address=_FXOS8700_ADDRESS,
108119

109120
def _read_u8(self, address):
110121
# Read an 8-bit unsigned value from the specified 8-bit address.
111-
with self._device:
122+
with self._device as i2c:
112123
self._BUFFER[0] = address & 0xFF
113-
self._device.write(self._BUFFER, end=1, stop=False)
114-
self._device.readinto(self._BUFFER, end=1)
124+
i2c.write(self._BUFFER, end=1, stop=False)
125+
i2c.readinto(self._BUFFER, end=1)
115126
return self._BUFFER[0]
116127

117128
def _write_u8(self, address, val):
118129
# Write an 8-bit unsigned value to the specified 8-bit address.
119-
with self._device:
130+
with self._device as i2c:
120131
self._BUFFER[0] = address & 0xFF
121132
self._BUFFER[1] = val & 0xFF
122-
self._device.write(self._BUFFER, end=2)
133+
i2c.write(self._BUFFER, end=2)
123134

124135
def read_raw_accel_mag(self):
125136
"""Read the raw accelerometer and magnetometer readings. Returns a
126137
2-tuple of 3-tuples:
127-
- Accelerometer X, Y, Z axis 14-bit unsigned raw values
128-
- Magnetometer X, Y, Z axis 16-bit unsigned raw values
138+
- Accelerometer X, Y, Z axis 14-bit signed raw values
139+
- Magnetometer X, Y, Z axis 16-bit signed raw values
129140
If you want the acceleration or magnetometer values in friendly units
130141
consider using the accelerometer and magnetometer properties!
131142
"""
132-
# Read 13 bytes from the sensor.
133-
with self._device:
134-
self._BUFFER[0] = _FXOS8700_REGISTER_STATUS | 0x80
135-
self._device.write(self._BUFFER, end=1, stop=False)
136-
self._device.readinto(self._BUFFER)
137-
# Parse out the accelerometer and magnetometer data.
138-
status = self._BUFFER[0]
139-
axhi = self._BUFFER[1]
140-
axlo = self._BUFFER[2]
141-
ayhi = self._BUFFER[3]
142-
aylo = self._BUFFER[4]
143-
azhi = self._BUFFER[5]
144-
azlo = self._BUFFER[6]
145-
mxhi = self._BUFFER[7]
146-
mxlo = self._BUFFER[8]
147-
myhi = self._BUFFER[9]
148-
mylo = self._BUFFER[10]
149-
mzhi = self._BUFFER[11]
150-
mzlo = self._BUFFER[12]
151-
# Shift values to create properly formed integers
152-
# Note, accel data is 14-bit and left-aligned, so we shift two bit right
153-
accel_raw_x = (((axhi << 8) | axlo) >> 2) & 0xFFFF
154-
accel_raw_y = (((ayhi << 8) | aylo) >> 2) & 0xFFFF
155-
accel_raw_z = (((azhi << 8) | azlo) >> 2) & 0xFFFF
156-
mag_raw_x = ((mxhi << 8) | mxlo) & 0xFFFF
157-
mag_raw_y = ((myhi << 8) | mylo) & 0xFFFF
158-
mag_raw_z = ((mzhi << 8) | mzlo) & 0xFFFF
143+
# Read accelerometer data from sensor.
144+
with self._device as i2c:
145+
self._BUFFER[0] = _FXOS8700_REGISTER_OUT_X_MSB
146+
i2c.write(self._BUFFER, end=1, stop=False)
147+
i2c.readinto(self._BUFFER, end=6)
148+
accel_raw_x = ustruct.unpack_from('>H', self._BUFFER[0:2])[0]
149+
accel_raw_y = ustruct.unpack_from('>H', self._BUFFER[2:4])[0]
150+
accel_raw_z = ustruct.unpack_from('>H', self._BUFFER[4:6])[0]
151+
# Convert accelerometer data to signed 14-bit value from 16-bit
152+
# left aligned 2's compliment value.
153+
accel_raw_x = _twos_comp(accel_raw_x >> 2, 14)
154+
accel_raw_y = _twos_comp(accel_raw_y >> 2, 14)
155+
accel_raw_z = _twos_comp(accel_raw_z >> 2, 14)
156+
# Read magnetometer data from sensor. No need to convert as this is
157+
# 16-bit signed data so struct parsing can handle it directly.
158+
with self._device as i2c:
159+
self._BUFFER[0] = _FXOS8700_REGISTER_MOUT_X_MSB
160+
i2c.write(self._BUFFER, end=1, stop=False)
161+
i2c.readinto(self._BUFFER, end=6)
162+
mag_raw_x = ustruct.unpack_from('>h', self._BUFFER[0:2])[0]
163+
mag_raw_y = ustruct.unpack_from('>h', self._BUFFER[2:4])[0]
164+
mag_raw_z = ustruct.unpack_from('>h', self._BUFFER[4:6])[0]
159165
return ((accel_raw_x, accel_raw_y, accel_raw_z),
160166
(mag_raw_x, mag_raw_y, mag_raw_z))
161167

0 commit comments

Comments
 (0)