commit
ef2deb9969
3 changed files with 220 additions and 39 deletions
|
|
@ -31,6 +31,7 @@ inertial measurement unit module with sensor fusion.
|
|||
* Author(s): Radomir Dopieralski
|
||||
"""
|
||||
import time
|
||||
import struct
|
||||
|
||||
from micropython import const
|
||||
from adafruit_bus_device.i2c_device import I2CDevice
|
||||
|
|
@ -114,33 +115,10 @@ class _ModeStruct(Struct): # pylint: disable=too-few-public-methods
|
|||
|
||||
class BNO055:
|
||||
"""
|
||||
Driver for the BNO055 9DOF IMU sensor.
|
||||
Base class for the BNO055 9DOF IMU sensor.
|
||||
"""
|
||||
|
||||
_temperature = _ReadOnlyUnaryStruct(0x34, "b")
|
||||
_acceleration = _ScaledReadOnlyStruct(0x08, "<hhh", 1 / 100)
|
||||
_magnetic = _ScaledReadOnlyStruct(0x0E, "<hhh", 1 / 16)
|
||||
_gyro = _ScaledReadOnlyStruct(0x14, "<hhh", 0.001090830782496456)
|
||||
_euler = _ScaledReadOnlyStruct(0x1A, "<hhh", 1 / 16)
|
||||
_quaternion = _ScaledReadOnlyStruct(0x20, "<hhhh", 1 / (1 << 14))
|
||||
_linear_acceleration = _ScaledReadOnlyStruct(0x28, "<hhh", 1 / 100)
|
||||
_gravity = _ScaledReadOnlyStruct(0x2E, "<hhh", 1 / 100)
|
||||
|
||||
offsets_accelerometer = _ModeStruct(_OFFSET_ACCEL_REGISTER, "<hhh", CONFIG_MODE)
|
||||
"""Calibration offsets for the accelerometer"""
|
||||
offsets_magnetometer = _ModeStruct(_OFFSET_MAGNET_REGISTER, "<hhh", CONFIG_MODE)
|
||||
"""Calibration offsets for the magnetometer"""
|
||||
offsets_gyroscope = _ModeStruct(_OFFSET_GYRO_REGISTER, "<hhh", CONFIG_MODE)
|
||||
"""Calibration offsets for the gyroscope"""
|
||||
|
||||
radius_accelerometer = _ModeStruct(_RADIUS_ACCEL_REGISTER, "<h", CONFIG_MODE)
|
||||
"""Radius for accelerometer (cm?)"""
|
||||
radius_magnetometer = _ModeStruct(_RADIUS_MAGNET_REGISTER, "<h", CONFIG_MODE)
|
||||
"""Radius for magnetometer (cm?)"""
|
||||
|
||||
def __init__(self, i2c, address=0x28):
|
||||
self.i2c_device = I2CDevice(i2c, address)
|
||||
self.buffer = bytearray(2)
|
||||
def __init__(self):
|
||||
chip_id = self._read_register(_ID_REGISTER)
|
||||
if chip_id != _CHIP_ID:
|
||||
raise RuntimeError("bad chip id (%x != %x)" % (chip_id, _CHIP_ID))
|
||||
|
|
@ -152,18 +130,6 @@ class BNO055:
|
|||
self.mode = NDOF_MODE
|
||||
time.sleep(0.01)
|
||||
|
||||
def _write_register(self, register, value):
|
||||
self.buffer[0] = register
|
||||
self.buffer[1] = value
|
||||
with self.i2c_device as i2c:
|
||||
i2c.write(self.buffer)
|
||||
|
||||
def _read_register(self, register):
|
||||
self.buffer[0] = register
|
||||
with self.i2c_device as i2c:
|
||||
i2c.write_then_readinto(self.buffer, self.buffer, out_end=1, in_start=1)
|
||||
return self.buffer[1]
|
||||
|
||||
def _reset(self):
|
||||
"""Resets the sensor to default settings."""
|
||||
self.mode = CONFIG_MODE
|
||||
|
|
@ -266,6 +232,10 @@ class BNO055:
|
|||
"""Measures the temperature of the chip in degrees Celsius."""
|
||||
return self._temperature
|
||||
|
||||
@property
|
||||
def _temperature(self):
|
||||
raise NotImplementedError("Must be implemented.")
|
||||
|
||||
@property
|
||||
def acceleration(self):
|
||||
"""Gives the raw accelerometer readings, in m/s.
|
||||
|
|
@ -275,6 +245,10 @@ class BNO055:
|
|||
return self._acceleration
|
||||
return (None, None, None)
|
||||
|
||||
@property
|
||||
def _acceleration(self):
|
||||
raise NotImplementedError("Must be implemented.")
|
||||
|
||||
@property
|
||||
def magnetic(self):
|
||||
"""Gives the raw magnetometer readings in microteslas.
|
||||
|
|
@ -284,6 +258,10 @@ class BNO055:
|
|||
return self._magnetic
|
||||
return (None, None, None)
|
||||
|
||||
@property
|
||||
def _magnetic(self):
|
||||
raise NotImplementedError("Must be implemented.")
|
||||
|
||||
@property
|
||||
def gyro(self):
|
||||
"""Gives the raw gyroscope reading in radians per second.
|
||||
|
|
@ -293,6 +271,10 @@ class BNO055:
|
|||
return self._gyro
|
||||
return (None, None, None)
|
||||
|
||||
@property
|
||||
def _gyro(self):
|
||||
raise NotImplementedError("Must be implemented.")
|
||||
|
||||
@property
|
||||
def euler(self):
|
||||
"""Gives the calculated orientation angles, in degrees.
|
||||
|
|
@ -302,6 +284,10 @@ class BNO055:
|
|||
return self._euler
|
||||
return (None, None, None)
|
||||
|
||||
@property
|
||||
def _euler(self):
|
||||
raise NotImplementedError("Must be implemented.")
|
||||
|
||||
@property
|
||||
def quaternion(self):
|
||||
"""Gives the calculated orientation as a quaternion.
|
||||
|
|
@ -311,6 +297,10 @@ class BNO055:
|
|||
return self._quaternion
|
||||
return (None, None, None, None)
|
||||
|
||||
@property
|
||||
def _quaternion(self):
|
||||
raise NotImplementedError("Must be implemented.")
|
||||
|
||||
@property
|
||||
def linear_acceleration(self):
|
||||
"""Returns the linear acceleration, without gravity, in m/s.
|
||||
|
|
@ -320,6 +310,10 @@ class BNO055:
|
|||
return self._linear_acceleration
|
||||
return (None, None, None)
|
||||
|
||||
@property
|
||||
def _linear_acceleration(self):
|
||||
raise NotImplementedError("Must be implemented.")
|
||||
|
||||
@property
|
||||
def gravity(self):
|
||||
"""Returns the gravity vector, without acceleration in m/s.
|
||||
|
|
@ -328,3 +322,185 @@ class BNO055:
|
|||
if self.mode in [0x09, 0x0B, 0x0C]:
|
||||
return self._gravity
|
||||
return (None, None, None)
|
||||
|
||||
@property
|
||||
def _gravity(self):
|
||||
raise NotImplementedError("Must be implemented.")
|
||||
|
||||
def _write_register(self, register, value):
|
||||
raise NotImplementedError("Must be implemented.")
|
||||
|
||||
def _read_register(self, register):
|
||||
raise NotImplementedError("Must be implemented.")
|
||||
|
||||
|
||||
class BNO055_I2C(BNO055):
|
||||
"""
|
||||
Driver for the BNO055 9DOF IMU sensor via I2C.
|
||||
"""
|
||||
|
||||
_temperature = _ReadOnlyUnaryStruct(0x34, "b")
|
||||
_acceleration = _ScaledReadOnlyStruct(0x08, "<hhh", 1 / 100)
|
||||
_magnetic = _ScaledReadOnlyStruct(0x0E, "<hhh", 1 / 16)
|
||||
_gyro = _ScaledReadOnlyStruct(0x14, "<hhh", 0.001090830782496456)
|
||||
_euler = _ScaledReadOnlyStruct(0x1A, "<hhh", 1 / 16)
|
||||
_quaternion = _ScaledReadOnlyStruct(0x20, "<hhhh", 1 / (1 << 14))
|
||||
_linear_acceleration = _ScaledReadOnlyStruct(0x28, "<hhh", 1 / 100)
|
||||
_gravity = _ScaledReadOnlyStruct(0x2E, "<hhh", 1 / 100)
|
||||
|
||||
offsets_accelerometer = _ModeStruct(_OFFSET_ACCEL_REGISTER, "<hhh", CONFIG_MODE)
|
||||
"""Calibration offsets for the accelerometer"""
|
||||
offsets_magnetometer = _ModeStruct(_OFFSET_MAGNET_REGISTER, "<hhh", CONFIG_MODE)
|
||||
"""Calibration offsets for the magnetometer"""
|
||||
offsets_gyroscope = _ModeStruct(_OFFSET_GYRO_REGISTER, "<hhh", CONFIG_MODE)
|
||||
"""Calibration offsets for the gyroscope"""
|
||||
|
||||
radius_accelerometer = _ModeStruct(_RADIUS_ACCEL_REGISTER, "<h", CONFIG_MODE)
|
||||
"""Radius for accelerometer (cm?)"""
|
||||
radius_magnetometer = _ModeStruct(_RADIUS_MAGNET_REGISTER, "<h", CONFIG_MODE)
|
||||
"""Radius for magnetometer (cm?)"""
|
||||
|
||||
def __init__(self, i2c, address=0x28):
|
||||
self.buffer = bytearray(2)
|
||||
self.i2c_device = I2CDevice(i2c, address)
|
||||
super().__init__()
|
||||
|
||||
def _write_register(self, register, value):
|
||||
self.buffer[0] = register
|
||||
self.buffer[1] = value
|
||||
with self.i2c_device as i2c:
|
||||
i2c.write(self.buffer)
|
||||
|
||||
def _read_register(self, register):
|
||||
self.buffer[0] = register
|
||||
with self.i2c_device as i2c:
|
||||
i2c.write_then_readinto(self.buffer, self.buffer, out_end=1, in_start=1)
|
||||
return self.buffer[1]
|
||||
|
||||
|
||||
class BNO055_UART(BNO055):
|
||||
"""
|
||||
Driver for the BNO055 9DOF IMU sensor via UART.
|
||||
"""
|
||||
|
||||
def __init__(self, uart):
|
||||
self._uart = uart
|
||||
self._uart.baudrate = 115200
|
||||
super().__init__()
|
||||
|
||||
def _write_register(self, register, data): # pylint: disable=arguments-differ
|
||||
if not isinstance(data, bytes):
|
||||
data = bytes([data])
|
||||
self._uart.write(bytes([0xAA, 0x00, register, len(data)]) + data)
|
||||
time.sleep(0.1)
|
||||
resp = self._uart.read(self._uart.in_waiting)
|
||||
if len(resp) < 2:
|
||||
raise OSError("UART access error.")
|
||||
if resp[0] != 0xEE or resp[1] != 0x01:
|
||||
raise RuntimeError("UART write error: {}".format(resp[1]))
|
||||
|
||||
def _read_register(self, register, length=1): # pylint: disable=arguments-differ
|
||||
self._uart.write(bytes([0xAA, 0x01, register, length]))
|
||||
time.sleep(0.1)
|
||||
resp = self._uart.read(self._uart.in_waiting)
|
||||
if len(resp) < 2:
|
||||
raise OSError("UART access error.")
|
||||
if resp[0] != 0xBB:
|
||||
raise RuntimeError("UART read error: {}".format(resp[1]))
|
||||
if length > 1:
|
||||
return resp[2:]
|
||||
return int(resp[2])
|
||||
|
||||
@property
|
||||
def _temperature(self):
|
||||
return self._read_register(0x34)
|
||||
|
||||
@property
|
||||
def _acceleration(self):
|
||||
resp = struct.unpack("<hhh", self._read_register(0x08, 6))
|
||||
return tuple([x / 100 for x in resp])
|
||||
|
||||
@property
|
||||
def _magnetic(self):
|
||||
resp = struct.unpack("<hhh", self._read_register(0x0E, 6))
|
||||
return tuple([x / 16 for x in resp])
|
||||
|
||||
@property
|
||||
def _gyro(self):
|
||||
resp = struct.unpack("<hhh", self._read_register(0x0E, 6))
|
||||
return tuple([x * 0.001090830782496456 for x in resp])
|
||||
|
||||
@property
|
||||
def _euler(self):
|
||||
resp = struct.unpack("<hhh", self._read_register(0x1A, 6))
|
||||
return tuple([x / 16 for x in resp])
|
||||
|
||||
@property
|
||||
def _quaternion(self):
|
||||
resp = struct.unpack("<hhhh", self._read_register(0x20, 8))
|
||||
return tuple([x / (1 << 14) for x in resp])
|
||||
|
||||
@property
|
||||
def _linear_acceleration(self):
|
||||
resp = struct.unpack("<hhh", self._read_register(0x28, 6))
|
||||
return tuple([x / 100 for x in resp])
|
||||
|
||||
@property
|
||||
def _gravity(self):
|
||||
resp = struct.unpack("<hhh", self._read_register(0x2E, 6))
|
||||
return tuple([x / 100 for x in resp])
|
||||
|
||||
@property
|
||||
def offsets_accelerometer(self):
|
||||
"""Calibration offsets for the accelerometer"""
|
||||
return struct.unpack("<hhh", self._read_register(_OFFSET_ACCEL_REGISTER, 6))
|
||||
|
||||
@offsets_accelerometer.setter
|
||||
def offsets_accelerometer(self, offsets):
|
||||
data = bytearray(6)
|
||||
struct.pack_into("<hhh", data, 0, *offsets)
|
||||
self._write_register(_OFFSET_ACCEL_REGISTER, bytes(data))
|
||||
|
||||
@property
|
||||
def offsets_magnetometer(self):
|
||||
"""Calibration offsets for the magnetometer"""
|
||||
return struct.unpack("<hhh", self._read_register(_OFFSET_MAGNET_REGISTER, 6))
|
||||
|
||||
@offsets_magnetometer.setter
|
||||
def offsets_magnetometer(self, offsets):
|
||||
data = bytearray(6)
|
||||
struct.pack_into("<hhh", data, 0, *offsets)
|
||||
self._write_register(_OFFSET_MAGNET_REGISTER, bytes(data))
|
||||
|
||||
@property
|
||||
def offsets_gyroscope(self):
|
||||
"""Calibration offsets for the gyroscope"""
|
||||
return struct.unpack("<hhh", self._read_register(_OFFSET_GYRO_REGISTER, 6))
|
||||
|
||||
@offsets_gyroscope.setter
|
||||
def offsets_gyroscope(self, offsets):
|
||||
data = bytearray(6)
|
||||
struct.pack_into("<hhh", data, 0, *offsets)
|
||||
self._write_register(_OFFSET_GYRO_REGISTER, bytes(data))
|
||||
|
||||
@property
|
||||
def radius_accelerometer(self):
|
||||
"""Radius for accelerometer (cm?)"""
|
||||
return struct.unpack("<h", self._read_register(_RADIUS_ACCEL_REGISTER, 2))[0]
|
||||
|
||||
@radius_accelerometer.setter
|
||||
def radius_accelerometer(self, radius):
|
||||
data = bytearray(2)
|
||||
struct.pack_into("<h", data, 0, radius)
|
||||
self._write_register(_RADIUS_ACCEL_REGISTER, bytes(data))
|
||||
|
||||
@property
|
||||
def radius_magnetometer(self):
|
||||
"""Radius for magnetometer (cm?)"""
|
||||
return struct.unpack("<h", self._read_register(_RADIUS_MAGNET_REGISTER, 2))[0]
|
||||
|
||||
@radius_magnetometer.setter
|
||||
def radius_magnetometer(self, radius):
|
||||
data = bytearray(2)
|
||||
struct.pack_into("<h", data, 0, radius)
|
||||
self._write_register(_RADIUS_MAGNET_REGISTER, bytes(data))
|
||||
|
|
|
|||
|
|
@ -3,8 +3,13 @@ import board
|
|||
import busio
|
||||
import adafruit_bno055
|
||||
|
||||
# Use these lines for I2C
|
||||
i2c = busio.I2C(board.SCL, board.SDA)
|
||||
sensor = adafruit_bno055.BNO055(i2c)
|
||||
sensor = adafruit_bno055.BNO055_I2C(i2c)
|
||||
|
||||
# User these lines for UART
|
||||
# uart = busio.UART(board.TX, board.RX)
|
||||
# sensor = adafruit_bno055.BNO055_UART(uart)
|
||||
|
||||
while True:
|
||||
print("Temperature: {} degrees C".format(sensor.temperature))
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ import adafruit_bno055
|
|||
i2c = busio.I2C(board.SCL, board.SDA)
|
||||
|
||||
# Create the BNO sensor connection.
|
||||
bno = adafruit_bno055.BNO055(i2c)
|
||||
bno = adafruit_bno055.BNO055_I2C(i2c)
|
||||
|
||||
# Application configuration below. You probably don't need to change these values.
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue