Skip to content

Added range and data_ready interrupt parameters #7

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/pycqa/pylint
rev: v2.17.4
rev: v3.2.6
hooks:
- id: pylint
name: pylint (library code)
Expand Down
139 changes: 132 additions & 7 deletions adafruit_adxl37x.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import adafruit_adxl34x

try:
from typing import Tuple, Optional
from typing import Tuple, Optional, Dict

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

_REG_DEVID: int = const(0x00) # Device ID
_REG_THRESH_TAP: int = const(0x1D) # Tap threshold
_REG_OFSX: int = const(0x1E) # X-axis offset
_REG_OFSY: int = const(0x1F) # Y-axis offset
_REG_OFSZ: int = const(0x20) # Z-axis offset
_REG_DUR: int = const(0x21) # Tap duration
_REG_LATENT: int = const(0x22) # Tap latency
_REG_WINDOW: int = const(0x23) # Tap window
_REG_THRESH_ACT: int = const(0x24) # Activity threshold
_REG_THRESH_INACT: int = const(0x25) # Inactivity threshold
_REG_TIME_INACT: int = const(0x26) # Inactivity time
_REG_ACT_INACT_CTL: int = const(0x27) # Axis enable control for [in]activity detection
_REG_THRESH_FF: int = const(0x28) # Free-fall threshold
_REG_TIME_FF: int = const(0x29) # Free-fall time
_REG_TAP_AXES: int = const(0x2A) # Axis control for single/double tap
_REG_ACT_TAP_STATUS: int = const(0x2B) # Source for single/double tap
_REG_BW_RATE: int = const(0x2C) # Data rate and power mode control
_REG_POWER_CTL: int = const(0x2D) # Power-saving features control
_REG_INT_ENABLE: int = const(0x2E) # Interrupt enable control
_REG_INT_MAP: int = const(0x2F) # Interrupt mapping control
_REG_INT_SOURCE: int = const(0x30) # Source of interrupts
_REG_DATA_FORMAT: int = const(0x31) # Data format control
_REG_DATAX0: int = const(0x32) # X-axis data 0
_REG_DATAX1: int = const(0x33) # X-axis data 1
_REG_DATAY0: int = const(0x34) # Y-axis data 0
_REG_DATAY1: int = const(0x35) # Y-axis data 1
_REG_DATAZ0: int = const(0x36) # Z-axis data 0
_REG_DATAZ1: int = const(0x37) # Z-axis data 1
_REG_FIFO_CTL: int = const(0x38) # FIFO control
_REG_FIFO_STATUS: int = const(0x39) # FIFO status
_INT_DATA_READY: int = const(0b10000000) # DATA_READY bit
_INT_SINGLE_TAP: int = const(0b01000000) # SINGLE_TAP bit
_INT_DOUBLE_TAP: int = const(0b00100000) # DOUBLE_TAP bit
_INT_ACT: int = const(0b00010000) # ACT bit
_INT_INACT: int = const(0b00001000) # INACT bit


# _INT_FREE_FALL: int = const(0b00000100) # FREE_FALL bit, unused in ADXL375


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


class Range(adafruit_adxl34x.Range): # pylint: disable=too-few-public-methods
"""Stub class for range."""
class Range: # pylint: disable=too-few-public-methods
"""An enum-like class representing the possible measurement ranges in +/- G.

Possible values are:

- ``Range.RANGE_200_G``
- ``Range.RANGE_100_G``
- ``Range.RANGE_50_G``
- ``Range.RANGE_25_G``

"""

RANGE_200_G: int = const(0b11) # +/- 200g
RANGE_100_G: int = const(0b10) # +/- 100g
RANGE_50_G: int = const(0b01) # +/- 50g
RANGE_25_G: int = const(0b00) # +/- 25g (default value)


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

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

@range.setter
def range(self, val: int) -> None:
"""Range is fixed. Updating the range is not implemented."""
raise NotImplementedError("Range not implemented. ADXL375 is fixed at 200G.")
# read the current value of the data format register
format_register = self._read_register_unpacked(_REG_DATA_FORMAT)

# update the range
format_register |= val

# Make sure that the FULL-RES bit is enabled for range scaling
format_register |= 0x08

# write the updated values
self._write_register_byte(_REG_DATA_FORMAT, format_register)

