5858_ADXL345_MG2G_MULTIPLIER = 0.004 # 4mg per lsb
5959_STANDARD_GRAVITY = 9.80665 # earth standard gravity
6060
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
9196
9297class DataRate : #pylint: disable=too-few-public-methods
9398 """An enum-like class representing the possible data rates.
@@ -155,40 +160,210 @@ class ADXL345:
155160 """
156161 def __init__ (self , i2c , address = _ADXL345_DEFAULT_ADDRESS ):
157162
163+
158164 self ._i2c = i2c_device .I2CDevice (i2c , address )
159165 self ._buffer = bytearray (6 )
160166 # 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 = {}
162172
163173 @property
164174 def acceleration (self ):
165175 """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 ))
167177 x = x * _ADXL345_MG2G_MULTIPLIER * _STANDARD_GRAVITY
168178 y = y * _ADXL345_MG2G_MULTIPLIER * _STANDARD_GRAVITY
169179 z = z * _ADXL345_MG2G_MULTIPLIER * _STANDARD_GRAVITY
170180 return (x , y , z )
171181
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+
172347 @property
173348 def data_rate (self ):
174349 """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 )
176351 return rate_register & 0x0F
177352
178353 @data_rate .setter
179354 def data_rate (self , val ):
180- self ._write_register_byte (_ADXL345_REG_BW_RATE , val )
355+ self ._write_register_byte (_REG_BW_RATE , val )
181356
182357 @property
183358 def range (self ):
184359 """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 )
186361 return range_register & 0x03
187362
188363 @range .setter
189364 def range (self , val ):
190365 # 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 )
192367
193368 # clear the bottom 4 bits and update the data rate
194369 format_register &= ~ 0x0F
@@ -198,7 +373,13 @@ def range(self, val):
198373 format_register |= 0x08
199374
200375 # 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 ]
202383
203384 def _read_register (self , register , length ):
204385 self ._buffer [0 ] = register & 0xFF
@@ -212,3 +393,9 @@ def _write_register_byte(self, register, value):
212393 self ._buffer [1 ] = value & 0xFF
213394 with self ._i2c as i2c :
214395 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