Python Forum
Adafruit LIS3DH coding error
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Adafruit LIS3DH coding error
#1
Hi,
I am very new to coding and am working on a lightsaber for my son using an Adafruit Prop Maker Featherwing board. I've wired everything up and am attempting to run the code but am getting an error in Line 56. (See Below)

54 # Set up accelerometer on I2C bus, 4G range:
55 i2c = busio.I2C(board.SCL, board.SDA)
56 accel = adafruit_lis3dh.LIS3DH_I2C(i2c)
57 accel.range = adafruit_lis3dh.RANGE_4_G

Do I have the wrong library file? (See Below)
import time
import math
from collections import namedtuple
import struct
import digitalio

from micropython import const

__version__ = "0.0.0-auto.0"
__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_LIS3DH.git"

# Register addresses:
_REG_OUTADC1_L = const(0x08)
_REG_WHOAMI = const(0x0F)
_REG_TEMPCFG = const(0x1F)
_REG_CTRL1 = const(0x20)
_REG_CTRL3 = const(0x22)
_REG_CTRL4 = const(0x23)
_REG_CTRL5 = const(0x24)
_REG_OUT_X_L = const(0x28)
_REG_INT1SRC = const(0x31)
_REG_CLICKCFG = const(0x38)
_REG_CLICKSRC = const(0x39)
_REG_CLICKTHS = const(0x3A)
_REG_TIMELIMIT = const(0x3B)
_REG_TIMELATENCY = const(0x3C)
_REG_TIMEWINDOW = const(0x3D)

# Register value constants:
RANGE_16_G = const(0b11)  # +/- 16g
RANGE_8_G = const(0b10)  # +/- 8g
RANGE_4_G = const(0b01)  # +/- 4g
RANGE_2_G = const(0b00)  # +/- 2g (default value)
DATARATE_1344_HZ = const(0b1001)  # 1.344 KHz
DATARATE_400_HZ = const(0b0111)  # 400Hz
DATARATE_200_HZ = const(0b0110)  # 200Hz
DATARATE_100_HZ = const(0b0101)  # 100Hz
DATARATE_50_HZ = const(0b0100)  # 50Hz
DATARATE_25_HZ = const(0b0011)  # 25Hz
DATARATE_10_HZ = const(0b0010)  # 10 Hz
DATARATE_1_HZ = const(0b0001)  # 1 Hz
DATARATE_POWERDOWN = const(0)
DATARATE_LOWPOWER_1K6HZ = const(0b1000)
DATARATE_LOWPOWER_5KHZ = const(0b1001)

# Other constants
STANDARD_GRAVITY = 9.806

# the named tuple returned by the class
AccelerationTuple = namedtuple("acceleration", ("x", "y", "z"))


