Source code for CB3.kxtj3

import time

"""KXTJ3 Driver - i2c Accelerometer

This module provides high-level functions to access the basic accelerometer features,
and low-level functions to allow access to the full register set for advanced usage.

Many advanced features are available - see `datasheet <https://www.kionix.com/product/KXTJ3-1057>`_
"""


[docs]class KXTJ3: """Device driver for KXTJ3 accelerometer, controlled via i2c bus.""" # Kionix Reserved - 0x00 – 0x05 XOUT_L = 0x06 # R XOUT_H = 0x07 # R YOUT_L = 0x08 # R YOUT_H = 0x09 # R ZOUT_L = 0x0A # R ZOUT_H = 0x0B # R DCST_RESP = 0x0C # R # Kionix Reserved - 0x0D – 0x0E WHO_AM_I = 0x0F # R # Kionix Reserved - 0x10 – 0 x15 INT_SOURCE1 = 0x16 # R INT_SOURCE2 = 0x17 # R STATUS_REG = 0x18 # R # Kionix Reserved - 0x19 INT_REL = 0x1A # R CTRL_REG1 = 0x1B # R/W # Kionix Reserved - 0x1C CTRL_REG2 = 0x1D INT_CTRL_REG1 = 0x1E # R/W INT_CTRL_REG2 = 0x1F # R/W # Kionix Reserved - 0x20 DATA_CTRL_REG = 0x21 # R/W # Kionix Reserved - 0x22 – 0x28 WAKEUP_COUNTER = 0x29 # R/W NA_COUNTER = 0x2A # R/W # Kionix Reserved - 0x2B – 0x39 SELF_TEST = 0x3A # W # Kionix Reserved - 0x3B – 0x69 WAKEUP_THRESHOLD_H = 0x6A # R/W WAKEUP_THRESHOLD_L = 0x6B # R/W # Basic API def __init__(self, i2c, address=0x0E): self._i2c = i2c self._address = address self._buffer1 = bytearray(1) self._buffer2 = bytearray(2) self._buffer6 = bytearray(6) self.reset()
[docs] def read(self): """Read current XYZ axis values and update 'self.orientation' tuple Returns: `tuple` of (x, y, z) axis values. - Default full-scale range is ±2g. - Values are signed 16-bit integer (-32767 to +32768) """ self._read_multiple_registers(KXTJ3.XOUT_L, self._buffer6) x = (self._buffer6[1] << 8) | self._buffer6[0] y = (self._buffer6[3] << 8) | self._buffer6[2] z = (self._buffer6[5] << 8) | self._buffer6[4] x = (x & 0x8000) - (x & 0x7fff) x = -x # to match the CB2 part y = (y & 0x8000) - (y & 0x7fff) z = (z & 0x8000) - (z & 0x7fff) return (x, y, z)
[docs] def dump_axes(self): """Debug - send axis values to stdout""" print("X={}, Y={}, Z={}".format(*self.read()))
# Advanced API
[docs] def verify_id(self): """Verify the part id. Return True if passed.""" return self._read_register(KXTJ3.WHO_AM_I) == 0x35
[docs] def reset(self): """Reset the accelerometer to expected configuration.""" # Go to stand-by mode while we configure the registers self._write_register(KXTJ3.CTRL_REG1, 0) # Software reset # https://kionixfs.azureedge.net/en/document/TN017-Power-On-Procedure.pdf self._write_register(KXTJ3.CTRL_REG2, 0) self._write_register(KXTJ3.CTRL_REG2, 0x80) time.sleep(0.002) # Software Reset Time max # Configure the registers # Stand-by, High-Res, Interrupts-Off, 2g, Wakeup-Disabled self._write_register(KXTJ3.CTRL_REG1, 0b_0_1_0_000_0_0) # self._write_register(KXTJ3.CTRL_REG1 # Nothing to change (we are not using wakeup function) # self._write_register(KXTJ3.INT_CTRL_REG1 # Nothing to change (we are not using interrupts yet) # self._write_register(KXTJ3.INT_CTRL_REG2 # Nothing to change (we are not using interrupts yet) self._write_register(KXTJ3.DATA_CTRL_REG, 0b_0000_0110) # 800Hz # self._write_register(KXTJ3.WAKEUP_COUNTER # Nothing to change (we are not using wakeup function) # self._write_register(KXTJ3.NA_COUNTER # Nothing to change (we are not using wakeup function) # self._write_register(KXTJ3.WAKEUP_THRESHOLD_H # Nothing to change (we are not using wakeup function) # self._write_register(KXTJ3.WAKEUP_THRESHOLD_L # Nothing to change (we are not using wakeup function) # Back to operational mode # Stand-by, High-Res, Interrupts-Off, 2g, Wakeup-Disabled self._write_register(KXTJ3.CTRL_REG1, 0b_1_1_0_000_0_0)
def _write_register(self, reg, value): """Write 8-bit register""" self._i2c.try_lock() try: self._buffer2[0] = reg self._buffer2[1] = value self._i2c.writeto(self._address, self._buffer2) finally: self._i2c.unlock() def _read_register(self, reg): """Read 8-bit register""" self._i2c.try_lock() try: self._buffer1[0] = reg self._i2c.writeto_then_readfrom(self._address, self._buffer1, self._buffer1) return self._buffer1[0] finally: self._i2c.unlock() def _read_multiple_registers(self, start, buffer): """Read several registers at once""" self._i2c.try_lock() try: self._buffer1[0] = start self._i2c.writeto_then_readfrom(self._address, self._buffer1, buffer) finally: self._i2c.unlock()
[docs] def self_test(self): """Run self-test. Return True if passed""" # Get the "normal" readings normal_values = self.read() reg1 = self._read_register(KXTJ3.CTRL_REG1) # To stand-by mode self._write_register(KXTJ3.CTRL_REG1, reg1 & 0x7F) # Turn on test deflection self._write_register(KXTJ3.SELF_TEST, 0xCA) # Back to operation mode self._write_register(KXTJ3.CTRL_REG1, reg1 | 0x80) # Get the "testing" readings test_values = self.read() # Back to stand-by mode self._write_register(KXTJ3.CTRL_REG1, reg1 & 0x7F) # Turn off test deflection self._write_register(KXTJ3.SELF_TEST, 0x00) # Back to operation mode self._write_register(KXTJ3.CTRL_REG1, reg1 | 0x80) # Typical deflection is 0.5g. With our 2g config, we get # 32K/2 = 16K for 1g. Half a g is thus 8K. # Remember, we flipped X. # Check that the axes changed between 4096 and 12288 (8K +- 4K) deflections = (abs(test_values[0]-normal_values[0]), abs(-test_values[1]+normal_values[1]), abs(test_values[2]-normal_values[2])) for d in deflections: if d < 4096 or d >= 12288: return False return True