55
55
from adafruit_register .i2c_struct import UnaryStruct
56
56
from adafruit_register .i2c_bit import RWBit
57
57
from adafruit_register .i2c_bits import RWBits
58
+ from adafruit_register .i2c_struct_array import StructArray
58
59
59
60
60
61
__version__ = "0.0.0-auto.0"
101
102
_REG_ACCEL_WHO_AM_I = const (0x0F )
102
103
103
104
# Conversion constants
104
- _LSM303ACCEL_MG_LSB = 16704.0
105
+ _LSM303ACCEL_MG_LSB = 16704.0 # magic!
105
106
_GRAVITY_STANDARD = 9.80665 # Earth's gravity in m/s^2
107
+ _SMOLLER_GRAVITY = 0.00980665
108
+
109
+ class Rate :
110
+ RATE_SHUTDOWN = const (0 )
111
+ RATE_1_HZ = const (1 )
112
+ RATE_10_HZ = const (2 )
113
+ RATE_25_HZ = const (3 )
114
+ RATE_50_HZ = const (4 )
115
+ RATE_100_HZ = const (5 )
116
+ RATE_200_HZ = const (6 )
117
+ RATE_400_HZ = const (7 )
118
+ RATE_1620_HZ = const (8 )
119
+ RATE_1344_HZ = const (9 )
120
+
121
+ class Mode :
122
+ """Options for `mode`"""
123
+ MODE_NORMAL = const (0 )
124
+ MODE_HIGH_RESOLUTION = const (1 )
125
+ MODE_LOW_POWER = const (2 )
126
+
127
+ class Range :
128
+ """Options for `range`"""
129
+ RANGE_2G = const (0 )
130
+ RANGE_4G = const (1 )
131
+ RANGE_8G = const (2 )
132
+ RANGE_16G = const (3 )
133
+
106
134
# pylint: enable=bad-whitespace
107
135
108
136
class LSM303_Accel :
@@ -122,13 +150,25 @@ class LSM303_Accel:
122
150
_act_duration = UnaryStruct (_REG_ACCEL_ACT_DUR_A , "B" )
123
151
124
152
_data_rate = RWBits (4 , _REG_ACCEL_CTRL_REG1_A , 4 , 1 )
153
+ _enable_xyz = RWBits (3 , _REG_ACCEL_CTRL_REG1_A , 0 , 1 )
154
+ _raw_accel_data = StructArray (_REG_ACCEL_OUT_X_L_A , "<h" , 3 )
155
+
156
+ _low_power = RWBit (_REG_ACCEL_CTRL_REG1_A , 3 , 1 )
157
+ _high_resolution = RWBit (_REG_ACCEL_CTRL_REG4_A , 3 , 1 )
158
+
159
+
160
+ _range = RWBits (2 , _REG_ACCEL_CTRL_REG4_A , 4 , 1 )
125
161
126
162
_BUFFER = bytearray (6 )
127
163
128
164
def __init__ (self , i2c ):
129
165
self ._accel_device = I2CDevice (i2c , _ADDRESS_ACCEL )
130
166
self .i2c_device = self ._accel_device
131
- self ._write_u8 (self ._accel_device , _REG_ACCEL_CTRL_REG1_A , 0x27 ) # Enable the accelerometer
167
+ #self._write_u8(self._accel_device, _REG_ACCEL_CTRL_REG1_A, 0x27) # Enable the accelerometer
168
+ self ._data_rate = 2
169
+ self ._enable_xyz = 0b111
170
+ self ._cached_mode = 0
171
+ self ._cached_range = 0
132
172
133
173
@property
134
174
def raw_acceleration (self ):
@@ -143,9 +183,101 @@ def acceleration(self):
143
183
"""The processed accelerometer sensor values.
144
184
A 3-tuple of X, Y, Z axis values in meters per second squared that are signed floats.
145
185
"""
186
+
146
187
raw_accel_data = self .raw_acceleration
147
- return tuple ([n / _LSM303ACCEL_MG_LSB * _GRAVITY_STANDARD for n in raw_accel_data ])
148
188
189
+ x = self ._scale_data (raw_accel_data [0 ])
190
+ y = self ._scale_data (raw_accel_data [1 ])
191
+ z = self ._scale_data (raw_accel_data [2 ])
192
+
193
+ return (x , y , z )
194
+
195
+ def _scale_data (self , raw_measurement ):
196
+ lsb , shift = self ._lsb_shift ()
197
+
198
+ return (raw_measurement >> shift ) * lsb * _SMOLLER_GRAVITY
199
+
200
+ def _lsb_shift (self ):
201
+ # the bit depth of the data depends on the mode, and the lsb value
202
+ # depends on the mode and range
203
+ lsb = - 1 # the default, normal mode @ 2G
204
+
205
+ if self ._cached_mode is Mode .MODE_HIGH_RESOLUTION : # 12-bit
206
+ shift = 4
207
+ if self ._cached_range is Range .RANGE_2G :
208
+ lsb = 0.98
209
+ elif self ._cached_range is Range .RANGE_4G :
210
+ lsb = 1.95
211
+ elif self ._cached_range is Range .RANGE_8G :
212
+ lsb = 3.9
213
+ elif self ._cached_range is Range .RANGE_16G :
214
+ lsb = 11.72
215
+ elif self ._cached_mode is Mode .MODE_NORMAL : # 10-bit
216
+ shift = 6
217
+ if self ._cached_range is Range .RANGE_2G :
218
+ lsb = 3.9
219
+ elif self ._cached_range is Range .RANGE_4G :
220
+ lsb = 7.82
221
+ elif self ._cached_range is Range .RANGE_8G :
222
+ lsb = 15.63
223
+ elif self ._cached_range is Range .RANGE_16G :
224
+ lsb = 46.9
225
+
226
+
227
+ elif self ._cached_mode is Mode .MODE_LOW_POWER : # 8-bit
228
+ shift = 8
229
+ if self ._cached_range is Range .RANGE_2G :
230
+ lsb = 15.63
231
+ elif self ._cached_range is Range .RANGE_4G :
232
+ lsb = 31.26
233
+ elif self ._cached_range is Range .RANGE_8G :
234
+ lsb = 62.52
235
+ elif self ._cached_range is Range .RANGE_16G :
236
+ lsb = 187.58
237
+
238
+ if lsb is - 1 :
239
+ raise AttributeError ("'impossible' range or mode detected: range: %d mode: %d" %
240
+ (self ._cached_range , self ._cached_mode ))
241
+ return (lsb , shift )
242
+
243
+ @property
244
+ def data_rate (self ):
245
+ """Select the rate at which the sensor takes measurements. Must be a `Rate`"""
246
+ return self ._data_rate
247
+
248
+ @data_rate .setter
249
+ def data_rate (self , value ):
250
+ if value < 0 or value > 9 :
251
+ raise AttributeError ("data_rate must be a `Rate`" )
252
+
253
+ self ._data_rate = value
254
+
255
+ @property
256
+ def range (self ):
257
+ """Adjusts the range of values that the sensor can measure, from +- 2G to +-16G
258
+ Note that larger ranges will be less accurate. Must be a `Range`"""
259
+ return self ._cached_range
260
+
261
+ @range .setter
262
+ def range (self , value ):
263
+ if value < 0 or value > 3 :
264
+ raise AttributeError ("range must be a `Range`" )
265
+ self ._range = value
266
+ self ._cached_range = value
267
+
268
+ @property
269
+ def mode (self ):
270
+ """Sets the power mode of the sensor. The mode must be a `Mode`. Note that the
271
+ mode and range will both affect the accuracy of the sensor"""
272
+ return self ._cached_mode
273
+
274
+ @mode .setter
275
+ def mode (self , value ):
276
+ if value < 0 or value > 2 :
277
+ raise AttributeError ("mode must be a `Mode`" )
278
+ self ._high_resolution = value & 0b01
279
+ self ._low_power = (value & 0b10 ) >> 1
280
+ self ._cached_mode = value
149
281
150
282
def _read_u8 (self , device , address ):
151
283
with device as i2c :
0 commit comments