""" Example for BNO080 integrated IMU. Available from Sparkfun. """ import sys import serial import time import struct import random import math from i2cdriver import I2CDriver def hexdump(s): def toprint(c): if 32 <= c < 127: return chr(c) else: return "." def hexline(s): return (" ".join(["%02x" % c for c in s]).ljust(49) + "|" + "".join([toprint(c) for c in s]).ljust(16) + "|") return "\n".join([hexline(s[i:i+16]) for i in range(0, len(s), 16)]) CHANNEL_COMMAND = 0 CHANNEL_EXECUTABLE = 1 CHANNEL_CONTROL = 2 CHANNEL_REPORTS = 3 CHANNEL_WAKE_REPORTS = 4 CHANNEL_GYRO = 5 # All the ways we can configure or talk to the BNO080, figure 34, page 36 reference manual # These are used for low level communication with the sensor, on channel 2 SHTP_REPORT_COMMAND_RESPONSE = 0xF1 SHTP_REPORT_COMMAND_REQUEST = 0xF2 SHTP_REPORT_FRS_READ_RESPONSE = 0xF3 SHTP_REPORT_FRS_READ_REQUEST = 0xF4 SHTP_REPORT_PRODUCT_ID_RESPONSE = 0xF8 SHTP_REPORT_PRODUCT_ID_REQUEST = 0xF9 SHTP_REPORT_BASE_TIMESTAMP = 0xFB SHTP_REPORT_SET_FEATURE_COMMAND = 0xFD # All the different sensors and features we can get reports from # These are used when enabling a given sensor SENSOR_REPORTID_ACCELEROMETER = 0x01 SENSOR_REPORTID_GYROSCOPE = 0x02 SENSOR_REPORTID_MAGNETIC_FIELD = 0x03 SENSOR_REPORTID_LINEAR_ACCELERATION = 0x04 SENSOR_REPORTID_ROTATION_VECTOR = 0x05 SENSOR_REPORTID_GRAVITY = 0x06 SENSOR_REPORTID_GAME_ROTATION_VECTOR = 0x08 SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR = 0x09 SENSOR_REPORTID_TAP_DETECTOR = 0x10 SENSOR_REPORTID_STEP_COUNTER = 0x11 SENSOR_REPORTID_STABILITY_CLASSIFIER = 0x13 SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER = 0x1E # Record IDs from figure 29, page 29 reference manual # These are used to read the metadata for each sensor type FRS_RECORDID_ACCELEROMETER = 0xE302 FRS_RECORDID_GYROSCOPE_CALIBRATED = 0xE306 FRS_RECORDID_MAGNETIC_FIELD_CALIBRATED = 0xE309 FRS_RECORDID_ROTATION_VECTOR = 0xE30B # Command IDs from section 6.4, page 42 # These are used to calibrate, initialize, set orientation, tare etc the sensor COMMAND_ERRORS = 1 COMMAND_COUNTER = 2 COMMAND_TARE = 3 COMMAND_INITIALIZE = 4 COMMAND_DCD = 6 COMMAND_ME_CALIBRATE = 7 COMMAND_DCD_PERIOD_SAVE = 9 COMMAND_OSCILLATOR = 10 COMMAND_CLEAR_DCD = 11 CALIBRATE_ACCEL = 0 CALIBRATE_GYRO = 1 CALIBRATE_MAG = 2 CALIBRATE_PLANAR_ACCEL = 3 CALIBRATE_ACCEL_GYRO_MAG = 4 CALIBRATE_STOP = 5 def normalize(v, tolerance=0.00001): mag2 = sum(n * n for n in v) if abs(mag2 - 1.0) > tolerance: mag = math.sqrt(mag2) v = tuple(n / mag for n in v) return v class BNO080: def __init__(self, i2, a = 0x4b): self.i2 = i2 self.a = a self.seqno = [0] * 8 if 1: self.sendPacket(CHANNEL_EXECUTABLE, [1]) time.sleep(0.150) while True: if not self.receivePacket(): break self.setFeature(SENSOR_REPORTID_ROTATION_VECTOR, 50000) def read_quaternion(self): while True: r = self.receivePacket() while r: tag = r[0] r = r[1:] if tag == 0xfb: # print("Time %d" % struct.unpack("I", r[:4])) r = r[4:] elif tag == SHTP_REPORT_COMMAND_RESPONSE: r = r[16:] elif tag == 0xfc: # print("Get Feature Response") r = r[17:] elif tag == SENSOR_REPORTID_ACCELEROMETER: r = r[10:] elif tag == SENSOR_REPORTID_ROTATION_VECTOR: (_,_,_,i,j,k,w,_) = struct.unpack("