class LIS3DH:
    """Driver base for the LIS3DH accelerometer."""

    def __init__(self, int1=None, int2=None):
        # Check device ID.
        device_id = self._read_register_byte(_REG_WHOAMI)
        if device_id != 0x33:
            raise RuntimeError("Failed to find LIS3DH!")
        # Reboot
        self._write_register_byte(_REG_CTRL5, 0x80)
        time.sleep(0.01)  # takes 5ms
        # Enable all axes, normal mode.
        self._write_register_byte(_REG_CTRL1, 0x07)
        # Set 400Hz data rate.
        self.data_rate = DATARATE_400_HZ
        # High res & BDU enabled.
        self._write_register_byte(_REG_CTRL4, 0x88)
        # Enable ADCs.
        self._write_register_byte(_REG_TEMPCFG, 0x80)
        # Latch interrupt for INT1
        self._write_register_byte(_REG_CTRL5, 0x08)

        # Initialise interrupt pins
        self._int1 = int1
        self._int2 = int2
        if self._int1:
            self._int1.direction = digitalio.Direction.INPUT
            self._int1.pull = digitalio.Pull.UP

    @property
    def data_rate(self):
        """The data rate of the accelerometer.  Can be DATA_RATE_400_HZ, DATA_RATE_200_HZ,
           DATA_RATE_100_HZ, DATA_RATE_50_HZ, DATA_RATE_25_HZ, DATA_RATE_10_HZ,
           DATA_RATE_1_HZ, DATA_RATE_POWERDOWN, DATA_RATE_LOWPOWER_1K6HZ, or
           DATA_RATE_LOWPOWER_5KHZ."""
        ctl1 = self._read_register_byte(_REG_CTRL1)
        return (ctl1 >> 4) & 0x0F

    @data_rate.setter
    def data_rate(self, rate):
        ctl1 = self._read_register_byte(_REG_CTRL1)
        ctl1 &= ~(0xF0)
        ctl1 |= rate << 4
        self._write_register_byte(_REG_CTRL1, ctl1)

    @property
    def range(self):
        """The range of the accelerometer.  Can be RANGE_2_G, RANGE_4_G, RANGE_8_G, or
           RANGE_16_G."""
        ctl4 = self._read_register_byte(_REG_CTRL4)
        return (ctl4 >> 4) & 0x03

    @range.setter
    def range(self, range_value):
        ctl4 = self._read_register_byte(_REG_CTRL4)
        ctl4 &= ~0x30
        ctl4 |= range_value << 4
        self._write_register_byte(_REG_CTRL4, ctl4)

    @property
    def acceleration(self):
        """The x, y, z acceleration values returned in a 3-tuple and are in m / s ^ 2."""
        divider = 1
        accel_range = self.range
        if accel_range == RANGE_16_G:
            divider = 1365
        elif accel_range == RANGE_8_G:
            divider = 4096
        elif accel_range == RANGE_4_G:
            divider = 8190
        elif accel_range == RANGE_2_G:
            divider = 16380

        x, y, z = struct.unpack("<hhh", self._read_register(_REG_OUT_X_L | 0x80, 6))

        # convert from Gs to m / s ^ 2 and adjust for the range
        x = (x / divider) * STANDARD_GRAVITY
        y = (y / divider) * STANDARD_GRAVITY
        z = (z / divider) * STANDARD_GRAVITY

        return AccelerationTuple(x, y, z)

    def shake(self, shake_threshold=30, avg_count=10, total_delay=0.1):
        """
        Detect when the accelerometer is shaken. Optional parameters:

        :param shake_threshold: Increase or decrease to change shake sensitivity. This
                                requires a minimum value of 10. 10 is the total
                                acceleration if the board is not moving, therefore
                                anything less than 10 will erroneously report a constant
                                shake detected. (Default 30)

        :param avg_count: The number of readings taken and used for the average
                          acceleration. (Default 10)

        :param total_delay: The total time in seconds it takes to obtain avg_count
                            readings from acceleration. (Default 0.1)
         """
        shake_accel = (0, 0, 0)
        for _ in range(avg_count):
            # shake_accel creates a list of tuples from acceleration data.
            # zip takes multiple tuples and zips them together, as in:
            # In : zip([-0.2, 0.0, 9.5], [37.9, 13.5, -72.8])
            # Out: [(-0.2, 37.9), (0.0, 13.5), (9.5, -72.8)]
            # map applies sum to each member of this tuple, resulting in a
            # 3-member list. tuple converts this list into a tuple which is
            # used as shake_accel.
            shake_accel = tuple(map(sum, zip(shake_accel, self.acceleration)))
            time.sleep(total_delay / avg_count)
        avg = tuple(value / avg_count for value in shake_accel)
        total_accel = math.sqrt(sum(map(lambda x: x * x, avg)))
        return total_accel > shake_threshold

    def read_adc_raw(self, adc):
        """Retrieve the raw analog to digital converter value.  ADC must be a
        value 1, 2, or 3.
        """
        if adc < 1 or adc > 3:
            raise ValueError("ADC must be a value 1 to 3!")

        return struct.unpack(
            "<h", self._read_register((_REG_OUTADC1_L + ((adc - 1) * 2)) | 0x80, 2)[0:2]
        )[0]

    def read_adc_mV(self, adc):  # pylint: disable=invalid-name
        """Read the specified analog to digital converter value in millivolts.
        ADC must be a value 1, 2, or 3.  NOTE the ADC can only measure voltages
        in the range of ~900-1200mV!
        """
        raw = self.read_adc_raw(adc)
        # Interpolate between 900mV and 1800mV, see:
        # https://learn.adafruit.com/adafruit-lis3dh-triple-axis-accelerometer-breakout/wiring-and-test#reading-the-3-adc-pins
        # This is a simplified linear interpolation of:
        # return y0 + (x-x0)*((y1-y0)/(x1-x0))
        # Where:
        #   x = ADC value
        #   x0 = -32512
        #   x1 = 32512
        #   y0 = 1800
        #   y1 = 900
        return 1800 + (raw + 32512) * (-900 / 65024)

    @property
    def tapped(self):
        """
        True if a tap was detected recently. Whether its a single tap or double tap is
        determined by the tap param on ``set_tap``. ``tapped`` may be True over
        multiple reads even if only a single tap or single double tap occurred if the
        interrupt (int) pin is not specified.

        The following example uses ``i2c`` and specifies the interrupt pin:

        .. code-block:: python

            import adafruit_lis3dh
            import digitalio

            i2c = busio.I2C(board.SCL, board.SDA)
            int1 = digitalio.DigitalInOut(board.D11) # pin connected to interrupt
            lis3dh = adafruit_lis3dh.LIS3DH_I2C(i2c, int1=int1)
            lis3dh.range = adafruit_lis3dh.RANGE_8_G

        """
        if self._int1 and not self._int1.value:
            return False
        raw = self._read_register_byte(_REG_CLICKSRC)
        return raw & 0x40 > 0

    def set_tap(
        self,
        tap,
        threshold,
        *,
        time_limit=10,
        time_latency=20,
        time_window=255,
        click_cfg=None
    ):
        """
        The tap detection parameters.

        .. note:: Tap related registers are called ``CLICK_`` in the datasheet.

        :param int tap: 0 to disable tap detection, 1 to detect only single
                        taps, and 2 to detect only double taps.

        :param int threshold: A threshold for the tap detection.  The higher the value
                              the less sensitive the detection.  This changes based on
                              the accelerometer range.  Good values are 5-10 for 16G,
                              10-20 for 8G, 20-40 for 4G, and 40-80 for 2G.

        :param int time_limit: TIME_LIMIT register value (default 10).
        :param int time_latency: TIME_LATENCY register value (default 20).
        :param int time_window: TIME_WINDOW register value (default 255).
        :param int click_cfg: CLICK_CFG register value.
        """
        if (tap < 0 or tap > 2) and click_cfg is None:
            raise ValueError(
                "Tap must be 0 (disabled), 1 (single tap), or 2 (double tap)!"
            )
        if threshold > 127 or threshold < 0:
            raise ValueError("Threshold out of range (0-127)")

        ctrl3 = self._read_register_byte(_REG_CTRL3)
        if tap == 0 and click_cfg is None:
            # Disable click interrupt.
            self._write_register_byte(_REG_CTRL3, ctrl3 & ~(0x80))  # Turn off I1_CLICK.
            self._write_register_byte(_REG_CLICKCFG, 0)
            return
        self._write_register_byte(_REG_CTRL3, ctrl3 | 0x80)  # Turn on int1 click output

        if click_cfg is None:
            if tap == 1:
                click_cfg = 0x15  # Turn on all axes & singletap.
            if tap == 2:
                click_cfg = 0x2A  # Turn on all axes & doubletap.
        # Or, if a custom click configuration register value specified, use it.
        self._write_register_byte(_REG_CLICKCFG, click_cfg)
        self._write_register_byte(_REG_CLICKTHS, 0x80 | threshold)
        self._write_register_byte(_REG_TIMELIMIT, time_limit)
        self._write_register_byte(_REG_TIMELATENCY, time_latency)
        self._write_register_byte(_REG_TIMEWINDOW, time_window)

    def _read_register_byte(self, register):
        # Read a byte register value and return it.
        return self._read_register(register, 1)[0]

    def _read_register(self, register, length):
        # Read an arbitrarily long register (specified by length number of
        # bytes) and return a bytearray of the retrieved data.
        # Subclasses MUST implement this!
        raise NotImplementedError

    def _write_register_byte(self, register, value):
        # Write a single byte register at the specified register address.
        # Subclasses MUST implement this!
        raise NotImplementedError


