32
32
* Author(s): Tony DiCola
33
33
"""
34
34
import time
35
+ import ustruct
35
36
36
37
import adafruit_bus_device .i2c_device as i2c_device
37
38
import adafruit_bus_device .spi_device as spi_device
112
113
GYROSCALE_500DPS = (0b01 << 4 ) # +/- 500 degrees/s rotation
113
114
GYROSCALE_2000DPS = (0b11 << 4 ) # +/- 2000 degrees/s rotation
114
115
116
+
117
+ def _twos_comp (val , bits ):
118
+ # Convert an unsigned integer in 2's compliment form of the specified bit
119
+ # length to its signed integer value and return it.
120
+ if val & (1 << (bits - 1 )) != 0 :
121
+ return val - (1 << bits )
122
+ else :
123
+ return val
124
+
125
+
115
126
class LSM9DS1 :
116
127
117
128
# Class-level buffer for reading and writing data with the sensor.
@@ -230,16 +241,9 @@ def read_accel_raw(self):
230
241
# Read the accelerometer
231
242
self ._read_bytes (_XGTYPE , 0x80 | _LSM9DS1_REGISTER_OUT_X_L_XL , 6 ,
232
243
self ._BUFFER )
233
- xlo = self ._BUFFER [0 ];
234
- xhi = self ._BUFFER [1 ];
235
- ylo = self ._BUFFER [2 ];
236
- yhi = self ._BUFFER [3 ];
237
- zlo = self ._BUFFER [4 ];
238
- zhi = self ._BUFFER [5 ];
239
- # Shift values to create properly formed integer (low byte first)
240
- raw_x = ((xhi << 8 ) | xlo ) & 0xFFFF
241
- raw_y = ((yhi << 8 ) | ylo ) & 0xFFFF
242
- raw_z = ((zhi << 8 ) | zlo ) & 0xFFFF
244
+ raw_x = ustruct .unpack_from ('<h' , self ._BUFFER [0 :2 ])[0 ]
245
+ raw_y = ustruct .unpack_from ('<h' , self ._BUFFER [2 :4 ])[0 ]
246
+ raw_z = ustruct .unpack_from ('<h' , self ._BUFFER [4 :6 ])[0 ]
243
247
return (raw_x , raw_y , raw_z )
244
248
245
249
@property
@@ -260,16 +264,9 @@ def read_mag_raw(self):
260
264
# Read the magnetometer
261
265
self ._read_bytes (_MAGTYPE , 0x80 | _LSM9DS1_REGISTER_OUT_X_L_M , 6 ,
262
266
self ._BUFFER )
263
- xlo = self ._BUFFER [0 ];
264
- xhi = self ._BUFFER [1 ];
265
- ylo = self ._BUFFER [2 ];
266
- yhi = self ._BUFFER [3 ];
267
- zlo = self ._BUFFER [4 ];
268
- zhi = self ._BUFFER [5 ];
269
- # Shift values to create properly formed integer (low byte first)
270
- raw_x = ((xhi << 8 ) | xlo ) & 0xFFFF
271
- raw_y = ((yhi << 8 ) | ylo ) & 0xFFFF
272
- raw_z = ((zhi << 8 ) | zlo ) & 0xFFFF
267
+ raw_x = ustruct .unpack_from ('<h' , self ._BUFFER [0 :2 ])[0 ]
268
+ raw_y = ustruct .unpack_from ('<h' , self ._BUFFER [2 :4 ])[0 ]
269
+ raw_z = ustruct .unpack_from ('<h' , self ._BUFFER [4 :6 ])[0 ]
273
270
return (raw_x , raw_y , raw_z )
274
271
275
272
@property
@@ -289,16 +286,9 @@ def read_gyro_raw(self):
289
286
# Read the gyroscope
290
287
self ._read_bytes (_XGTYPE , 0x80 | _LSM9DS1_REGISTER_OUT_X_L_G , 6 ,
291
288
self ._BUFFER )
292
- xlo = self ._BUFFER [0 ];
293
- xhi = self ._BUFFER [1 ];
294
- ylo = self ._BUFFER [2 ];
295
- yhi = self ._BUFFER [3 ];
296
- zlo = self ._BUFFER [4 ];
297
- zhi = self ._BUFFER [5 ];
298
- # Shift values to create properly formed integer (low byte first)
299
- raw_x = ((xhi << 8 ) | xlo ) & 0xFFFF
300
- raw_y = ((yhi << 8 ) | ylo ) & 0xFFFF
301
- raw_z = ((zhi << 8 ) | zlo ) & 0xFFFF
289
+ raw_x = ustruct .unpack_from ('<h' , self ._BUFFER [0 :2 ])[0 ]
290
+ raw_y = ustruct .unpack_from ('<h' , self ._BUFFER [2 :4 ])[0 ]
291
+ raw_z = ustruct .unpack_from ('<h' , self ._BUFFER [4 :6 ])[0 ]
302
292
return (raw_x , raw_y , raw_z )
303
293
304
294
@property
@@ -310,22 +300,26 @@ def gyroscope(self):
310
300
return map (lambda x : x * self ._gyro_dps_digit , raw )
311
301
312
302
def read_temp_raw (self ):
313
- """Read the raw temperature sensor value and return it as a 16 -bit
314
- unsigned value. If you want the temperature in nice units you probably
303
+ """Read the raw temperature sensor value and return it as a 12 -bit
304
+ signed value. If you want the temperature in nice units you probably
315
305
want to use the temperature property!
316
306
"""
317
307
# Read temp sensor
318
308
self ._read_bytes (_XGTYPE , 0x80 | _LSM9DS1_REGISTER_TEMP_OUT_L , 2 ,
319
309
self ._BUFFER )
320
- temp = (self ._BUFFER [1 ] << 8 ) | self ._BUFFER [0 ]
310
+ temp = ((self ._BUFFER [1 ] << 8 ) | self ._BUFFER [0 ]) >> 4
311
+ return _twos_comp (temp , 12 )
312
+ #print('Raw temp: {0} 0x{0:04X}'.format(temp))
321
313
return temp
322
314
323
315
@property
324
316
def temperature (self ):
325
317
"""Get the temperature of the sensor in degrees Celsius."""
326
318
# This is just a guess since the starting point (21C here) isn't documented :(
319
+ # See discussion from:
320
+ # https://github.com/kriswiner/LSM9DS1/issues/3
327
321
temp = self .read_temp_raw ()
328
- temp = 21.0 + temp / 8
322
+ temp = 27.5 + temp / 16
329
323
return temp
330
324
331
325
def _read_u8 (self , sensor_type , address ):
@@ -335,7 +329,7 @@ def _read_u8(self, sensor_type, address):
335
329
# MUST be implemented by subclasses!
336
330
raise NotImplementedError ()
337
331
338
- def _read_bytes (self , sensor_type , address , count , buffer ):
332
+ def _read_bytes (self , sensor_type , address , count , buf ):
339
333
# Read a count number of bytes into buffer from the provided 8-bit
340
334
# register address. The sensor_type boolean should be _MAGTYPE when
341
335
# talking to the magnetometer, or _XGTYPE when talking to the accel or
@@ -368,15 +362,15 @@ def _read_u8(self, sensor_type, address):
368
362
i2c .readinto (self ._BUFFER , end = 1 )
369
363
return self ._BUFFER [0 ]
370
364
371
- def _read_bytes (self , sensor_type , address , count , buffer ):
365
+ def _read_bytes (self , sensor_type , address , count , buf ):
372
366
if sensor_type == _MAGTYPE :
373
367
device = self ._mag_device
374
368
else :
375
369
device = self ._xg_device
376
370
with device as i2c :
377
- self . _BUFFER [0 ] = address & 0xFF
378
- i2c .write (self . _BUFFER , end = 1 , stop = False )
379
- i2c .readinto (self . _BUFFER , end = count )
371
+ buf [0 ] = address & 0xFF
372
+ i2c .write (buf , end = 1 , stop = False )
373
+ i2c .readinto (buf , end = count )
380
374
381
375
def _write_u8 (self , sensor_type , address , val ):
382
376
if sensor_type == _MAGTYPE :
0 commit comments