Skip to content

Commit 46b5969

Browse files
authored
Merge pull request #7 from RoaCode/main
Added range and data_ready interrupt parameters
2 parents 9fb7385 + 38506f1 commit 46b5969

File tree

6 files changed

+174
-9
lines changed

6 files changed

+174
-9
lines changed

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ repos:
1818
- id: end-of-file-fixer
1919
- id: trailing-whitespace
2020
- repo: https://github.com/pycqa/pylint
21-
rev: v2.17.4
21+
rev: v3.2.6
2222
hooks:
2323
- id: pylint
2424
name: pylint (library code)

adafruit_adxl37x.py

+132-7
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
import adafruit_adxl34x
3434

3535
try:
36-
from typing import Tuple, Optional
36+
from typing import Tuple, Optional, Dict
3737

3838
# This is only needed for typing
3939
import busio
@@ -48,20 +48,66 @@
4848
_ADXL347_MULTIPLIER: float = 0.049 # 49mg per lsb
4949
_STANDARD_GRAVITY: float = 9.80665 # earth standard gravity
5050

51+
_REG_DEVID: int = const(0x00) # Device ID
52+
_REG_THRESH_TAP: int = const(0x1D) # Tap threshold
53+
_REG_OFSX: int = const(0x1E) # X-axis offset
54+
_REG_OFSY: int = const(0x1F) # Y-axis offset
55+
_REG_OFSZ: int = const(0x20) # Z-axis offset
56+
_REG_DUR: int = const(0x21) # Tap duration
57+
_REG_LATENT: int = const(0x22) # Tap latency
58+
_REG_WINDOW: int = const(0x23) # Tap window
59+
_REG_THRESH_ACT: int = const(0x24) # Activity threshold
60+
_REG_THRESH_INACT: int = const(0x25) # Inactivity threshold
61+
_REG_TIME_INACT: int = const(0x26) # Inactivity time
62+
_REG_ACT_INACT_CTL: int = const(0x27) # Axis enable control for [in]activity detection
63+
_REG_THRESH_FF: int = const(0x28) # Free-fall threshold
64+
_REG_TIME_FF: int = const(0x29) # Free-fall time
65+
_REG_TAP_AXES: int = const(0x2A) # Axis control for single/double tap
66+
_REG_ACT_TAP_STATUS: int = const(0x2B) # Source for single/double tap
67+
_REG_BW_RATE: int = const(0x2C) # Data rate and power mode control
68+
_REG_POWER_CTL: int = const(0x2D) # Power-saving features control
69+
_REG_INT_ENABLE: int = const(0x2E) # Interrupt enable control
70+
_REG_INT_MAP: int = const(0x2F) # Interrupt mapping control
71+
_REG_INT_SOURCE: int = const(0x30) # Source of interrupts
72+
_REG_DATA_FORMAT: int = const(0x31) # Data format control
5173
_REG_DATAX0: int = const(0x32) # X-axis data 0
5274
_REG_DATAX1: int = const(0x33) # X-axis data 1
5375
_REG_DATAY0: int = const(0x34) # Y-axis data 0
5476
_REG_DATAY1: int = const(0x35) # Y-axis data 1
5577
_REG_DATAZ0: int = const(0x36) # Z-axis data 0
5678
_REG_DATAZ1: int = const(0x37) # Z-axis data 1
79+
_REG_FIFO_CTL: int = const(0x38) # FIFO control
80+
_REG_FIFO_STATUS: int = const(0x39) # FIFO status
81+
_INT_DATA_READY: int = const(0b10000000) # DATA_READY bit
82+
_INT_SINGLE_TAP: int = const(0b01000000) # SINGLE_TAP bit
83+
_INT_DOUBLE_TAP: int = const(0b00100000) # DOUBLE_TAP bit
84+
_INT_ACT: int = const(0b00010000) # ACT bit
85+
_INT_INACT: int = const(0b00001000) # INACT bit
86+
87+
88+
# _INT_FREE_FALL: int = const(0b00000100) # FREE_FALL bit, unused in ADXL375
5789

