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)
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