Merge pull request #47 from caternuson/uart

Add UART support
This commit is contained in:
Carter Nelson 2020-04-24 15:42:27 -07:00 committed by GitHub
commit ef2deb9969
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 220 additions and 39 deletions

View file

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

View file

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

View file

@ -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.