@property
def events(self) -> Dict[str, bool]:
"""
:attr: `events` will return a dictionary with a key for each
event type that has been enabled.
The possible keys are:

+------------+----------------------------------------------------------------------------+
| Key | Description |
+============+============================================================================+
| ``tap`` | True if a tap was detected recently. Whether it's looking for a single |
| | or double tap is determined by the tap param of |
| | :meth:`adafruit_adxl34x.enable_tap_detection` |
+------------+----------------------------------------------------------------------------+
| ``motion`` | True if the sensor has seen acceleration above the threshold |
| | set with :meth:`adafruit_adxl34x.enable_motion_detection` |
+------------+----------------------------------------------------------------------------+
| ``data_ready`` | True if the sensor has data to be read. Can be used for more precise |
| | timing if reading many samples. Set with `enable_data_ready_interrupt` |
+------------+----------------------------------------------------------------------------+


"""

interrupt_source_register = self._read_clear_interrupt_source()

self._event_status.clear()

for event_type, value in self._enabled_interrupts.items():
if event_type == "motion":
self._event_status[event_type] = (
interrupt_source_register & _INT_ACT > 0
)
if event_type == "tap":
if value == 1:
self._event_status[event_type] = (
interrupt_source_register & _INT_SINGLE_TAP > 0
)
else:
self._event_status[event_type] = (
interrupt_source_register & _INT_DOUBLE_TAP > 0
)
if event_type == "data_ready":
self._event_status[event_type] = (
interrupt_source_register & _INT_DATA_READY > 0
)

return self._event_status

def enable_data_ready_interrupt(self):
"""
Enable Data Ready interrupt for precise data timing
"""
active_interrupts = self._read_register_unpacked(_REG_INT_ENABLE)

self._write_register_byte(_REG_INT_ENABLE, 0x0) # disable interrupts for setup

# add DATA_READY to the active interrupts and set them to re-enable
active_interrupts |= _INT_DATA_READY
self._write_register_byte(_REG_INT_ENABLE, active_interrupts)
self._enabled_interrupts["data_ready"] = True

def disable_data_ready_interrupt(self) -> None:
"""Disable Data Ready interrupt"""
active_interrupts = self._read_register_unpacked(_REG_INT_ENABLE)
active_interrupts &= ~_INT_DATA_READY
self._write_register_byte(_REG_INT_ENABLE, active_interrupts)
self._enabled_interrupts.pop("data_ready")
4 changes: 4 additions & 0 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
"python": ("https://docs.python.org/3", None),
"BusDevice": ("https://docs.circuitpython.org/projects/busdevice/en/latest/", None),
"CircuitPython": ("https://docs.circuitpython.org/en/latest/", None),
"adafruit_adxl34x": (
"https://docs.circuitpython.org/projects/adxl34x/en/latest/",
None,
),
}

# Show the docstring from both the class and its __init__() method.
Expand Down
9 changes: 9 additions & 0 deletions docs/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,12 @@ Ensure your device works with this simple test.
.. literalinclude:: ../examples/adxl37x_simpletest.py
:caption: examples/adxl37x_simpletest.py
:linenos:

Data Ready Interrupt
---------------------

Use the Data Ready interrupt for precise data timing.

.. literalinclude:: ../examples/adxl37x_data_ready.py
:caption: examples/adxl37x_data_ready.py
:linenos:
5 changes: 4 additions & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@ Table of Contents
:caption: Tutorials

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

.. toctree::
:caption: Related Products

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


.. toctree::
:caption: Other Links
Expand Down
24 changes: 24 additions & 0 deletions examples/adxl37x_data_ready.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# SPDX-FileCopyrightText: 2022 Kattni Rembor for Adafruit Industries
# SPDX-License-Identifier: MIT

import board
import digitalio
import adafruit_adxl37x

i2c = board.STEMMA_I2C() # uses board.SCL and board.SDA
accelerometer = adafruit_adxl37x.ADXL375(i2c)

interrupt = digitalio.DigitalInOut(board.GP3) # Set interrupt dio pin

print("Accelerometer starting...")
accelerometer.data_rate = (
accelerometer.DataRate.RATE_800_HZ
) # Set Data Rate of accelerometer
accelerometer.range = adafruit_adxl37x.Range.RANGE_200_G # Set Full Data Range 200g
accelerometer.enable_data_ready_interrupt() # Enable Data Ready Interrupt

while True:
if interrupt.value:
# ADXL375 interrupt pin stays HIGH until data is read, so simply reading the logic state
# is sufficient instead of having to catch the rising edge.
print("%f %f %f m/s^2" % accelerometer.acceleration)