5890

5991
class DataRate(adafruit_adxl34x.DataRate): # pylint: disable=too-few-public-methods
6092
"""Stub class for data rate."""
6193

6294

63-
class Range(adafruit_adxl34x.Range): # pylint: disable=too-few-public-methods
64-
"""Stub class for range."""
95+
class Range: # pylint: disable=too-few-public-methods
96+
"""An enum-like class representing the possible measurement ranges in +/- G.
97+
98+
Possible values are:
99+
100+
- ``Range.RANGE_200_G``
101+
- ``Range.RANGE_100_G``
102+
- ``Range.RANGE_50_G``
103+
- ``Range.RANGE_25_G``
104+
105+
"""
106+
107+
RANGE_200_G: int = const(0b11) # +/- 200g
108+
RANGE_100_G: int = const(0b10) # +/- 100g
109+
RANGE_50_G: int = const(0b01) # +/- 50g
110+
RANGE_25_G: int = const(0b00) # +/- 25g (default value)
65111

66112

67113
class ADXL375(adafruit_adxl34x.ADXL345):
@@ -114,10 +160,89 @@ def acceleration(self) -> Tuple[int, int, int]:
114160

115161
@property
116162
def range(self) -> int:
117-
"""Range is fixed. Updating the range is not implemented."""
118-
raise NotImplementedError("Range not implemented. ADXL375 is fixed at 200G.")
163+
"""The measurement range of the sensor."""
164+
range_register = self._read_register_unpacked(_REG_DATA_FORMAT)
165+
return range_register & 0x03
119166

120167
@range.setter
121168
def range(self, val: int) -> None:
122-
"""Range is fixed. Updating the range is not implemented."""
123-
raise NotImplementedError("Range not implemented. ADXL375 is fixed at 200G.")
169+
# read the current value of the data format register
170+
format_register = self._read_register_unpacked(_REG_DATA_FORMAT)
171+
172+
# update the range
173+
format_register |= val
174+
175+
# Make sure that the FULL-RES bit is enabled for range scaling
176+
format_register |= 0x08
177+
178+
# write the updated values
179+
self._write_register_byte(_REG_DATA_FORMAT, format_register)
180+
181+
@property
182+
def events(self) -> Dict[str, bool]:
183+
"""
184+
:attr: `events` will return a dictionary with a key for each
185+
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 |
192+
| | or double tap is determined by the tap param of |
193+
| | :meth:`adafruit_adxl34x.enable_tap_detection` |
194+
+------------+----------------------------------------------------------------------------+
195+
| ``motion`` | True if the sensor has seen acceleration above the threshold |
196+
| | set with :meth:`adafruit_adxl34x.enable_motion_detection` |
197+
+------------+----------------------------------------------------------------------------+
198+
| ``data_ready`` | True if the sensor has data to be read. Can be used for more precise |
199+
| | timing if reading many samples. Set with `enable_data_ready_interrupt` |
200+
+------------+----------------------------------------------------------------------------+
201+
202+
203+
"""
204+
205+
interrupt_source_register = self._read_clear_interrupt_source()
206+
207+
self._event_status.clear()
208+
209+
for event_type, value in self._enabled_interrupts.items():
210+
if event_type == "motion":
211+
self._event_status[event_type] = (
212+
interrupt_source_register & _INT_ACT > 0
213+
)
214+
if event_type == "tap":
215+
if value == 1:
216+
self._event_status[event_type] = (
217+
interrupt_source_register & _INT_SINGLE_TAP > 0
218+
)
219+
else:
220+
self._event_status[event_type] = (
221+
interrupt_source_register & _INT_DOUBLE_TAP > 0
222+
)
223+
if event_type == "data_ready":
224+
self._event_status[event_type] = (
225+
interrupt_source_register & _INT_DATA_READY > 0
226+
)
227+
228+
return self._event_status
229+
230+
def enable_data_ready_interrupt(self):
231+
"""
232+
Enable Data Ready interrupt for precise data timing
233+
"""
234+
active_interrupts = self._read_register_unpacked(_REG_INT_ENABLE)
235+
236+
self._write_register_byte(_REG_INT_ENABLE, 0x0) # disable interrupts for setup
237+
238+
# add DATA_READY to the active interrupts and set them to re-enable
239+
active_interrupts |= _INT_DATA_READY
240+
self._write_register_byte(_REG_INT_ENABLE, active_interrupts)
241+
self._enabled_interrupts["data_ready"] = True
242+
243+
def disable_data_ready_interrupt(self) -> None:
244+
"""Disable Data Ready interrupt"""
245+
active_interrupts = self._read_register_unpacked(_REG_INT_ENABLE)
246+
active_interrupts &= ~_INT_DATA_READY
247+
self._write_register_byte(_REG_INT_ENABLE, active_interrupts)
248+
self._enabled_interrupts.pop("data_ready")

