diff --git a/.python-version b/.python-version
new file mode 100644
index 0000000..aaf18d2
--- /dev/null
+++ b/.python-version
@@ -0,0 +1 @@
+3.7.5
diff --git a/LICENSE b/LICENSE
index 6b323f4..b630ac0 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2019 Bryan Siepert for Adafruit Industries
+Copyright (c) 2020 Bryan Siepert for Adafruit Industries
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/README.rst b/README.rst
index a2178f7..71a091d 100644
--- a/README.rst
+++ b/README.rst
@@ -9,11 +9,11 @@ Introduction
:target: https://discord.gg/nBQh6qu
:alt: Discord
-.. image:: https://github.com/adafruit/Adafruit_CircuitPython_ICM20649/workflows/Build%20CI/badge.svg
- :target: https://github.com/adafruit/Adafruit_CircuitPython_ICM20649/actions
+.. image:: https://github.com/adafruit/Adafruit_CircuitPython_ICM20X/workflows/Build%20CI/badge.svg
+ :target: https://github.com/adafruit/Adafruit_CircuitPython_ICM20X/actions
:alt: Build Status
-Library for the ST ICM-20649 Wide-Range 6-DoF Accelerometer and Gyro
+Library for the ST ICM-20X Wide-Range 6-DoF Accelerometer and Gyro Family
Dependencies
@@ -32,17 +32,17 @@ Installing from PyPI
=====================
On supported GNU/Linux systems like the Raspberry Pi, you can install the driver locally `from
-PyPI `_. To install for current user:
+PyPI `_. To install for current user:
.. code-block:: shell
- pip3 install adafruit-circuitpython-icm20649
+ pip3 install adafruit-circuitpython-icm20x
To install system-wide (this may be required in some cases):
.. code-block:: shell
- sudo pip3 install adafruit-circuitpython-icm20649
+ sudo pip3 install adafruit-circuitpython-icm20x
To install in a virtual environment in your current project:
@@ -51,23 +51,45 @@ To install in a virtual environment in your current project:
mkdir project-name && cd project-name
python3 -m venv .env
source .env/bin/activate
- pip3 install adafruit-circuitpython-icm20649
+ pip3 install adafruit-circuitpython-icm20x
Usage Example
=============
-.. code-block: python3
+For use with the ICM20649:
+
+.. code-block:: python3
+
+ import time
+ import board
+ import busio
+ import adafruit_icm20x
+
+ i2c = busio.I2C(board.SCL, board.SDA)
+ icm = adafruit_icm20x.ICM20649(i2c)
+
+ while True:
+ print("Acceleration: X:%.2f, Y: %.2f, Z: %.2f m/s^2" % (icm.acceleration))
+ print("Gyro X:%.2f, Y: %.2f, Z: %.2f rads/s" % (icm.gyro))
+ print("")
+ time.sleep(0.5)
+
+For use with the ICM20948:
+
+.. code-block:: python3
+
import time
import board
import busio
- import adafruit_icm20649
+ import adafruit_icm20x
i2c = busio.I2C(board.SCL, board.SDA)
- icm = adafruit_icm20649.ICM20649(i2c)
+ icm = adafruit_icm20x.ICM20948(i2c)
while True:
- print("Acceleration: X:%.2f, Y: %.2f, Z: %.2f m/s^2"%(icm.acceleration))
- print("Gyro X:%.2f, Y: %.2f, Z: %.2f degrees/s"%(icm.gyro))
+ print("Acceleration: X:%.2f, Y: %.2f, Z: %.2f m/s^2" % (icm.acceleration))
+ print("Gyro X:%.2f, Y: %.2f, Z: %.2f rads/s" % (icm.gyro))
+ print("Magnetometer X:%.2f, Y: %.2f, Z: %.2f uT" % (icm.magnetic))
print("")
time.sleep(0.5)
@@ -75,7 +97,7 @@ Contributing
============
Contributions are welcome! Please read our `Code of Conduct
-`_
+`_
before contributing to help this project stay welcoming.
Documentation
diff --git a/adafruit_icm20649.py b/adafruit_icm20649.py
deleted file mode 100644
index 36f6ebd..0000000
--- a/adafruit_icm20649.py
+++ /dev/null
@@ -1,345 +0,0 @@
-# The MIT License (MIT)
-#
-# Copyright (c) 2019 Bryan Siepert for Adafruit Industries
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-"""
-`adafruit_icm20649`
-================================================================================
-
-Library for the ST ICM20649 Wide-Range 6-DoF Accelerometer and Gyro
-
-* Author(s): Bryan Siepert
-
-Implementation Notes
---------------------
-
-**Hardware:**
-
-* Adafruit's ICM20649 Breakout: https://adafruit.com/product/4464
-
-**Software and Dependencies:**
-
-* Adafruit CircuitPython firmware for the supported boards:
- https://circuitpython.org/downloads
-
-
-* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
-* Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
-"""
-
-__version__ = "0.0.0-auto.0"
-__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ICM20649.git"
-# Common imports; remove if unused or pylint will complain
-from time import sleep
-import adafruit_bus_device.i2c_device as i2c_device
-
-from adafruit_register.i2c_struct import UnaryStruct, ROUnaryStruct, Struct
-from adafruit_register.i2c_bit import RWBit
-from adafruit_register.i2c_bits import RWBits
-
-# pylint: disable=bad-whitespace
-_ICM20649_DEFAULT_ADDRESS = 0x68 # icm20649 default i2c address
-_ICM20649_DEVICE_ID = 0xE1 # Correct context of WHO_AM_I register
-
-# Bank 0
-_ICM20649_WHO_AM_I = 0x00 # device_id register
-_ICM20649_REG_BANK_SEL = 0x7F # register bank selection register
-_ICM20649_PWR_MGMT_1 = 0x06 # primary power management register
-_ICM20649_ACCEL_XOUT_H = 0x2D # first byte of accel data
-_ICM20649_GYRO_XOUT_H = 0x33 # first byte of accel data
-
-# Bank 2
-_ICM20649_GYRO_SMPLRT_DIV = 0x00
-_ICM20649_GYRO_CONFIG_1 = 0x01
-_ICM20649_ACCEL_SMPLRT_DIV_1 = 0x10
-_ICM20649_ACCEL_SMPLRT_DIV_2 = 0x11
-_ICM20649_ACCEL_CONFIG_1 = 0x14
-
-
-G_TO_ACCEL = 9.80665
-# pylint: enable=bad-whitespace
-class CV:
- """struct helper"""
-
- @classmethod
- def add_values(cls, value_tuples):
- """Add CV values to the class"""
- cls.string = {}
- cls.lsb = {}
-
- for value_tuple in value_tuples:
- name, value, string, lsb = value_tuple
- setattr(cls, name, value)
- cls.string[value] = string
- cls.lsb[value] = lsb
-
- @classmethod
- def is_valid(cls, value):
- """Validate that a given value is a member"""
- return value in cls.string
-
-
-class AccelRange(CV):
- """Options for ``accelerometer_range``"""
-
- pass # pylint: disable=unnecessary-pass
-
-
-AccelRange.add_values(
- (
- ("RANGE_4G", 0, 4, 8192),
- ("RANGE_8G", 1, 8, 4096.0),
- ("RANGE_16G", 2, 16, 2048),
- ("RANGE_30G", 3, 30, 1024),
- )
-)
-
-
-class GyroRange(CV):
- """Options for ``gyro_data_range``"""
-
- pass # pylint: disable=unnecessary-pass
-
-
-GyroRange.add_values(
- (
- ("RANGE_500_DPS", 0, 500, 65.5),
- ("RANGE_1000_DPS", 1, 1000, 32.8),
- ("RANGE_2000_DPS", 2, 2000, 16.4),
- ("RANGE_4000_DPS", 3, 4000, 8.2),
- )
-)
-
-
-class ICM20649: # pylint:disable=too-many-instance-attributes
- """Library for the ST ICM-20649 Wide-Range 6-DoF Accelerometer and Gyro.
-
- :param ~busio.I2C i2c_bus: The I2C bus the ICM20649 is connected to.
- :param address: The I2C slave address of the sensor
-
- """
-
- # Bank 0
- _device_id = ROUnaryStruct(_ICM20649_WHO_AM_I, "hhh")
- _raw_gyro_data = Struct(_ICM20649_GYRO_XOUT_H, ">hhh")
-
- # Bank 2
- _gyro_range = RWBits(2, _ICM20649_GYRO_CONFIG_1, 1)
- _accel_dlpf_enable = RWBits(1, _ICM20649_ACCEL_CONFIG_1, 0)
- _accel_range = RWBits(2, _ICM20649_ACCEL_CONFIG_1, 1)
- _accel_dlpf_config = RWBits(3, _ICM20649_ACCEL_CONFIG_1, 3)
-
- # this value is a 12-bit register spread across two bytes, big-endian first
- _accel_rate_divisor = UnaryStruct(_ICM20649_ACCEL_SMPLRT_DIV_1, ">H")
-
- _gyro_rate_divisor = UnaryStruct(_ICM20649_GYRO_SMPLRT_DIV, ">B")
-
- def __init__(self, i2c_bus, address=_ICM20649_DEFAULT_ADDRESS):
- self.i2c_device = i2c_device.I2CDevice(i2c_bus, address)
- if self._device_id != _ICM20649_DEVICE_ID:
- raise RuntimeError("Failed to find ICM20649 - check your wiring!")
- self.reset()
-
- self._bank = 0
- self._sleep = False
-
- self._bank = 2
- self._accel_range = AccelRange.RANGE_8G # pylint: disable=no-member
- self._cached_accel_range = self._accel_range
-
- # TODO: CV-ify
- self._accel_dlpf_config = 3
-
- # 1.125 kHz/(1+ACCEL_SMPLRT_DIV[11:0]),
- # 1125Hz/(1+20) = 53.57Hz
- self._accel_rate_divisor = 20
-
- # writeByte(ICM20649_ADDR,GYRO_CONFIG_1, gyroConfig);
- self._gyro_range = GyroRange.RANGE_500_DPS # pylint: disable=no-member
- sleep(0.100)
- self._cached_gyro_range = self._gyro_range
-
- # //ORD = 1100Hz/(1+10) = 100Hz
- self._gyro_rate_divisor = 0x0A
-
- # //reset to register bank 0
- self._bank = 0
-
- def reset(self):
- """Resets the internal registers and restores the default settings"""
- self._reset = True
- while self._reset:
- sleep(0.001)
-
- @property
- def acceleration(self):
- """The x, y, z acceleration values returned in a 3-tuple and are in m / s ^ 2."""
- raw_accel_data = self._raw_accel_data
-
- x = self._scale_xl_data(raw_accel_data[0])
- y = self._scale_xl_data(raw_accel_data[1])
- z = self._scale_xl_data(raw_accel_data[2])
-
- return (x, y, z)
-
- @property
- def gyro(self):
- """The x, y, z angular velocity values returned in a 3-tuple and are in degrees / second"""
- raw_gyro_data = self._raw_gyro_data
- x = self._scale_gyro_data(raw_gyro_data[0])
- y = self._scale_gyro_data(raw_gyro_data[1])
- z = self._scale_gyro_data(raw_gyro_data[2])
-
- return (x, y, z)
-
- def _scale_xl_data(self, raw_measurement):
- return raw_measurement / AccelRange.lsb[self._cached_accel_range] * G_TO_ACCEL
-
- def _scale_gyro_data(self, raw_measurement):
- return raw_measurement / GyroRange.lsb[self._cached_gyro_range]
-
- @property
- def accelerometer_range(self):
- """Adjusts the range of values that the sensor can measure, from +/- 4G to +/-30G
- Note that larger ranges will be less accurate. Must be an `AccelRange`"""
- return self._cached_accel_range
-
- @accelerometer_range.setter
- def accelerometer_range(self, value): # pylint: disable=no-member
- if not AccelRange.is_valid(value):
- raise AttributeError("range must be an `AccelRange`")
- self._bank = 2
- self._accel_range = value
- self._cached_accel_range = value
- self._bank = 0
-
- @property
- def gyro_range(self):
- """Adjusts the range of values that the sensor can measure, from 500 Degrees/second to 4000
- degrees/s. Note that larger ranges will be less accurate. Must be a `GyroRange`"""
- return self._cached_gyro_range
-
- @gyro_range.setter
- def gyro_range(self, value):
- if not GyroRange.is_valid(value):
- raise AttributeError("range must be a `GyroRange`")
-
- self._bank = 2
- self._gyro_range = value
- self._cached_gyro_range = value
- self._bank = 0
- sleep(0.100) # needed to let new range settle
-
- @property
- def accelerometer_data_rate_divisor(self):
- """The divisor for the rate at which accelerometer measurements are taken in Hz
-
- Note: The data rates are set indirectly by setting a rate divisor according to the
- following formula: ``accelerometer_data_rate = 1125/(1+divisor)``
-
- This function sets the raw rate divisor.
-"""
- self._bank = 2
- raw_rate_divisor = self._accel_rate_divisor
- self._bank = 0
- # rate_hz = 1125/(1+raw_rate_divisor)
- return raw_rate_divisor
-
- @accelerometer_data_rate_divisor.setter
- def accelerometer_data_rate_divisor(self, value):
- # check that value <= 4095
- self._bank = 2
- self._accel_rate_divisor = value
- self._bank = 0
-
- @property
- def gyro_data_rate_divisor(self):
- """The divisor for the rate at which gyro measurements are taken in Hz
-
- Note: The data rates are set indirectly by setting a rate divisor according to the
- following formula: ``gyro_data_rate = 1100/(1+divisor)``
-
- This function sets the raw rate divisor.
- """
-
- self._bank = 2
- raw_rate_divisor = self._gyro_rate_divisor
- self._bank = 0
- # rate_hz = 1100/(1+raw_rate_divisor)
- return raw_rate_divisor
-
- @gyro_data_rate_divisor.setter
- def gyro_data_rate_divisor(self, value):
- # check that value <= 255
- self._bank = 2
- self._gyro_rate_divisor = value
- self._bank = 0
-
- def _accel_rate_calc(self, divisor): # pylint:disable=no-self-use
- return 1125 / (1 + divisor)
-
- def _gyro_rate_calc(self, divisor): # pylint:disable=no-self-use
- return 1100 / (1 + divisor)
-
- @property
- def accelerometer_data_rate(self):
- """The rate at which accelerometer measurements are taken in Hz
-
- Note: The data rates are set indirectly by setting a rate divisor according to the
- following formula: ``accelerometer_data_rate = 1125/(1+divisor)``
-
- This function does the math to find the divisor from a given rate but it will not be
- exactly as specified.
- """
- return self._accel_rate_calc(self.accelerometer_data_rate_divisor)
-
- @accelerometer_data_rate.setter
- def accelerometer_data_rate(self, value):
- if value < self._accel_rate_calc(4095) or value > self._accel_rate_calc(0):
- raise AttributeError(
- "Accelerometer data rate must be between 0.27 and 1125.0"
- )
- self.accelerometer_data_rate_divisor = value
-
- @property
- def gyro_data_rate(self):
- """The rate at which gyro measurements are taken in Hz
-
- Note: The data rates are set indirectly by setting a rate divisor according to the
- following formula: ``gyro_data_rate = 1100/(1+divisor)``
-
- This function does the math to find the divisor from a given rate but it will not
- be exactly as specified.
- """
- return self._gyro_rate_calc(self.gyro_data_rate_divisor)
-
- @gyro_data_rate.setter
- def gyro_data_rate(self, value):
- if value < self._gyro_rate_calc(4095) or value > self._gyro_rate_calc(0):
- raise AttributeError("Gyro data rate must be between 4.30 and 1100.0")
-
- divisor = round(((1125.0 - value) / value))
- self.gyro_data_rate_divisor = divisor
diff --git a/adafruit_icm20x.py b/adafruit_icm20x.py
new file mode 100644
index 0000000..e595b41
--- /dev/null
+++ b/adafruit_icm20x.py
@@ -0,0 +1,761 @@
+# The MIT License (MIT)
+#
+# Copyright (c) 2020 Bryan Siepert for Adafruit Industries
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+"""
+`adafruit_icm20x`
+================================================================================
+
+Library for the ST ICM20X Motion Sensor Family
+
+* Author(s): Bryan Siepert
+
+Implementation Notes
+--------------------
+
+**Hardware:**
+
+* Adafruit's ICM20649 Breakout: https://adafruit.com/product/4464
+* Adafruit's ICM20948 Breakout: https://adafruit.com/product/4554
+
+**Software and Dependencies:**
+
+* Adafruit CircuitPython firmware for the supported boards:
+ https://circuitpython.org/downloads
+
+
+* Adafruit's Bus Device library: https://github.com/adafruit/Adafruit_CircuitPython_BusDevice
+* Adafruit's Register library: https://github.com/adafruit/Adafruit_CircuitPython_Register
+"""
+
+__version__ = "0.0.0-auto.0"
+__repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_ICM20X.git"
+# Common imports; remove if unused or pylint will complain
+from time import sleep
+import adafruit_bus_device.i2c_device as i2c_device
+
+from adafruit_register.i2c_struct import UnaryStruct, ROUnaryStruct, Struct
+from adafruit_register.i2c_bit import RWBit, ROBit
+from adafruit_register.i2c_bits import RWBits
+
+# pylint: disable=bad-whitespace
+_ICM20649_DEFAULT_ADDRESS = 0x68 # icm20649 default i2c address
+_ICM20948_DEFAULT_ADDRESS = 0x69 # icm20649 default i2c address
+_ICM20649_DEVICE_ID = 0xE1 # Correct content of WHO_AM_I register
+_ICM20948_DEVICE_ID = 0xEA # Correct content of WHO_AM_I register
+
+# Functions using these bank-specific registers are responsible for ensuring
+# that the correct bank is set
+# Bank 0
+_ICM20X_WHO_AM_I = 0x00 # device_id register
+_ICM20X_REG_BANK_SEL = 0x7F # register bank selection register
+_ICM20X_PWR_MGMT_1 = 0x06 # primary power management register
+_ICM20X_ACCEL_XOUT_H = 0x2D # first byte of accel data
+_ICM20X_GYRO_XOUT_H = 0x33 # first byte of accel data
+_ICM20X_I2C_MST_STATUS = 0x17 # I2C Master Status bits
+_ICM20948_EXT_SLV_SENS_DATA_00 = 0x3B
+
+_ICM20X_USER_CTRL = 0x03 # User Control Reg. Includes I2C Master
+_ICM20X_LP_CONFIG = 0x05 # Low Power config
+_ICM20X_REG_INT_PIN_CFG = 0xF # Interrupt config register
+_ICM20X_REG_INT_ENABLE_0 = 0x10 # Interrupt enable register 0
+_ICM20X_REG_INT_ENABLE_1 = 0x11 # Interrupt enable register 1
+
+# Bank 2
+_ICM20X_GYRO_SMPLRT_DIV = 0x00
+_ICM20X_GYRO_CONFIG_1 = 0x01
+_ICM20X_ACCEL_SMPLRT_DIV_1 = 0x10
+_ICM20X_ACCEL_SMPLRT_DIV_2 = 0x11
+_ICM20X_ACCEL_CONFIG_1 = 0x14
+
+
+# Bank 3
+
+_ICM20X_I2C_MST_ODR_CONFIG = 0x0 # Sets ODR for I2C master bus
+_ICM20X_I2C_MST_CTRL = 0x1 # I2C master bus config
+_ICM20X_I2C_MST_DELAY_CTRL = 0x2 # I2C master bus config
+_ICM20X_I2C_SLV0_ADDR = 0x3 # Sets I2C address for I2C master bus slave 0
+_ICM20X_I2C_SLV0_REG = 0x4 # Sets register address for I2C master bus slave 0
+_ICM20X_I2C_SLV0_CTRL = 0x5 # Controls for I2C master bus slave 0
+_ICM20X_I2C_SLV0_DO = 0x6 # Sets I2C master bus slave 0 data out
+
+_ICM20X_I2C_SLV4_ADDR = 0x13 # Sets I2C address for I2C master bus slave 4
+_ICM20X_I2C_SLV4_REG = 0x14 # Sets register address for I2C master bus slave 4
+_ICM20X_I2C_SLV4_CTRL = 0x15 # Controls for I2C master bus slave 4
+_ICM20X_I2C_SLV4_DO = 0x16 # Sets I2C master bus slave 4 data out
+_ICM20X_I2C_SLV4_DI = 0x17 # Sets I2C master bus slave 4 data in
+
+_ICM20X_UT_PER_LSB = 0.15 # mag data LSB value (fixed)
+_ICM20X_RAD_PER_DEG = 0.017453293 # Degrees/s to rad/s multiplier
+
+G_TO_ACCEL = 9.80665
+# pylint: enable=bad-whitespace
+class CV:
+ """struct helper"""
+
+ @classmethod
+ def add_values(cls, value_tuples):
+ """Add CV values to the class"""
+ cls.string = {}
+ cls.lsb = {}
+
+ for value_tuple in value_tuples:
+ name, value, string, lsb = value_tuple
+ setattr(cls, name, value)
+ cls.string[value] = string
+ cls.lsb[value] = lsb
+
+ @classmethod
+ def is_valid(cls, value):
+ """Validate that a given value is a member"""
+ return value in cls.string
+
+
+class AccelRange(CV):
+ """Options for ``accelerometer_range``"""
+
+ pass # pylint: disable=unnecessary-pass
+
+
+class GyroRange(CV):
+ """Options for ``gyro_data_range``"""
+
+ pass # pylint: disable=unnecessary-pass
+
+
+class GyroDLPFFreq(CV):
+ """Options for ``gyro_dlpf_cutoff``"""
+
+ pass # pylint: disable=unnecessary-pass
+
+
+class AccelDLPFFreq(CV):
+ """Options for ``accel_dlpf_cutoff``"""
+
+ pass # pylint: disable=unnecessary-pass
+
+
+class ICM20X: # pylint:disable=too-many-instance-attributes
+ """Library for the ST ICM-20X Wide-Range 6-DoF Accelerometer and Gyro Family
+
+
+ :param ~busio.I2C i2c_bus: The I2C bus the ICM20X is connected to.
+ :param address: The I2C slave address of the sensor
+
+ """
+
+ # Bank 0
+ _device_id = ROUnaryStruct(_ICM20X_WHO_AM_I, ">B")
+ _bank_reg = UnaryStruct(_ICM20X_REG_BANK_SEL, ">B")
+ _reset = RWBit(_ICM20X_PWR_MGMT_1, 7)
+ _sleep_reg = RWBit(_ICM20X_PWR_MGMT_1, 6)
+ _low_power_en = RWBit(_ICM20X_PWR_MGMT_1, 5)
+ _clock_source = RWBits(3, _ICM20X_PWR_MGMT_1, 0)
+
+ _raw_accel_data = Struct(_ICM20X_ACCEL_XOUT_H, ">hhh") # ds says LE :|
+ _raw_gyro_data = Struct(_ICM20X_GYRO_XOUT_H, ">hhh")
+
+ _lp_config_reg = UnaryStruct(_ICM20X_LP_CONFIG, ">B")
+
+ _i2c_master_cycle_en = RWBit(_ICM20X_LP_CONFIG, 6)
+ _accel_cycle_en = RWBit(_ICM20X_LP_CONFIG, 5)
+ _gyro_cycle_en = RWBit(_ICM20X_LP_CONFIG, 4)
+
+ # Bank 2
+ _gyro_dlpf_enable = RWBits(1, _ICM20X_GYRO_CONFIG_1, 0)
+ _gyro_range = RWBits(2, _ICM20X_GYRO_CONFIG_1, 1)
+ _gyro_dlpf_config = RWBits(3, _ICM20X_GYRO_CONFIG_1, 3)
+
+ _accel_dlpf_enable = RWBits(1, _ICM20X_ACCEL_CONFIG_1, 0)
+ _accel_range = RWBits(2, _ICM20X_ACCEL_CONFIG_1, 1)
+ _accel_dlpf_config = RWBits(3, _ICM20X_ACCEL_CONFIG_1, 3)
+
+ # this value is a 12-bit register spread across two bytes, big-endian first
+ _accel_rate_divisor = UnaryStruct(_ICM20X_ACCEL_SMPLRT_DIV_1, ">H")
+ _gyro_rate_divisor = UnaryStruct(_ICM20X_GYRO_SMPLRT_DIV, ">B")
+ AccelDLPFFreq.add_values(
+ (
+ (
+ "DISABLED",
+ -1,
+ "Disabled",
+ None,
+ ), # magical value that we will use do disable
+ ("FREQ_246_0HZ_3DB", 1, 246.0, None),
+ ("FREQ_111_4HZ_3DB", 2, 111.4, None),
+ ("FREQ_50_4HZ_3DB", 3, 50.4, None),
+ ("FREQ_23_9HZ_3DB", 4, 23.9, None),
+ ("FREQ_11_5HZ_3DB", 5, 11.5, None),
+ ("FREQ_5_7HZ_3DB", 6, 5.7, None),
+ ("FREQ_473HZ_3DB", 7, 473, None),
+ )
+ )
+ GyroDLPFFreq.add_values(
+ (
+ (
+ "DISABLED",
+ -1,
+ "Disabled",
+ None,
+ ), # magical value that we will use do disable
+ ("FREQ_196_6HZ_3DB", 0, 196.6, None),
+ ("FREQ_151_8HZ_3DB", 1, 151.8, None),
+ ("FREQ_119_5HZ_3DB", 2, 119.5, None),
+ ("FREQ_51_2HZ_3DB", 3, 51.2, None),
+ ("FREQ_23_9HZ_3DB", 4, 23.9, None),
+ ("FREQ_11_6HZ_3DB", 5, 11.6, None),
+ ("FREQ_5_7HZ_3DB", 6, 5.7, None),
+ ("FREQ_361_4HZ_3DB", 7, 361.4, None),
+ )
+ )
+
+ @property
+ def _bank(self):
+ return self._bank_reg >> 4
+
+ @_bank.setter
+ def _bank(self, value):
+ self._bank_reg = value << 4
+
+ def __init__(self, i2c_bus, address):
+
+ self.i2c_device = i2c_device.I2CDevice(i2c_bus, address)
+ self._bank = 0
+ if not self._device_id in [_ICM20649_DEVICE_ID, _ICM20948_DEVICE_ID]:
+ raise RuntimeError("Failed to find an ICM20X sensor - check your wiring!")
+ self.reset()
+ self.initialize()
+
+ def initialize(self):
+ """Configure the sensors with the default settings. For use after calling `reset()`"""
+
+ self._sleep = False
+ self.accelerometer_range = AccelRange.RANGE_8G # pylint: disable=no-member
+ self.gyro_range = GyroRange.RANGE_500_DPS # pylint: disable=no-member
+
+ self.accelerometer_data_rate_divisor = 20 # ~53.57Hz
+ self.gyro_data_rate_divisor = 10 # ~100Hz
+
+ def reset(self):
+ """Resets the internal registers and restores the default settings"""
+ self._bank = 0
+
+ sleep(0.005)
+ self._reset = True
+ sleep(0.005)
+ while self._reset:
+ sleep(0.005)
+
+ @property
+ def _sleep(self):
+ self._bank = 0
+ sleep(0.005)
+ self._sleep_reg = False
+ sleep(0.005)
+
+ @_sleep.setter
+ def _sleep(self, sleep_enabled):
+ self._bank = 0
+ sleep(0.005)
+ self._sleep_reg = sleep_enabled
+ sleep(0.005)
+
+ @property
+ def acceleration(self):
+ """The x, y, z acceleration values returned in a 3-tuple and are in m / s ^ 2."""
+ self._bank = 0
+ raw_accel_data = self._raw_accel_data
+ sleep(0.005)
+
+ x = self._scale_xl_data(raw_accel_data[0])
+ y = self._scale_xl_data(raw_accel_data[1])
+ z = self._scale_xl_data(raw_accel_data[2])
+
+ return (x, y, z)
+
+ @property
+ def gyro(self):
+ """The x, y, z angular velocity values returned in a 3-tuple and are in degrees / second"""
+ self._bank = 0
+ raw_gyro_data = self._raw_gyro_data
+ x = self._scale_gyro_data(raw_gyro_data[0])
+ y = self._scale_gyro_data(raw_gyro_data[1])
+ z = self._scale_gyro_data(raw_gyro_data[2])
+
+ return (x, y, z)
+
+ def _scale_xl_data(self, raw_measurement):
+ sleep(0.005)
+ return raw_measurement / AccelRange.lsb[self._cached_accel_range] * G_TO_ACCEL
+
+ def _scale_gyro_data(self, raw_measurement):
+ return (
+ raw_measurement / GyroRange.lsb[self._cached_gyro_range]
+ ) * _ICM20X_RAD_PER_DEG
+
+ @property
+ def accelerometer_range(self):
+ """Adjusts the range of values that the sensor can measure, from +/- 4G to +/-30G
+ Note that larger ranges will be less accurate. Must be an `AccelRange`"""
+ return self._cached_accel_range
+
+ @accelerometer_range.setter
+ def accelerometer_range(self, value): # pylint: disable=no-member
+ if not AccelRange.is_valid(value):
+ raise AttributeError("range must be an `AccelRange`")
+ self._bank = 2
+ sleep(0.005)
+ self._accel_range = value
+ sleep(0.005)
+ self._cached_accel_range = value
+ self._bank = 0
+
+ @property
+ def gyro_range(self):
+ """Adjusts the range of values that the sensor can measure, from 500 Degrees/second to 4000
+ degrees/s. Note that larger ranges will be less accurate. Must be a `GyroRange`"""
+ return self._cached_gyro_range
+
+ @gyro_range.setter
+ def gyro_range(self, value):
+ if not GyroRange.is_valid(value):
+ raise AttributeError("range must be a `GyroRange`")
+
+ self._bank = 2
+ sleep(0.005)
+ self._gyro_range = value
+ sleep(0.005)
+ self._cached_gyro_range = value
+ self._bank = 0
+ sleep(0.100) # needed to let new range settle
+
+ @property
+ def accelerometer_data_rate_divisor(self):
+ """The divisor for the rate at which accelerometer measurements are taken in Hz
+
+ Note: The data rates are set indirectly by setting a rate divisor according to the
+ following formula: ``accelerometer_data_rate = 1125/(1+divisor)``
+
+ This function sets the raw rate divisor.
+ """
+ self._bank = 2
+ raw_rate_divisor = self._accel_rate_divisor
+ sleep(0.005)
+ self._bank = 0
+ # rate_hz = 1125/(1+raw_rate_divisor)
+ return raw_rate_divisor
+
+ @accelerometer_data_rate_divisor.setter
+ def accelerometer_data_rate_divisor(self, value):
+ # check that value <= 4095
+ self._bank = 2
+ sleep(0.005)
+ self._accel_rate_divisor = value
+ sleep(0.005)
+
+ @property
+ def gyro_data_rate_divisor(self):
+ """The divisor for the rate at which gyro measurements are taken in Hz
+
+ Note: The data rates are set indirectly by setting a rate divisor according to the
+ following formula: ``gyro_data_rate = 1100/(1+divisor)``
+
+ This function sets the raw rate divisor.
+ """
+
+ self._bank = 2
+ raw_rate_divisor = self._gyro_rate_divisor
+ sleep(0.005)
+ self._bank = 0
+ # rate_hz = 1100/(1+raw_rate_divisor)
+ return raw_rate_divisor
+
+ @gyro_data_rate_divisor.setter
+ def gyro_data_rate_divisor(self, value):
+ # check that value <= 255
+ self._bank = 2
+ sleep(0.005)
+ self._gyro_rate_divisor = value
+ sleep(0.005)
+
+ def _accel_rate_calc(self, divisor): # pylint:disable=no-self-use
+ return 1125 / (1 + divisor)
+
+ def _gyro_rate_calc(self, divisor): # pylint:disable=no-self-use
+ return 1100 / (1 + divisor)
+
+ @property
+ def accelerometer_data_rate(self):
+ """The rate at which accelerometer measurements are taken in Hz
+
+ Note: The data rates are set indirectly by setting a rate divisor according to the
+ following formula: ``accelerometer_data_rate = 1125/(1+divisor)``
+
+ This function does the math to find the divisor from a given rate but it will not be
+ exactly as specified.
+ """
+ return self._accel_rate_calc(self.accelerometer_data_rate_divisor)
+
+ @accelerometer_data_rate.setter
+ def accelerometer_data_rate(self, value):
+ if value < self._accel_rate_calc(4095) or value > self._accel_rate_calc(0):
+ raise AttributeError(
+ "Accelerometer data rate must be between 0.27 and 1125.0"
+ )
+ self.accelerometer_data_rate_divisor = value
+
+ @property
+ def gyro_data_rate(self):
+ """The rate at which gyro measurements are taken in Hz
+
+ Note: The data rates are set indirectly by setting a rate divisor according to the
+ following formula: ``gyro_data_rate = 1100/(1+divisor)``
+ This function does the math to find the divisor from a given rate but it will not
+ be exactly as specified.
+ """
+ return self._gyro_rate_calc(self.gyro_data_rate_divisor)
+
+ @gyro_data_rate.setter
+ def gyro_data_rate(self, value):
+ if value < self._gyro_rate_calc(4095) or value > self._gyro_rate_calc(0):
+ raise AttributeError("Gyro data rate must be between 4.30 and 1100.0")
+
+ divisor = round(((1125.0 - value) / value))
+ self.gyro_data_rate_divisor = divisor
+
+ @property
+ def accel_dlpf_cutoff(self):
+ """The cutoff frequency for the accelerometer's digital low pass filter. Signals
+ above the given frequency will be filtered out. Must be an ``AccelDLPFCutoff``.
+ Use AccelDLPFCutoff.DISABLED to disable the filter
+
+ **Note** readings immediately following setting a cutoff frequency will be
+ inaccurate due to the filter "warming up" """
+ self._bank = 2
+ return self._accel_dlpf_config
+
+ @accel_dlpf_cutoff.setter
+ def accel_dlpf_cutoff(self, cutoff_frequency):
+ if not AccelDLPFFreq.is_valid(cutoff_frequency):
+ raise AttributeError("accel_dlpf_cutoff must be an `AccelDLPFFreq`")
+ self._bank = 2
+ # check for shutdown
+ if cutoff_frequency is AccelDLPFFreq.DISABLED: # pylint: disable=no-member
+ self._accel_dlpf_enable = False
+ return
+ self._accel_dlpf_enable = True
+ self._accel_dlpf_config = cutoff_frequency
+
+ @property
+ def gyro_dlpf_cutoff(self):
+ """The cutoff frequency for the gyro's digital low pass filter. Signals above the
+ given frequency will be filtered out. Must be a ``GyroDLPFFreq``. Use
+ GyroDLPFCutoff.DISABLED to disable the filter
+
+ **Note** readings immediately following setting a cutoff frequency will be
+ inaccurate due to the filter "warming up" """
+ self._bank = 2
+ return self._gyro_dlpf_config
+
+ @gyro_dlpf_cutoff.setter
+ def gyro_dlpf_cutoff(self, cutoff_frequency):
+ if not GyroDLPFFreq.is_valid(cutoff_frequency):
+ raise AttributeError("gyro_dlpf_cutoff must be a `GyroDLPFFreq`")
+ self._bank = 2
+ # check for shutdown
+ if cutoff_frequency is GyroDLPFFreq.DISABLED: # pylint: disable=no-member
+ self._gyro_dlpf_enable = False
+ return
+ self._gyro_dlpf_enable = True
+ self._gyro_dlpf_config = cutoff_frequency
+
+ @property
+ def _low_power(self):
+ self._bank = 0
+ return self._low_power_en
+
+ @_low_power.setter
+ def _low_power(self, enabled):
+ self._bank = 0
+ self._low_power_en = enabled
+
+
+class ICM20649(ICM20X):
+ """Library for the ST ICM-20649 Wide-Range 6-DoF Accelerometer and Gyro.
+
+ :param ~busio.I2C i2c_bus: The I2C bus the ICM20649 is connected to.
+ :param address: The I2C slave address of the sensor
+
+ """
+
+ def __init__(self, i2c_bus, address=_ICM20649_DEFAULT_ADDRESS):
+
+ AccelRange.add_values(
+ (
+ ("RANGE_4G", 0, 4, 8192),
+ ("RANGE_8G", 1, 8, 4096.0),
+ ("RANGE_16G", 2, 16, 2048),
+ ("RANGE_30G", 3, 30, 1024),
+ )
+ )
+
+ GyroRange.add_values(
+ (
+ ("RANGE_500_DPS", 0, 500, 65.5),
+ ("RANGE_1000_DPS", 1, 1000, 32.8),
+ ("RANGE_2000_DPS", 2, 2000, 16.4),
+ ("RANGE_4000_DPS", 3, 4000, 8.2),
+ )
+ )
+ super().__init__(i2c_bus, address)
+
+
+# https://www.y-ic.es/datasheet/78/SMDSW.020-2OZ.pdf page 19
+_AK09916_WIA1 = 0x00
+_AK09916_WIA2 = 0x01
+_AK09916_ST1 = 0x10
+_AK09916_HXL = 0x11
+_AK09916_HXH = 0x12
+_AK09916_HYL = 0x13
+_AK09916_HYH = 0x14
+_AK09916_HZL = 0x15
+_AK09916_HZH = 0x16
+_AK09916_ST2 = 0x18
+_AK09916_CNTL2 = 0x31
+_AK09916_CNTL3 = 0x32
+
+
+class MagDataRate(CV):
+ """Options for ``magnetometer_data_rate``"""
+
+ pass # pylint: disable=unnecessary-pass
+
+
+class ICM20948(ICM20X): # pylint:disable=too-many-instance-attributes
+ """Library for the ST ICM-20948 Wide-Range 6-DoF Accelerometer and Gyro.
+
+ :param ~busio.I2C i2c_bus: The I2C bus the ICM20948 is connected to.
+ :param address: The I2C slave address of the sensor
+ """
+
+ _slave_finished = ROBit(_ICM20X_I2C_MST_STATUS, 6)
+
+ # mag data is LE
+ _raw_mag_data = Struct(_ICM20948_EXT_SLV_SENS_DATA_00, "B")
+ _i2c_master_enable = RWBit(_ICM20X_USER_CTRL, 5) # TODO: use this in sw reset
+ _i2c_master_reset = RWBit(_ICM20X_USER_CTRL, 1)
+
+ _slave0_addr = UnaryStruct(_ICM20X_I2C_SLV0_ADDR, ">B")
+ _slave0_reg = UnaryStruct(_ICM20X_I2C_SLV0_REG, ">B")
+ _slave0_ctrl = UnaryStruct(_ICM20X_I2C_SLV0_CTRL, ">B")
+ _slave0_do = UnaryStruct(_ICM20X_I2C_SLV0_DO, ">B")
+
+ _slave4_addr = UnaryStruct(_ICM20X_I2C_SLV4_ADDR, ">B")
+ _slave4_reg = UnaryStruct(_ICM20X_I2C_SLV4_REG, ">B")
+ _slave4_ctrl = UnaryStruct(_ICM20X_I2C_SLV4_CTRL, ">B")
+ _slave4_do = UnaryStruct(_ICM20X_I2C_SLV4_DO, ">B")
+ _slave4_di = UnaryStruct(_ICM20X_I2C_SLV4_DI, ">B")
+
+ def __init__(self, i2c_bus, address=_ICM20948_DEFAULT_ADDRESS):
+ AccelRange.add_values(
+ (
+ ("RANGE_2G", 0, 2, 16384),
+ ("RANGE_4G", 1, 4, 8192),
+ ("RANGE_8G", 2, 8, 4096.0),
+ ("RANGE_16G", 3, 16, 2048),
+ )
+ )
+ GyroRange.add_values(
+ (
+ ("RANGE_250_DPS", 0, 250, 131.0),
+ ("RANGE_500_DPS", 1, 500, 65.5),
+ ("RANGE_1000_DPS", 2, 1000, 32.8),
+ ("RANGE_2000_DPS", 3, 2000, 16.4),
+ )
+ )
+
+ # https://www.y-ic.es/datasheet/78/SMDSW.020-2OZ.pdf page 9
+ MagDataRate.add_values(
+ (
+ ("SHUTDOWN", 0x0, "Shutdown", None),
+ ("SINGLE", 0x1, "Single", None),
+ ("RATE_10HZ", 0x2, 10, None),
+ ("RATE_20HZ", 0x4, 20, None),
+ ("RATE_50HZ", 0x6, 50, None),
+ ("RATE_100HZ", 0x8, 100, None),
+ )
+ )
+ super().__init__(i2c_bus, address)
+ self._magnetometer_init()
+
+ # A million thanks to the SparkFun folks for their library that I pillaged to write this method!
+ # See their Python library here:
+ # https://github.com/sparkfun/Qwiic_9DoF_IMU_ICM20948_Py
+ @property
+ def _mag_configured(self):
+ success = False
+ for _i in range(5):
+ success = self._mag_id() is not None
+
+ if success:
+ return True
+ self._reset_i2c_master()
+ # i2c master stuck, try resetting
+ return False
+
+ def _reset_i2c_master(self):
+ self._bank = 0
+ self._i2c_master_reset = True
+
+ def _magnetometer_enable(self):
+
+ self._bank = 0
+ sleep(0.100)
+ self._bypass_i2c_master = False
+ sleep(0.005)
+
+ # no repeated start, i2c master clock = 345.60kHz
+ self._bank = 3
+ sleep(0.100)
+ self._i2c_master_control = 0x17
+ sleep(0.100)
+
+ self._bank = 0
+ sleep(0.100)
+ self._i2c_master_enable = True
+ sleep(0.020)
+
+ def _magnetometer_init(self):
+ self._magnetometer_enable()
+ self.magnetometer_data_rate = (
+ MagDataRate.RATE_100HZ # pylint: disable=no-member
+ )
+
+ if not self._mag_configured:
+ return False
+
+ self._setup_mag_readout()
+
+ return True
+
+ # set up slave0 for reading into the bank 0 data registers
+ def _setup_mag_readout(self):
+ self._bank = 3
+ self._slave0_addr = 0x8C
+ sleep(0.005)
+ self._slave0_reg = 0x11
+ sleep(0.005)
+ self._slave0_ctrl = 0x89 # enable
+ sleep(0.005)
+
+ def _mag_id(self):
+ return self._read_mag_register(0x01)
+
+ @property
+ def magnetic(self):
+ """The current magnetic field strengths onthe X, Y, and Z axes in uT (micro-teslas)"""
+
+ self._bank = 0
+ full_data = self._raw_mag_data
+ sleep(0.005)
+
+ x = full_data[0] * _ICM20X_UT_PER_LSB
+ y = full_data[1] * _ICM20X_UT_PER_LSB
+ z = full_data[2] * _ICM20X_UT_PER_LSB
+
+ return (x, y, z)
+
+ @property
+ def magnetometer_data_rate(self):
+ """The rate at which the magenetometer takes measurements to update its output registers"""
+ # read mag DR register
+ self._read_mag_register(_AK09916_CNTL2)
+
+ @magnetometer_data_rate.setter
+ def magnetometer_data_rate(self, mag_rate):
+ # From https://www.y-ic.es/datasheet/78/SMDSW.020-2OZ.pdf page 9
+
+ # "When user wants to change operation mode, transit to Power-down mode first and then
+ # transit to other modes. After Power-down mode is set, at least 100 microsectons (Twait)
+ # is needed before setting another mode"
+ if not MagDataRate.is_valid(mag_rate):
+ raise AttributeError("range must be an `MagDataRate`")
+ self._write_mag_register(
+ _AK09916_CNTL2, MagDataRate.SHUTDOWN # pylint: disable=no-member
+ )
+ sleep(0.001)
+ self._write_mag_register(_AK09916_CNTL2, mag_rate)
+
+ def _read_mag_register(self, register_addr, slave_addr=0x0C):
+ self._bank = 3
+
+ slave_addr |= 0x80 # set top bit for read
+
+ self._slave4_addr = slave_addr
+ sleep(0.005)
+ self._slave4_reg = register_addr
+ sleep(0.005)
+ self._slave4_ctrl = (
+ 0x80 # enable, don't raise interrupt, write register value, no delay
+ )
+ sleep(0.005)
+ self._bank = 0
+
+ finished = False
+ for _i in range(100):
+ finished = self._slave_finished
+ if finished: # bueno!
+ break
+ sleep(0.010)
+
+ if not finished:
+ return None
+
+ self._bank = 3
+ mag_register_data = self._slave4_di
+ sleep(0.005)
+ return mag_register_data
+
+ def _write_mag_register(self, register_addr, value, slave_addr=0x0C):
+ self._bank = 3
+
+ self._slave4_addr = slave_addr
+ sleep(0.005)
+ self._slave4_reg = register_addr
+ sleep(0.005)
+ self._slave4_do = value
+ sleep(0.005)
+ self._slave4_ctrl = (
+ 0x80 # enable, don't raise interrupt, write register value, no delay
+ )
+ sleep(0.005)
+ self._bank = 0
+
+ finished = False
+ for _i in range(100):
+ finished = self._slave_finished
+ if finished: # bueno!
+ break
+ sleep(0.010)
+
+ return finished
diff --git a/docs/api.rst b/docs/api.rst
index b0970b5..69a0acf 100644
--- a/docs/api.rst
+++ b/docs/api.rst
@@ -4,5 +4,5 @@
.. If your library file(s) are nested in a directory (e.g. /adafruit_foo/foo.py)
.. use this format as the module name: "adafruit_foo.foo"
-.. automodule:: adafruit_icm20649
+.. automodule:: adafruit_icm20x
:members:
diff --git a/docs/conf.py b/docs/conf.py
index fb60b54..49d69b6 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -46,8 +46,8 @@
master_doc = "index"
# General information about the project.
-project = "Adafruit ICM20649 Library"
-copyright = "2019 Bryan Siepert"
+project = "Adafruit ICM20X Library"
+copyright = "2020 Bryan Siepert"
author = "Bryan Siepert"
# The version info for the project you're documenting, acts as replacement for
@@ -147,8 +147,8 @@
latex_documents = [
(
master_doc,
- "AdafruitICM20649Library.tex",
- "AdafruitICM20649 Library Documentation",
+ "AdafruitICM20XLibrary.tex",
+ "AdafruitICM20X Library Documentation",
author,
"manual",
),
@@ -161,8 +161,8 @@
man_pages = [
(
master_doc,
- "AdafruitICM20649library",
- "Adafruit ICM20649 Library Documentation",
+ "AdafruitICM20Xlibrary",
+ "Adafruit ICM20X Library Documentation",
[author],
1,
)
@@ -176,10 +176,10 @@
texinfo_documents = [
(
master_doc,
- "AdafruitICM20649Library",
- "Adafruit ICM20649 Library Documentation",
+ "AdafruitICM20XLibrary",
+ "Adafruit ICM20X Library Documentation",
author,
- "AdafruitICM20649Library",
+ "AdafruitICM20XLibrary",
"One line description of project.",
"Miscellaneous",
),
diff --git a/docs/examples.rst b/docs/examples.rst
index 3b9bebd..76f6011 100644
--- a/docs/examples.rst
+++ b/docs/examples.rst
@@ -1,8 +1,12 @@
Simple test
------------
-Ensure your device works with this simple test.
+Ensure your device works with one of these simple tests.
.. literalinclude:: ../examples/icm20649_simpletest.py
:caption: examples/icm20649_simpletest.py
:linenos:
+
+.. literalinclude:: ../examples/icm20948_simpletest.py
+ :caption: examples/icm20948_simpletest.py
+ :linenos:
diff --git a/docs/index.rst b/docs/index.rst
index 1afdd92..7001a29 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -32,7 +32,7 @@ Table of Contents
.. toctree::
:caption: Other Links
- Download
+ Download
CircuitPython Reference Documentation
CircuitPython Support Forum
Discord Chat
diff --git a/examples/icm20649_full_test.py b/examples/icm20649_full_test.py
index ef7ad22..a2f0336 100644
--- a/examples/icm20649_full_test.py
+++ b/examples/icm20649_full_test.py
@@ -1,7 +1,7 @@
import time
import board
import busio
-from adafruit_icm20649 import ICM20649, AccelRange, GyroRange
+from adafruit_icm20x import ICM20649, AccelRange, GyroRange
def printNewMax(value, current_max, axis):
@@ -17,7 +17,7 @@ def printNewMax(value, current_max, axis):
ism = ICM20649(i2c)
ism.accelerometer_range = AccelRange.RANGE_30G
-print("Accelerometer range set to: %d G" % AccelRange.string[ism.accelerometer_range])
+print("Accelerometer range set to: %d g" % AccelRange.string[ism.accelerometer_range])
ism.gyro_range = GyroRange.RANGE_500_DPS
print("Gyro range set to: %d DPS" % GyroRange.string[ism.gyro_range])
diff --git a/examples/icm20649_simpletest.py b/examples/icm20649_simpletest.py
index 66e92e5..1197544 100644
--- a/examples/icm20649_simpletest.py
+++ b/examples/icm20649_simpletest.py
@@ -1,13 +1,13 @@
import time
import board
import busio
-import adafruit_icm20649
+import adafruit_icm20x
i2c = busio.I2C(board.SCL, board.SDA)
-icm = adafruit_icm20649.ICM20649(i2c)
+icm = adafruit_icm20x.ICM20649(i2c)
while True:
print("Acceleration: X:%.2f, Y: %.2f, Z: %.2f m/s^2" % (icm.acceleration))
- print("Gyro X:%.2f, Y: %.2f, Z: %.2f degrees/s" % (icm.gyro))
+ print("Gyro X:%.2f, Y: %.2f, Z: %.2f rads/s" % (icm.gyro))
print("")
time.sleep(0.5)
diff --git a/examples/icm20948_accel_data_rate_test.py b/examples/icm20948_accel_data_rate_test.py
new file mode 100644
index 0000000..93bf6ea
--- /dev/null
+++ b/examples/icm20948_accel_data_rate_test.py
@@ -0,0 +1,24 @@
+import time
+import board
+import busio
+from adafruit_icm20x import ICM20948
+
+cycles = 200
+i2c = busio.I2C(board.SCL, board.SDA)
+icm = ICM20948(i2c)
+
+# Cycle between two data rates
+# Best viewed in the Mu serial plotter where you can see how
+# the data rate affects the resolution of the data
+while True:
+ icm.accelerometer_data_rate_divisor = 0 # minimum
+ print("Data Rate:", icm.accelerometer_data_rate)
+ time.sleep(2)
+ for i in range(cycles):
+ print(icm.acceleration)
+
+ icm.accelerometer_data_rate_divisor = 4095 # maximum
+ print("Data Rate:", icm.accelerometer_data_rate)
+ time.sleep(2)
+ for i in range(cycles):
+ print(icm.acceleration)
diff --git a/examples/icm20948_gyro_data_rate_test.py b/examples/icm20948_gyro_data_rate_test.py
new file mode 100644
index 0000000..cc62d29
--- /dev/null
+++ b/examples/icm20948_gyro_data_rate_test.py
@@ -0,0 +1,24 @@
+import time
+import board
+import busio
+from adafruit_icm20x import ICM20948
+
+cycles = 200
+i2c = busio.I2C(board.SCL, board.SDA)
+icm = ICM20948(i2c)
+
+# Cycle between two data rates
+# Best viewed in the Mu serial plotter where you can see how
+# the data rate affects the resolution of the data
+while True:
+ icm.gyro_data_rate_divisor = 0 # minimum
+ print("Data Rate:", icm.gyro_data_rate)
+ time.sleep(2)
+ for i in range(cycles):
+ print(icm.gyro)
+
+ icm.gyro_data_rate_divisor = 255 # maximum
+ print("Data Rate:", icm.gyro_data_rate)
+ time.sleep(2)
+ for i in range(cycles):
+ print(icm.gyro)
diff --git a/examples/icm20948_mag_data_rate_test.py b/examples/icm20948_mag_data_rate_test.py
new file mode 100644
index 0000000..63ba2a6
--- /dev/null
+++ b/examples/icm20948_mag_data_rate_test.py
@@ -0,0 +1,22 @@
+# pylint: disable=no-member
+import time
+import board
+import busio
+from adafruit_icm20x import MagDataRate, ICM20948
+
+cycles = 200
+i2c = busio.I2C(board.SCL, board.SDA)
+icm = ICM20948(i2c)
+
+# Cycle between two data rates
+# Best viewed in the Mu serial plotter where you can see how
+# the data rate affects the resolution of the data
+while True:
+ icm.magnetometer_data_rate = MagDataRate.RATE_100HZ
+ for i in range(cycles):
+ print(icm.magnetic)
+ time.sleep(0.3)
+ icm.magnetometer_data_rate = MagDataRate.RATE_10HZ
+ for i in range(cycles):
+ print(icm.magnetic)
+ time.sleep(0.3)
diff --git a/examples/icm20948_simpletest.py b/examples/icm20948_simpletest.py
new file mode 100644
index 0000000..8c1adf7
--- /dev/null
+++ b/examples/icm20948_simpletest.py
@@ -0,0 +1,14 @@
+import time
+import board
+import busio
+import adafruit_icm20x
+
+i2c = busio.I2C(board.SCL, board.SDA)
+icm = adafruit_icm20x.ICM20948(i2c)
+
+while True:
+ print("Acceleration: X:%.2f, Y: %.2f, Z: %.2f m/s^2" % (icm.acceleration))
+ print("Gyro X:%.2f, Y: %.2f, Z: %.2f rads/s" % (icm.gyro))
+ print("Magnetometer X:%.2f, Y: %.2f, Z: %.2f uT" % (icm.magnetic))
+ print("")
+ time.sleep(0.5)
diff --git a/setup.py b/setup.py
index 0a294e6..f0ead50 100644
--- a/setup.py
+++ b/setup.py
@@ -18,14 +18,14 @@
long_description = f.read()
setup(
- name="adafruit-circuitpython-icm20649",
+ name="adafruit-circuitpython-icm20x",
use_scm_version=True,
setup_requires=["setuptools_scm"],
- description="Library for the ST ICM-20649 Wide-Range 6-DoF Accelerometer and Gyro",
+ description="Library for the ST ICM-20X Wide-Range 6-DoF Accelerometer and Gyro Family",
long_description=long_description,
long_description_content_type="text/x-rst",
# The project's main homepage.
- url="https://github.com/adafruit/Adafruit_CircuitPython_ICM20649",
+ url="https://github.com/adafruit/Adafruit_CircuitPython_ICM20X",
# Author details
author="Adafruit Industries",
author_email="circuitpython@adafruit.com",
@@ -48,11 +48,11 @@
"Programming Language :: Python :: 3.5",
],
# What does your project relate to?
- keywords="adafruit blinka circuitpython micropython icm20649 gyro accelerometer high-G "
+ keywords="adafruit blinka circuitpython micropython icm20649 icm20948 icm20x gyro accelerometer high-G "
"6-axis wide range",
# You can just specify the packages manually here if your project is
# simple. Or you can use find_packages().
# TODO: IF LIBRARY FILES ARE A PACKAGE FOLDER,
# CHANGE `py_modules=['...']` TO `packages=['...']`
- py_modules=["adafruit_icm20649"],
+ py_modules=["adafruit_icm20x"],
)