|
33 | 33 | import adafruit_adxl34x
|
34 | 34 |
|
35 | 35 | try:
|
36 |
| - from typing import Tuple, Optional |
| 36 | + from typing import Tuple, Optional, Dict |
37 | 37 |
|
38 | 38 | # This is only needed for typing
|
39 | 39 | import busio
|
|
48 | 48 | _ADXL347_MULTIPLIER: float = 0.049 # 49mg per lsb
|
49 | 49 | _STANDARD_GRAVITY: float = 9.80665 # earth standard gravity
|
50 | 50 |
|
| 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 |
51 | 73 | _REG_DATAX0: int = const(0x32) # X-axis data 0
|
52 | 74 | _REG_DATAX1: int = const(0x33) # X-axis data 1
|
53 | 75 | _REG_DATAY0: int = const(0x34) # Y-axis data 0
|
54 | 76 | _REG_DATAY1: int = const(0x35) # Y-axis data 1
|
55 | 77 | _REG_DATAZ0: int = const(0x36) # Z-axis data 0
|
56 | 78 | _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 |
57 | 89 |
|
58 | 90 |
|
59 | 91 | class DataRate(adafruit_adxl34x.DataRate): # pylint: disable=too-few-public-methods
|
60 | 92 | """Stub class for data rate."""
|
61 | 93 |
|
62 | 94 |
|
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) |
65 | 111 |
|
66 | 112 |
|
67 | 113 | class ADXL375(adafruit_adxl34x.ADXL345):
|
@@ -114,10 +160,89 @@ def acceleration(self) -> Tuple[int, int, int]:
|
114 | 160 |
|
115 | 161 | @property
|
116 | 162 | 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 |
119 | 166 |
|
120 | 167 | @range.setter
|
121 | 168 | 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") |
0 commit comments