class LIS3DH_I2C(LIS3DH):
    """Driver for the LIS3DH accelerometer connected over I2C."""

    def __init__(self, i2c, *, address=0x18, int1=None, int2=None):
        import adafruit_bus_device.i2c_device as i2c_device  # pylint: disable=import-outside-toplevel

        self._i2c = i2c_device.I2CDevice(i2c, address)
        self._buffer = bytearray(6)
        super().__init__(int1=int1, int2=int2)

    def _read_register(self, register, length):
        self._buffer[0] = register & 0xFF
        with self._i2c as i2c:
            i2c.write(self._buffer, start=0, end=1)
            i2c.readinto(self._buffer, start=0, end=length)
            return self._buffer

    def _write_register_byte(self, register, value):
        self._buffer[0] = register & 0xFF
        self._buffer[1] = value & 0xFF
        with self._i2c as i2c:
            i2c.write(self._buffer, start=0, end=2)


class LIS3DH_SPI(LIS3DH):
    """Driver for the LIS3DH accelerometer connected over SPI."""

    def __init__(self, spi, cs, *, baudrate=100000, int1=None, int2=None):
        import adafruit_bus_device.spi_device as spi_device  # pylint: disable=import-outside-toplevel

        self._spi = spi_device.SPIDevice(spi, cs, baudrate=baudrate)
        self._buffer = bytearray(6)
        super().__init__(int1=int1, int2=int2)

    def _read_register(self, register, length):
        if length == 1:
            self._buffer[0] = (register | 0x80) & 0xFF  # Read single, bit 7 high.
        else:
            self._buffer[0] = (register | 0xC0) & 0xFF  # Read multiple, bit 6&7 high.
        with self._spi as spi:
            spi.write(self._buffer, start=0, end=1)  # pylint: disable=no-member
            spi.readinto(self._buffer, start=0, end=length)  # pylint: disable=no-member
            return self._buffer

    def _write_register_byte(self, register, value):
        self._buffer[0] = register & 0x7F  # Write, bit 7 low.
        self._buffer[1] = value & 0xFF
        with self._spi as spi:
            spi.write(self._buffer, start=0, end=2)  # pylint: disable=no-member
