58
58
_ADXL345_MG2G_MULTIPLIER = 0.004 # 4mg per lsb
59
59
_STANDARD_GRAVITY = 9.80665 # earth standard gravity
60
60
61
- _ADXL345_REG_DEVID = const (0x00 ) # Device ID
62
- _ADXL345_REG_THRESH_TAP = const (0x1D ) # Tap threshold
63
- _ADXL345_REG_OFSX = const (0x1E ) # X-axis offset
64
- _ADXL345_REG_OFSY = const (0x1F ) # Y-axis offset
65
- _ADXL345_REG_OFSZ = const (0x20 ) # Z-axis offset
66
- _ADXL345_REG_DUR = const (0x21 ) # Tap duration
67
- _ADXL345_REG_LATENT = const (0x22 ) # Tap latency
68
- _ADXL345_REG_WINDOW = const (0x23 ) # Tap window
69
- _ADXL345_REG_THRESH_ACT = const (0x24 ) # Activity threshold
70
- _ADXL345_REG_THRESH_INACT = const (0x25 ) # Inactivity threshold
71
- _ADXL345_REG_TIME_INACT = const (0x26 ) # Inactivity time
72
- _ADXL345_REG_ACT_INACT_CTL = const (0x27 ) # Axis enable control for [in]activity detection
73
- _ADXL345_REG_THRESH_FF = const (0x28 ) # Free-fall threshold
74
- _ADXL345_REG_TIME_FF = const (0x29 ) # Free-fall time
75
- _ADXL345_REG_TAP_AXES = const (0x2A ) # Axis control for single/double tap
76
- _ADXL345_REG_ACT_TAP_STATUS = const (0x2B ) # Source for single/double tap
77
- _ADXL345_REG_BW_RATE = const (0x2C ) # Data rate and power mode control
78
- _ADXL345_REG_POWER_CTL = const (0x2D ) # Power-saving features control
79
- _ADXL345_REG_INT_ENABLE = const (0x2E ) # Interrupt enable control
80
- _ADXL345_REG_INT_MAP = const (0x2F ) # Interrupt mapping control
81
- _ADXL345_REG_INT_SOURCE = const (0x30 ) # Source of interrupts
82
- _ADXL345_REG_DATA_FORMAT = const (0x31 ) # Data format control
83
- _ADXL345_REG_DATAX0 = const (0x32 ) # X-axis data 0
84
- _ADXL345_REG_DATAX1 = const (0x33 ) # X-axis data 1
85
- _ADXL345_REG_DATAY0 = const (0x34 ) # Y-axis data 0
86
- _ADXL345_REG_DATAY1 = const (0x35 ) # Y-axis data 1
87
- _ADXL345_REG_DATAZ0 = const (0x36 ) # Z-axis data 0
88
- _ADXL345_REG_DATAZ1 = const (0x37 ) # Z-axis data 1
89
- _ADXL345_REG_FIFO_CTL = const (0x38 ) # FIFO control
90
- _ADXL345_REG_FIFO_STATUS = const (0x39 ) # FIFO status
61
+ _REG_DEVID = const (0x00 ) # Device ID
62
+ _REG_THRESH_TAP = const (0x1D ) # Tap threshold
63
+ _REG_OFSX = const (0x1E ) # X-axis offset
64
+ _REG_OFSY = const (0x1F ) # Y-axis offset
65
+ _REG_OFSZ = const (0x20 ) # Z-axis offset
66
+ _REG_DUR = const (0x21 ) # Tap duration
67
+ _REG_LATENT = const (0x22 ) # Tap latency
68
+ _REG_WINDOW = const (0x23 ) # Tap window
69
+ _REG_THRESH_ACT = const (0x24 ) # Activity threshold
70
+ _REG_THRESH_INACT = const (0x25 ) # Inactivity threshold
71
+ _REG_TIME_INACT = const (0x26 ) # Inactivity time
72
+ _REG_ACT_INACT_CTL = const (0x27 ) # Axis enable control for [in]activity detection
73
+ _REG_THRESH_FF = const (0x28 ) # Free-fall threshold
74
+ _REG_TIME_FF = const (0x29 ) # Free-fall time
75
+ _REG_TAP_AXES = const (0x2A ) # Axis control for single/double tap
76
+ _REG_ACT_TAP_STATUS = const (0x2B ) # Source for single/double tap
77
+ _REG_BW_RATE = const (0x2C ) # Data rate and power mode control
78
+ _REG_POWER_CTL = const (0x2D ) # Power-saving features control
79
+ _REG_INT_ENABLE = const (0x2E ) # Interrupt enable control
80
+ _REG_INT_MAP = const (0x2F ) # Interrupt mapping control
81
+ _REG_INT_SOURCE = const (0x30 ) # Source of interrupts
82
+ _REG_DATA_FORMAT = const (0x31 ) # Data format control
83
+ _REG_DATAX0 = const (0x32 ) # X-axis data 0
84
+ _REG_DATAX1 = const (0x33 ) # X-axis data 1
85
+ _REG_DATAY0 = const (0x34 ) # Y-axis data 0
86
+ _REG_DATAY1 = const (0x35 ) # Y-axis data 1
87
+ _REG_DATAZ0 = const (0x36 ) # Z-axis data 0
88
+ _REG_DATAZ1 = const (0x37 ) # Z-axis data 1
89
+ _REG_FIFO_CTL = const (0x38 ) # FIFO control
90
+ _REG_FIFO_STATUS = const (0x39 ) # FIFO status
91
+ _INT_SINGLE_TAP = const (0b01000000 ) # SINGLE_TAP bit
92
+ _INT_DOUBLE_TAP = const (0b00100000 ) # DOUBLE_TAP bit
93
+ _INT_ACT = const (0b00010000 ) # ACT bit
94
+ _INT_INACT = const (0b00001000 ) # INACT bit
95
+ _INT_FREE_FALL = const (0b00000100 ) # FREE_FALL bit
91
96
92
97
class DataRate : #pylint: disable=too-few-public-methods
93
98
"""An enum-like class representing the possible data rates.
@@ -155,40 +160,210 @@ class ADXL345:
155
160
"""
156
161
def __init__ (self , i2c , address = _ADXL345_DEFAULT_ADDRESS ):
157
162
163
+
158
164
self ._i2c = i2c_device .I2CDevice (i2c , address )
159
165
self ._buffer = bytearray (6 )
160
166
# set the 'measure' bit in to enable measurement
161
- self ._write_register_byte (_ADXL345_REG_POWER_CTL , 0x08 )
167
+ self ._write_register_byte (_REG_POWER_CTL , 0x08 )
168
+ self ._write_register_byte (_REG_INT_ENABLE , 0x0 )
169
+
170
+ self ._enabled_interrupts = {}
171
+ self ._event_status = {}
162
172
163
173
@property
164
174
def acceleration (self ):
165
175
"""The x, y, z acceleration values returned in a 3-tuple in m / s ^ 2."""
166
- x , y , z = unpack ('<hhh' , self ._read_register (_ADXL345_REG_DATAX0 , 6 ))
176
+ x , y , z = unpack ('<hhh' , self ._read_register (_REG_DATAX0 , 6 ))
167
177
x = x * _ADXL345_MG2G_MULTIPLIER * _STANDARD_GRAVITY
168
178
y = y * _ADXL345_MG2G_MULTIPLIER * _STANDARD_GRAVITY
169
179
z = z * _ADXL345_MG2G_MULTIPLIER * _STANDARD_GRAVITY
170
180
return (x , y , z )
171
181
182
+ @property
183
+ def events (self ):
184
+ """
185
+ ``events`` will return a dictionary with a key for each event type that has been enabled.
186
+ The possible keys are:
187
+
188
+ +------------+----------------------------------------------------------------------------+
189
+ | Key | Description |
190
+ +============+============================================================================+
191
+ | ``tap`` | True if a tap was detected recently. Whether it's looking for a single or |
192
+ | | double tap is determined by the tap param of `enable_tap_detection` |
193
+ +------------+----------------------------------------------------------------------------+
194
+ | ``motion`` | True if the sensor has seen acceleration above the threshold |
195
+ | | set with `enable_motion_detection`. |
196
+ +------------+----------------------------------------------------------------------------+
197
+ |``freefall``| True if the sensor was in freefall. Parameters are set when enabled with |
198
+ | | `enable_freefall_detection` |
199
+ +------------+----------------------------------------------------------------------------+
200
+
201
+
202
+ """
203
+
204
+ interrupt_source_register = self ._read_clear_interrupt_source ()
205
+
206
+ self ._event_status .clear ()
207
+
208
+ for event_type , value in self ._enabled_interrupts .items ():
209
+ if event_type == "motion" :
210
+ self ._event_status [event_type ] = interrupt_source_register & _INT_ACT > 0
211
+ if event_type == "tap" :
212
+ if value == 1 :
213
+ self ._event_status [event_type ] = interrupt_source_register & _INT_SINGLE_TAP > 0
214
+ else :
215
+ self ._event_status [event_type ] = interrupt_source_register & _INT_DOUBLE_TAP > 0
216
+ if event_type == "freefall" :
217
+ self ._event_status [event_type ] = interrupt_source_register & _INT_FREE_FALL > 0
218
+
219
+ return self ._event_status
220
+
221
+ def enable_motion_detection (self , * , threshold = 18 ):
222
+ """
223
+ The activity detection parameters.
224
+
225
+ :param int threshold: The value that acceleration on any axis must exceed to\
226
+ register as active. The scale factor is 62.5 mg/LSB.
227
+
228
+ If you wish to set them yourself rather than using the defaults,
229
+ you must use keyword arguments::
230
+
231
+ accelerometer.enable_motion_detection(threshold=20)
232
+
233
+ """
234
+ active_interrupts = self ._read_register_unpacked (_REG_INT_ENABLE )
235
+
236
+
237
+ self ._write_register_byte (_REG_INT_ENABLE , 0x0 ) # disable interrupts for setup
238
+ self ._write_register_byte (_REG_ACT_INACT_CTL , 0b01110000 ) # enable activity on X,Y,Z
239
+ self ._write_register_byte (_REG_THRESH_ACT , threshold )
240
+ self ._write_register_byte (_REG_INT_ENABLE , _INT_ACT ) # Inactive interrupt only
241
+
242
+ active_interrupts |= _INT_ACT
243
+ self ._write_register_byte (_REG_INT_ENABLE , active_interrupts )
244
+ self ._enabled_interrupts ["motion" ] = True
245
+
246
+ def disable_motion_detection (self ):
247
+ """
248
+ Disable motion detection
249
+ """
250
+ active_interrupts = self ._read_register_unpacked (_REG_INT_ENABLE )
251
+ active_interrupts &= ~ _INT_ACT
252
+ self ._write_register_byte (_REG_INT_ENABLE , active_interrupts )
253
+ self ._enabled_interrupts .pop ("motion" )
254
+
255
+
256
+ def enable_freefall_detection (self , * , threshold = 10 , time = 25 ):
257
+ """
258
+ Freefall detection parameters:
259
+
260
+ :param int threshold: The value that acceleration on all axes must be under to\
261
+ register as dropped. The scale factor is 62.5 mg/LSB.
262
+
263
+ :param int time: The amount of time that acceleration on all axes must be less than\
264
+ ``threshhold`` to register as dropped. The scale factor is 5 ms/LSB. Values between 100 ms\
265
+ and 350 ms (20 to 70) are recommended.
266
+
267
+ If you wish to set them yourself rather than using the defaults,
268
+ you must use keyword arguments::
269
+
270
+ accelerometer.enable_freefall_detection(time=30)
271
+
272
+ """
273
+
274
+ active_interrupts = self ._read_register_unpacked (_REG_INT_ENABLE )
275
+
276
+ self ._write_register_byte (_REG_INT_ENABLE , 0x0 ) # disable interrupts for setup
277
+ self ._write_register_byte (_REG_THRESH_FF , threshold )
278
+ self ._write_register_byte (_REG_TIME_FF , time )
279
+
280
+ # add FREE_FALL to the active interrupts and set them to re-enable
281
+ active_interrupts |= _INT_FREE_FALL
282
+ self ._write_register_byte (_REG_INT_ENABLE , active_interrupts )
283
+ self ._enabled_interrupts ["freefall" ] = True
284
+
285
+ def disable_freefall_detection (self ):
286
+ "Disable freefall detection"
287
+ active_interrupts = self ._read_register_unpacked (_REG_INT_ENABLE )
288
+ active_interrupts &= ~ _INT_FREE_FALL
289
+ self ._write_register_byte (_REG_INT_ENABLE , active_interrupts )
290
+ self ._enabled_interrupts .pop ("freefall" )
291
+
292
+ def enable_tap_detection (self , * , tap_count = 1 , threshold = 20 , duration = 50 , latency = 20 , window = 255 ):#pylint: disable=line-too-long
293
+ """
294
+ The tap detection parameters.
295
+
296
+ :param int tap_count: 1 to detect only single taps, and 2 to detect only double taps.
297
+
298
+ :param int threshold: A threshold for the tap detection. The scale factor is 62.5 mg/LSB\
299
+ The higher the value the less sensitive the detection. This changes based on the\
300
+ accelerometer range.
301
+
302
+ :param int duration: This caps the duration of the impulse above ``threshhold``.\
303
+ Anything above ``duration`` won't register as a tap. The scale factor is 625 µs/LSB
304
+
305
+ :param int latency(double tap only): The length of time after the initial impulse\
306
+ falls below ``threshold`` to start the window looking for a second impulse.\
307
+ The scale factor is 1.25 ms/LSB.
308
+
309
+ :param int window(double tap only): The length of the window in which to look for a\
310
+ second tap. The scale factor is 1.25 ms/LSB
311
+
312
+ If you wish to set them yourself rather than using the defaults,
313
+ you must use keyword arguments::
314
+
315
+ accelerometer.enable_tap_detection(duration=30, threshold=25)
316
+
317
+ """
318
+ active_interrupts = self ._read_register_unpacked (_REG_INT_ENABLE )
319
+
320
+ self ._write_register_byte (_REG_INT_ENABLE , 0x0 ) # disable interrupts for setup
321
+ self ._write_register_byte (_REG_TAP_AXES , 0b00000111 ) # enable X, Y, Z axes for tap
322
+ self ._write_register_byte (_REG_THRESH_TAP , threshold )
323
+ self ._write_register_byte (_REG_DUR , duration )
324
+
325
+ if tap_count == 1 :
326
+ active_interrupts |= _INT_SINGLE_TAP
327
+ self ._write_register_byte (_REG_INT_ENABLE , active_interrupts )
328
+ self ._enabled_interrupts ["tap" ] = 1
329
+ elif tap_count == 2 :
330
+ self ._write_register_byte (_REG_LATENT , latency )
331
+ self ._write_register_byte (_REG_WINDOW , window )
332
+
333
+ active_interrupts |= _INT_DOUBLE_TAP
334
+ self ._write_register_byte (_REG_INT_ENABLE , active_interrupts )
335
+ self ._enabled_interrupts ["tap" ] = 2
336
+ else :
337
+ raise ValueError ("tap must be 0 to disable, 1 for single tap, or 2 for double tap" )
338
+
339
+ def disable_tap_detection (self ):
340
+ "Disable tap detection"
341
+ active_interrupts = self ._read_register_unpacked (_REG_INT_ENABLE )
342
+ active_interrupts &= ~ _INT_SINGLE_TAP
343
+ active_interrupts &= ~ _INT_DOUBLE_TAP
344
+ self ._write_register_byte (_REG_INT_ENABLE , active_interrupts )
345
+ self ._enabled_interrupts .pop ("tap" )
346
+
172
347
@property
173
348
def data_rate (self ):
174
349
"""The data rate of the sensor."""
175
- rate_register = unpack ( "<b" , self ._read_register ( _ADXL345_REG_BW_RATE , 1 ))[ 0 ]
350
+ rate_register = self ._read_register_unpacked ( _REG_BW_RATE )
176
351
return rate_register & 0x0F
177
352
178
353
@data_rate .setter
179
354
def data_rate (self , val ):
180
- self ._write_register_byte (_ADXL345_REG_BW_RATE , val )
355
+ self ._write_register_byte (_REG_BW_RATE , val )
181
356
182
357
@property
183
358
def range (self ):
184
359
"""The measurement range of the sensor."""
185
- range_register = unpack ( "<b" , self ._read_register ( _ADXL345_REG_DATA_FORMAT , 1 ))[ 0 ]
360
+ range_register = self ._read_register_unpacked ( _REG_DATA_FORMAT )
186
361
return range_register & 0x03
187
362
188
363
@range .setter
189
364
def range (self , val ):
190
365
# read the current value of the data format register
191
- format_register = unpack ( "<b" , self ._read_register ( _ADXL345_REG_DATA_FORMAT , 1 ))[ 0 ]
366
+ format_register = self ._read_register_unpacked ( _REG_DATA_FORMAT )
192
367
193
368
# clear the bottom 4 bits and update the data rate
194
369
format_register &= ~ 0x0F
@@ -198,7 +373,13 @@ def range(self, val):
198
373
format_register |= 0x08
199
374
200
375
# write the updated values
201
- self ._write_register_byte (_ADXL345_REG_DATA_FORMAT , format_register )
376
+ self ._write_register_byte (_REG_DATA_FORMAT , format_register )
377
+
378
+ def _read_clear_interrupt_source (self ):
379
+ return self ._read_register_unpacked (_REG_INT_SOURCE )
380
+
381
+ def _read_register_unpacked (self , register ):
382
+ return unpack ("<b" , self ._read_register (register , 1 ))[0 ]
202
383
203
384
def _read_register (self , register , length ):
204
385
self ._buffer [0 ] = register & 0xFF
@@ -212,3 +393,9 @@ def _write_register_byte(self, register, value):
212
393
self ._buffer [1 ] = value & 0xFF
213
394
with self ._i2c as i2c :
214
395
i2c .write (self ._buffer , start = 0 , end = 2 )
396
+
397
+ def _config_iterrupt_register (self , register , value ):
398
+ active_interrupts = self ._read_register_unpacked (_REG_INT_ENABLE )
399
+ self ._write_register_byte (_REG_INT_ENABLE , 0x0 ) # disable interrupts for setup
400
+ self ._write_register_byte (register , value )
401
+ self ._write_register_byte (_REG_INT_ENABLE , active_interrupts )
0 commit comments