docs/conf.py

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
"python": ("https://docs.python.org/3", None),
3535
"BusDevice": ("https://docs.circuitpython.org/projects/busdevice/en/latest/", None),
3636
"CircuitPython": ("https://docs.circuitpython.org/en/latest/", None),
37+
"adafruit_adxl34x": (
38+
"https://docs.circuitpython.org/projects/adxl34x/en/latest/",
39+
None,
40+
),
3741
}
3842

3943
# Show the docstring from both the class and its __init__() method.

docs/examples.rst

+9
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,12 @@ Ensure your device works with this simple test.
66
.. literalinclude:: ../examples/adxl37x_simpletest.py
77
:caption: examples/adxl37x_simpletest.py
88
:linenos:
9+
10+
Data Ready Interrupt
11+
---------------------
12+
13+
Use the Data Ready interrupt for precise data timing.
14+
15+
.. literalinclude:: ../examples/adxl37x_data_ready.py
16+
:caption: examples/adxl37x_data_ready.py
17+
:linenos:

docs/index.rst

+4-1
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,14 @@ Table of Contents
2525
:caption: Tutorials
2626

2727
Adafruit ADXL375 <https://learn.adafruit.com/adafruit-adxl375>
28+
Adafruit ADXL345 - Triple-Axis Accelerometer (+-2g/4g/8g/16g) w/ I2C/SPI Learning Guide <https://learn.adafruit.com/adxl345-digital-accelerometer>
2829

2930
.. toctree::
3031
:caption: Related Products
3132

32-
ADXL375 - High G Accelerometer with I2C - STEMMA QT <https://www.adafruit.com/product/5374>
33+
ADXL345 - Triple-Axis Accelerometer (+-2g/4g/8g/16g) w/ I2C/SPI <https://www.adafruit.com/product/1231>
34+
ADXL375 - High G Accelerometer with I2C - STEMMA QT <https://www.adafruit.com/product/5374>
35+
3336

3437
.. toctree::
3538
:caption: Other Links

examples/adxl37x_data_ready.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# SPDX-FileCopyrightText: 2022 Kattni Rembor for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
3+
4+
import board
5+
import digitalio
6+
import adafruit_adxl37x
7+
8+
i2c = board.STEMMA_I2C() # uses board.SCL and board.SDA
9+
accelerometer = adafruit_adxl37x.ADXL375(i2c)
10+
11+
interrupt = digitalio.DigitalInOut(board.GP3) # Set interrupt dio pin
12+
13+
print("Accelerometer starting...")
14+
accelerometer.data_rate = (
15+
accelerometer.DataRate.RATE_800_HZ
16+
) # Set Data Rate of accelerometer
17+
accelerometer.range = adafruit_adxl37x.Range.RANGE_200_G # Set Full Data Range 200g
18+
accelerometer.enable_data_ready_interrupt() # Enable Data Ready Interrupt
19+
20+
while True:
21+
if interrupt.value:
22+
# ADXL375 interrupt pin stays HIGH until data is read, so simply reading the logic state
23+
# is sufficient instead of having to catch the rising edge.
24+
print("%f %f %f m/s^2" % accelerometer.acceleration)

0 commit comments

Comments
 (0)