Reply
#2
I can't tell which part is which. Please edit your post to have proper Python tags. See the bbcode page.

Also, include the actual error, not just the line it's from. I can't see if you've shown it.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Coding error. xflyerwdavis 2 528 Oct-07-2023, 07:08 PM
Last Post: deanhystad
  Coding error. Can't open directory EddieG 6 1,127 Jul-13-2023, 06:47 PM
Last Post: deanhystad
  Coding Error EddieG 2 543 Jul-09-2023, 02:59 AM
Last Post: EddieG
  Grid-EYE and Raspberry Pi to adafruit IO JLivingstonsg 0 1,030 Jun-16-2022, 01:23 PM
Last Post: JLivingstonsg
  python coding error isntitzee 1 2,211 Oct-17-2020, 06:30 AM
Last Post: buran
  Coding error- Not sure where I have put error markers against the code that is wrong Username9 1 1,736 Sep-28-2020, 07:57 AM
Last Post: buran
  coding error iro a menu Rollo 2 2,090 Sep-27-2020, 04:17 PM
Last Post: deanhystad
  Coding error- help FatherYeals 3 33,105 Mar-27-2020, 02:11 PM
Last Post: deanhystad
  name undefined Coding Error Ewilliam51 2 2,143 Feb-06-2020, 12:19 AM
Last Post: Ewilliam51
  coding error bilawal 11 5,462 Dec-07-2019, 05:23 PM
Last Post: DreamingInsanity

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020