Fully featured I2C and SPI driver for CEVA (Hilcrest)'s BNO080 and FSM300 Inertial Measurement Units.

Dependents:   BNO080-Examples BNO080-Examples

BNO080 Driver

by Jamie Smith / USC Rocket Propulsion Lab

After lots of development, we are proud to present our driver for the Hilcrest BNO080 IMU! This driver is inspired by SparkFun and Nathan Seidle's Arduino driver for this chip, but has been substantially rewritten and adapted.

It supports the main features of the chip, such as reading rotation and acceleration data, as well as some of its more esoteric functionality, such as counting steps and detecting whether the device is being hand-held.

Features

  • Support for 15 different data reports from the IMU, from acceleration to rotation to tap detection
  • Support for reading of sensor data, and automatic checking of update rate against allowed values in metadata
  • BNO_DEBUG switch enabling verbose, detailed output about communications with the chip for ease of debugging
  • Ability to tare sensor rotation and set mounting orientation
  • Can operate in several execution modes: polling I2C, polling SPI, and threaded SPI (which handles timing-critical functions in a dedicated thread, and automatically activates when the IMU has data available)
    • Also has experimental support for using asynchronous SPI transactions, allowing other threads to execute while communication with the BNO is occurring. Note that this functionality requires a patch to Mbed OS source code due to Mbed bug #13941
  • Calibration function
  • Reasonable code size for what you get: the library uses about 4K of flash and one instance of the object uses about 1700 bytes of RAM.

Documentation

Full Doxygen documentation is available online here

Example Code

Here's a simple example:

BNO080 Rotation Vector and Acceleration

#include <mbed.h>
#include <BNO080.h>

int main()
{
	Serial pc(USBTX, USBRX);

	// Create IMU, passing in output stream, pins, I2C address, and I2C frequency
	// These pin assignments are specific to my dev setup -- you'll need to change them
	BNO080I2C imu(&pc, p28, p27, p16, p30, 0x4a, 100000); 

	pc.baud(115200);
	pc.printf("============================================================\n");

	// Tell the IMU to report rotation every 100ms and acceleration every 200ms
	imu.enableReport(BNO080::ROTATION, 100);
	imu.enableReport(BNO080::TOTAL_ACCELERATION, 200);

	while (true)
	{
		wait(.001f);
		
		// poll the IMU for new data -- this returns true if any packets were received
		if(imu.updateData())
		{
			// now check for the specific type of data that was received (can be multiple at once)
			if (imu.hasNewData(BNO080::ROTATION))
			{
				// convert quaternion to Euler degrees and print
				pc.printf("IMU Rotation Euler: ");
				TVector3 eulerRadians = imu.rotationVector.euler();
				TVector3 eulerDegrees = eulerRadians * (180.0 / M_PI);
				eulerDegrees.print(pc, true);
				pc.printf("\n");
			}
			if (imu.hasNewData(BNO080::TOTAL_ACCELERATION))
			{
				// print the acceleration vector using its builtin print() method
				pc.printf("IMU Total Acceleration: ");
				imu.totalAcceleration.print(pc, true);
				pc.printf("\n");
			}
		}
	}

}


If you want more, a comprehensive, ready-to-run set of examples is available on my BNO080-Examples repository.

Credits

This driver makes use of a lightweight, public-domain library for vectors and quaternions available here.

Changelog

Version 2.1 (Nov 24 2020)

  • Added BNO080Async, which provides a threaded implementation of the SPI driver. This should help get the best performance and remove annoying timing requirements on the code calling the driver
  • Added experimental USE_ASYNC_SPI option
  • Fixed bug in v2.0 causing calibrations to fail

Version 2.0 (Nov 18 2020)

  • Added SPI support
  • Refactored buffer system so that SPI could be implemented as a subclass. Unfortunately this does substantially increase the memory usage of the driver, but I believe that the benefits are worth it.

Version 1.3 (Jul 21 2020)

  • Fix deprecation warnings and compile errors in Mbed 6
  • Fix compile errors in Arm Compiler (why doesn't it have M_PI????)

Version 1.2 (Jan 30 2020)

  • Removed accidental IRQ change
  • Fixed hard iron offset reading incorrectly due to missing cast

Version 1.1 (Jun 14 2019)

  • Added support for changing permanent orientation
  • Add FRS writing functions
  • Removed some errant printfs

Version 1.0 (Dec 29 2018)

  • Initial Mbed OS release
Committer:
Jamie Smith
Date:
Tue Nov 24 15:06:05 2020 -0800
Revision:
9:430f5302f9e1
Parent:
8:199c7fad233d
Implement BNO080Async

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jamie Smith 1:aac28ffd63ed 1 /*
Jamie Smith 1:aac28ffd63ed 2 * This is USC RPL's ARM MBed BNO080 IMU driver, by Jamie Smith.
Jamie Smith 1:aac28ffd63ed 3 *
Jamie Smith 1:aac28ffd63ed 4 * It is based on SparkFun and Nathan Seidle's Arduino driver for this chip, but is substantially rewritten and adapted.
Jamie Smith 1:aac28ffd63ed 5 * It also supports some extra features, such as setting the mounting orientation and
Jamie Smith 1:aac28ffd63ed 6 * enabling some additional data reports.
Jamie Smith 1:aac28ffd63ed 7 *
Jamie Smith 1:aac28ffd63ed 8 * This driver uses no dynamic allocation, but does allocate a couple hundred bytes of class variables as buffers.
Jamie Smith 1:aac28ffd63ed 9 * This should allow you to monitor its memory usage using MBed's size printout.
Jamie Smith 1:aac28ffd63ed 10 *
Jamie Smith 1:aac28ffd63ed 11 * The BNO080 is a very complex chip; it's capable of monitoring and controlling other sensors and making
Jamie Smith 1:aac28ffd63ed 12 * intelligent decisions and calculations using its data. Accordingly, the protocol for communicating with it
Jamie Smith 1:aac28ffd63ed 13 * is quite complex, and it took me quite a while to wrap my head around it. If you need to modify or debug
Jamie Smith 1:aac28ffd63ed 14 * this driver, look at the CPP file for an overview of the chip's communication protocol.
Jamie Smith 1:aac28ffd63ed 15 *
Jamie Smith 1:aac28ffd63ed 16 * Note: this driver only supports I2C. I attempted to create an SPI version, but as far as I can tell,
Jamie Smith 1:aac28ffd63ed 17 * the BNO's SPI interface has a bug that causes you to be unable to wake the chip from sleep in some conditions.
Jamie Smith 1:aac28ffd63ed 18 * Until this is fixed, SPI on it is virtually unusable.
Jamie Smith 1:aac28ffd63ed 19 */
Jamie Smith 1:aac28ffd63ed 20
Jamie Smith 1:aac28ffd63ed 21 #ifndef HAMSTER_BNO080_H
Jamie Smith 1:aac28ffd63ed 22 #define HAMSTER_BNO080_H
Jamie Smith 1:aac28ffd63ed 23
Jamie Smith 1:aac28ffd63ed 24 #include <mbed.h>
Jamie Smith 8:199c7fad233d 25 #include <Stream.h>
Jamie Smith 1:aac28ffd63ed 26 #include <quaternion.h>
Jamie Smith 1:aac28ffd63ed 27
Jamie Smith 1:aac28ffd63ed 28 #include "BNO080Constants.h"
Jamie Smith 1:aac28ffd63ed 29
Jamie Smith 1:aac28ffd63ed 30 // useful define when working with orientation quaternions
Jamie Smith 3:197ad972fb7c 31 #define SQRT_2 1.414213562f
Jamie Smith 1:aac28ffd63ed 32
Jamie Smith 9:430f5302f9e1 33 // Enable this to enable experimental support for Mbed's asynchronous SPI transfer API.
Jamie Smith 9:430f5302f9e1 34 // This will allow your processor to do other things while long SPI transfers are taking place
Jamie Smith 9:430f5302f9e1 35 // (and this IMU can end up transferring hundreds of bytes per packet, so this is useful).
Jamie Smith 9:430f5302f9e1 36 // To get this to work, you may need to use a slower clock rate (<1MHz on the STM32F429ZI I tested).
Jamie Smith 9:430f5302f9e1 37 // You also will need to edit Mbed OS code in order to use 0x00 as the SPI fill character for
Jamie Smith 9:430f5302f9e1 38 // asynchronous transfers (the API currently only allows changing this for synchronous transfers)
Jamie Smith 9:430f5302f9e1 39 // (I had to edit the SPI_FILL_CHAR constant in stm_spi_api.c).
Jamie Smith 9:430f5302f9e1 40 #define USE_ASYNC_SPI 0
Jamie Smith 9:430f5302f9e1 41
Jamie Smith 9:430f5302f9e1 42 // Note: I filed a bug about the SPI fill char issue: https://github.com/ARMmbed/mbed-os/issues/13941
Jamie Smith 9:430f5302f9e1 43
Jamie Smith 1:aac28ffd63ed 44 /**
Jamie Smith 1:aac28ffd63ed 45 Class to drive the BNO080 9-axis IMU.
Jamie Smith 1:aac28ffd63ed 46
Jamie Smith 1:aac28ffd63ed 47 There should be one instance of this class per IMU chip. I2C address and pin assignments are passed in the constructor.
Jamie Smith 1:aac28ffd63ed 48 */
Jamie Smith 8:199c7fad233d 49 class BNO080Base
Jamie Smith 1:aac28ffd63ed 50 {
Jamie Smith 8:199c7fad233d 51 protected:
Jamie Smith 1:aac28ffd63ed 52 /**
Jamie Smith 1:aac28ffd63ed 53 * Serial stream to print debug info to. Used for errors, and debugging output if debugging is enabled.
Jamie Smith 1:aac28ffd63ed 54 */
Jamie Smith 6:5ba996be5312 55 Stream * _debugPort;
Jamie Smith 1:aac28ffd63ed 56
Jamie Smith 1:aac28ffd63ed 57 /// Interrupt pin -- signals to the host that the IMU has data to send
Jamie Smith 9:430f5302f9e1 58 // Note: only ever used as a digital input by BNO080.
Jamie Smith 9:430f5302f9e1 59 // Used for interrupts by BNO080Async.
Jamie Smith 9:430f5302f9e1 60 InterruptIn _int;
Jamie Smith 1:aac28ffd63ed 61
Jamie Smith 1:aac28ffd63ed 62 // Reset pin -- resets IMU when held low.
Jamie Smith 1:aac28ffd63ed 63 DigitalOut _rst;
Jamie Smith 1:aac28ffd63ed 64
Jamie Smith 1:aac28ffd63ed 65 // packet storage
Jamie Smith 1:aac28ffd63ed 66 //-----------------------------------------------------------------------------------------------------------------
Jamie Smith 1:aac28ffd63ed 67
Jamie Smith 1:aac28ffd63ed 68 #define SHTP_HEADER_SIZE 4
Jamie Smith 1:aac28ffd63ed 69
Jamie Smith 8:199c7fad233d 70 // Size of the largest individual packet we can receive.
Jamie Smith 8:199c7fad233d 71 // Min value is set by the advertisement packet (272 bytes)
Jamie Smith 3:197ad972fb7c 72 // If you enable lots of sensor reports and get an error, you might need to increase this.
Jamie Smith 8:199c7fad233d 73 #define SHTP_RX_PACKET_SIZE 272
Jamie Smith 8:199c7fad233d 74
Jamie Smith 8:199c7fad233d 75 // Size of largest packet that we need to transmit (not including header)
Jamie Smith 8:199c7fad233d 76 #define SHTP_MAX_TX_PACKET_SIZE 17
Jamie Smith 1:aac28ffd63ed 77
Jamie Smith 8:199c7fad233d 78 // scratch space buffers
Jamie Smith 8:199c7fad233d 79 uint8_t txPacketBuffer[SHTP_HEADER_SIZE + SHTP_MAX_TX_PACKET_SIZE];
Jamie Smith 8:199c7fad233d 80 uint8_t rxPacketBuffer[SHTP_HEADER_SIZE + SHTP_RX_PACKET_SIZE + SHTP_HEADER_SIZE]; // need a second header worth of extra scratch space to write the header of a continued packet
Jamie Smith 1:aac28ffd63ed 81
Jamie Smith 8:199c7fad233d 82 /// Each SHTP packet starts with a header of 4 uint8_ts
Jamie Smith 8:199c7fad233d 83 uint8_t * txShtpHeader = txPacketBuffer;
Jamie Smith 8:199c7fad233d 84 uint8_t * rxShtpHeader = rxPacketBuffer;
Jamie Smith 8:199c7fad233d 85
Jamie Smith 8:199c7fad233d 86 /// Stores data contained in each packet. Packets can contain an arbitrary amount of data, but
Jamie Smith 1:aac28ffd63ed 87 /// rarely get over a hundred bytes unless you have a million sensor reports enabled.
Jamie Smith 1:aac28ffd63ed 88 /// The only long packets we actually care about are batched sensor data packets.
Jamie Smith 8:199c7fad233d 89 uint8_t * txShtpData = txPacketBuffer + SHTP_HEADER_SIZE;
Jamie Smith 8:199c7fad233d 90 uint8_t * rxShtpData = rxPacketBuffer + SHTP_HEADER_SIZE;
Jamie Smith 1:aac28ffd63ed 91
Jamie Smith 1:aac28ffd63ed 92 /// Length of packet that was received into buffer. Does NOT include header bytes.
Jamie Smith 8:199c7fad233d 93 uint16_t rxPacketLength;
Jamie Smith 1:aac28ffd63ed 94
Jamie Smith 1:aac28ffd63ed 95 /// Current sequence number for each channel, incremented after transmission.
Jamie Smith 2:2269b723d16a 96 uint8_t sequenceNumber[6];
Jamie Smith 1:aac28ffd63ed 97
Jamie Smith 1:aac28ffd63ed 98 /// Commands have a seqNum as well. These are inside command packet, the header uses its own seqNum per channel
Jamie Smith 2:2269b723d16a 99 uint8_t commandSequenceNumber;
Jamie Smith 1:aac28ffd63ed 100
Jamie Smith 1:aac28ffd63ed 101 // frs metadata
Jamie Smith 1:aac28ffd63ed 102 //-----------------------------------------------------------------------------------------------------------------
Jamie Smith 1:aac28ffd63ed 103
Jamie Smith 1:aac28ffd63ed 104 /// Record ID of the metadata record currently stored in the metadataRecord[] buffer.
Jamie Smith 1:aac28ffd63ed 105 /// Used so that we can avoid requerying the FRS record if we need to make multiple metadata reads
Jamie Smith 1:aac28ffd63ed 106 /// in succession.
Jamie Smith 1:aac28ffd63ed 107 uint16_t bufferMetadataRecord;
Jamie Smith 1:aac28ffd63ed 108
Jamie Smith 1:aac28ffd63ed 109 /// currently we only need the first 10 words of the metadata
Jamie Smith 1:aac28ffd63ed 110 #define METADATA_BUFFER_LEN 10
Jamie Smith 1:aac28ffd63ed 111
Jamie Smith 1:aac28ffd63ed 112 /// Buffer for current metadata record.
Jamie Smith 2:2269b723d16a 113 uint32_t metadataRecord[METADATA_BUFFER_LEN];
Jamie Smith 1:aac28ffd63ed 114
Jamie Smith 1:aac28ffd63ed 115 // data storage
Jamie Smith 1:aac28ffd63ed 116 //-----------------------------------------------------------------------------------------------------------------
Jamie Smith 1:aac28ffd63ed 117
Jamie Smith 1:aac28ffd63ed 118 // 1 larger than the largest sensor report ID
Jamie Smith 1:aac28ffd63ed 119 #define STATUS_ARRAY_LEN MAX_SENSOR_REPORTID + 1
Jamie Smith 1:aac28ffd63ed 120
Jamie Smith 1:aac28ffd63ed 121 /// stores status of each sensor, indexed by report ID
Jamie Smith 2:2269b723d16a 122 uint8_t reportStatus[STATUS_ARRAY_LEN];
Jamie Smith 1:aac28ffd63ed 123
Jamie Smith 1:aac28ffd63ed 124 /// stores whether a sensor has been updated since the last call to hasNewData()
Jamie Smith 2:2269b723d16a 125 bool reportHasBeenUpdated[STATUS_ARRAY_LEN];
Jamie Smith 1:aac28ffd63ed 126
Jamie Smith 1:aac28ffd63ed 127 public:
Jamie Smith 1:aac28ffd63ed 128
Jamie Smith 1:aac28ffd63ed 129 // list of reports
Jamie Smith 1:aac28ffd63ed 130 //-----------------------------------------------------------------------------------------------------------------
Jamie Smith 1:aac28ffd63ed 131
Jamie Smith 1:aac28ffd63ed 132 /// List of all sensor reports that the IMU supports.
Jamie Smith 2:2269b723d16a 133 enum Report
Jamie Smith 1:aac28ffd63ed 134 {
Jamie Smith 1:aac28ffd63ed 135 /**
Jamie Smith 1:aac28ffd63ed 136 * Total acceleration of the IMU in world space.
Jamie Smith 1:aac28ffd63ed 137 * See BNO datasheet section 2.1.1
Jamie Smith 1:aac28ffd63ed 138 */
Jamie Smith 1:aac28ffd63ed 139 TOTAL_ACCELERATION = SENSOR_REPORTID_ACCELEROMETER,
Jamie Smith 1:aac28ffd63ed 140
Jamie Smith 1:aac28ffd63ed 141 /**
Jamie Smith 1:aac28ffd63ed 142 * Acceleration of the IMU not including the acceleration of gravity.
Jamie Smith 1:aac28ffd63ed 143 * See BNO datasheet section 2.1.1
Jamie Smith 1:aac28ffd63ed 144 */
Jamie Smith 1:aac28ffd63ed 145 LINEAR_ACCELERATION = SENSOR_REPORTID_LINEAR_ACCELERATION,
Jamie Smith 1:aac28ffd63ed 146
Jamie Smith 1:aac28ffd63ed 147 /**
Jamie Smith 1:aac28ffd63ed 148 * Acceleration of gravity felt by the IMU.
Jamie Smith 1:aac28ffd63ed 149 * See BNO datasheet section 2.1.1
Jamie Smith 1:aac28ffd63ed 150 */
Jamie Smith 1:aac28ffd63ed 151 GRAVITY_ACCELERATION = SENSOR_REPORTID_GRAVITY,
Jamie Smith 1:aac28ffd63ed 152
Jamie Smith 1:aac28ffd63ed 153 /**
Jamie Smith 1:aac28ffd63ed 154 * (calibrated) gyroscope reading of the rotational speed of the IMU.
Jamie Smith 1:aac28ffd63ed 155 * See BNO datasheet section 2.1.2
Jamie Smith 1:aac28ffd63ed 156 */
Jamie Smith 1:aac28ffd63ed 157 GYROSCOPE = SENSOR_REPORTID_GYROSCOPE_CALIBRATED,
Jamie Smith 1:aac28ffd63ed 158
Jamie Smith 1:aac28ffd63ed 159 /**
Jamie Smith 1:aac28ffd63ed 160 * (calibrated) reading of Earth's magnetic field levels.
Jamie Smith 1:aac28ffd63ed 161 * See BNO datasheet section 2.1.3
Jamie Smith 1:aac28ffd63ed 162 */
Jamie Smith 1:aac28ffd63ed 163 MAG_FIELD = SENSOR_REPORTID_MAGNETIC_FIELD_CALIBRATED,
Jamie Smith 1:aac28ffd63ed 164
Jamie Smith 1:aac28ffd63ed 165 /**
Jamie Smith 1:aac28ffd63ed 166 * Uncalibrated reading of magnetic field levels, without any hard iron offsets applied
Jamie Smith 1:aac28ffd63ed 167 * See BNO datasheet section 2.1.3
Jamie Smith 1:aac28ffd63ed 168 */
Jamie Smith 1:aac28ffd63ed 169 MAG_FIELD_UNCALIBRATED = SENSOR_REPORTID_MAGNETIC_FIELD_UNCALIBRATED,
Jamie Smith 1:aac28ffd63ed 170
Jamie Smith 1:aac28ffd63ed 171 /**
Jamie Smith 1:aac28ffd63ed 172 * Fused reading of the IMU's rotation in space using all three sensors. This is the most accurate reading
Jamie Smith 1:aac28ffd63ed 173 * of absolute orientation that the IMU can provide.
Jamie Smith 1:aac28ffd63ed 174 * See BNO datasheet section 2.2.4
Jamie Smith 1:aac28ffd63ed 175 */
Jamie Smith 1:aac28ffd63ed 176 ROTATION = SENSOR_REPORTID_ROTATION_VECTOR,
Jamie Smith 1:aac28ffd63ed 177
Jamie Smith 1:aac28ffd63ed 178 /**
Jamie Smith 1:aac28ffd63ed 179 * Fused reading of rotation from accelerometer and magnetometer readings. This report is designed to decrease
Jamie Smith 1:aac28ffd63ed 180 * power consumption (by turning off the gyroscope) in exchange for reduced responsiveness.
Jamie Smith 1:aac28ffd63ed 181 */
Jamie Smith 1:aac28ffd63ed 182 GEOMAGNETIC_ROTATION = SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR,
Jamie Smith 1:aac28ffd63ed 183
Jamie Smith 1:aac28ffd63ed 184 /**
Jamie Smith 1:aac28ffd63ed 185 * Fused reading of the IMU's rotation in space. Unlike the regular rotation vector, the Game Rotation Vector
Jamie Smith 1:aac28ffd63ed 186 * is not referenced against the magnetic field and the "zero yaw" point is arbitrary.
Jamie Smith 1:aac28ffd63ed 187 * See BNO datasheet section 2.2.2
Jamie Smith 1:aac28ffd63ed 188 */
Jamie Smith 1:aac28ffd63ed 189 GAME_ROTATION = SENSOR_REPORTID_GAME_ROTATION_VECTOR,
Jamie Smith 1:aac28ffd63ed 190
Jamie Smith 1:aac28ffd63ed 191 /**
Jamie Smith 1:aac28ffd63ed 192 * Detects a user tapping on the device containing the IMU.
Jamie Smith 1:aac28ffd63ed 193 * See BNO datasheet section 2.4.2
Jamie Smith 1:aac28ffd63ed 194 */
Jamie Smith 1:aac28ffd63ed 195 TAP_DETECTOR = SENSOR_REPORTID_TAP_DETECTOR,
Jamie Smith 1:aac28ffd63ed 196
Jamie Smith 1:aac28ffd63ed 197 /**
Jamie Smith 1:aac28ffd63ed 198 * Detects whether the device is on a table, being held stably, or being moved.
Jamie Smith 1:aac28ffd63ed 199 * See BNO datasheet section 2.4.1
Jamie Smith 1:aac28ffd63ed 200 */
Jamie Smith 1:aac28ffd63ed 201 STABILITY_CLASSIFIER = SENSOR_REPORTID_STABILITY_CLASSIFIER,
Jamie Smith 1:aac28ffd63ed 202
Jamie Smith 1:aac28ffd63ed 203 /**
Jamie Smith 1:aac28ffd63ed 204 * Detects a user taking a step with the IMU worn on their person.
Jamie Smith 1:aac28ffd63ed 205 * See BNO datasheet section 2.4.3
Jamie Smith 1:aac28ffd63ed 206 */
Jamie Smith 1:aac28ffd63ed 207 STEP_DETECTOR = SENSOR_REPORTID_STEP_DETECTOR,
Jamie Smith 1:aac28ffd63ed 208
Jamie Smith 1:aac28ffd63ed 209 /**
Jamie Smith 1:aac28ffd63ed 210 * Detects how many steps a user has taken.
Jamie Smith 1:aac28ffd63ed 211 * See BNO datasheet section 2.4.4
Jamie Smith 1:aac28ffd63ed 212 */
Jamie Smith 1:aac28ffd63ed 213 STEP_COUNTER = SENSOR_REPORTID_STEP_COUNTER,
Jamie Smith 1:aac28ffd63ed 214
Jamie Smith 1:aac28ffd63ed 215 /**
Jamie Smith 1:aac28ffd63ed 216 * Detects when the IMU has made a "significant" motion, defined as moving a few steps and/or accelerating significantly.
Jamie Smith 1:aac28ffd63ed 217 *
Jamie Smith 1:aac28ffd63ed 218 * NOTE: this report automatically disables itself after sending a report, so you'll have to reenable it each time a motion i s detected.
Jamie Smith 1:aac28ffd63ed 219 * See BNO datasheet section 2.4.6
Jamie Smith 1:aac28ffd63ed 220 */
Jamie Smith 1:aac28ffd63ed 221 SIGNIFICANT_MOTION = SENSOR_REPORTID_SIGNIFICANT_MOTION,
Jamie Smith 1:aac28ffd63ed 222
Jamie Smith 1:aac28ffd63ed 223 /**
Jamie Smith 1:aac28ffd63ed 224 * Detects when the IMU is being shaken.
Jamie Smith 1:aac28ffd63ed 225 * See BNO datasheet section 2.4.7
Jamie Smith 1:aac28ffd63ed 226 */
Jamie Smith 1:aac28ffd63ed 227 SHAKE_DETECTOR = SENSOR_REPORTID_SHAKE_DETECTOR
Jamie Smith 1:aac28ffd63ed 228 };
Jamie Smith 1:aac28ffd63ed 229
Jamie Smith 1:aac28ffd63ed 230 // data variables to read reports from
Jamie Smith 1:aac28ffd63ed 231 //-----------------------------------------------------------------------------------------------------------------
Jamie Smith 1:aac28ffd63ed 232
Jamie Smith 1:aac28ffd63ed 233 // @{
Jamie Smith 1:aac28ffd63ed 234 /// Version info read from the IMU when it starts up
Jamie Smith 1:aac28ffd63ed 235 uint8_t majorSoftwareVersion;
Jamie Smith 1:aac28ffd63ed 236 uint8_t minorSoftwareVersion;
Jamie Smith 1:aac28ffd63ed 237 uint16_t patchSoftwareVersion;
Jamie Smith 1:aac28ffd63ed 238 uint32_t partNumber;
Jamie Smith 1:aac28ffd63ed 239 uint32_t buildNumber;
Jamie Smith 1:aac28ffd63ed 240 // @}
Jamie Smith 1:aac28ffd63ed 241
Jamie Smith 1:aac28ffd63ed 242
Jamie Smith 1:aac28ffd63ed 243 /**
Jamie Smith 1:aac28ffd63ed 244 * Readout from Accleration report.
Jamie Smith 1:aac28ffd63ed 245 * Represents total acceleration in m/s^2 felt by the BNO's accelerometer.
Jamie Smith 1:aac28ffd63ed 246 */
Jamie Smith 1:aac28ffd63ed 247 TVector3 totalAcceleration;
Jamie Smith 1:aac28ffd63ed 248
Jamie Smith 1:aac28ffd63ed 249 /**
Jamie Smith 1:aac28ffd63ed 250 * Readout from Linear Acceleration report.
Jamie Smith 1:aac28ffd63ed 251 * Represents acceleration felt in m/s^2 by the BNO's accelerometer not including the force of gravity.
Jamie Smith 1:aac28ffd63ed 252 */
Jamie Smith 1:aac28ffd63ed 253 TVector3 linearAcceleration;
Jamie Smith 1:aac28ffd63ed 254
Jamie Smith 1:aac28ffd63ed 255 /**
Jamie Smith 1:aac28ffd63ed 256 * Readout from Gravity report.
Jamie Smith 1:aac28ffd63ed 257 * Represents the force of gravity in m/s^2 felt by the BNO's accelerometer.
Jamie Smith 1:aac28ffd63ed 258 */
Jamie Smith 1:aac28ffd63ed 259 TVector3 gravityAcceleration;
Jamie Smith 1:aac28ffd63ed 260
Jamie Smith 1:aac28ffd63ed 261 /**
Jamie Smith 1:aac28ffd63ed 262 * Readout from Calibrated Gyroscope report
Jamie Smith 1:aac28ffd63ed 263 * Represents the angular velocities of the chip in rad/s in the X, Y, and Z axes
Jamie Smith 1:aac28ffd63ed 264 */
Jamie Smith 1:aac28ffd63ed 265 TVector3 gyroRotation;
Jamie Smith 1:aac28ffd63ed 266
Jamie Smith 1:aac28ffd63ed 267 /**
Jamie Smith 1:aac28ffd63ed 268 * Readout from the Magnetic Field Calibrated report.
Jamie Smith 1:aac28ffd63ed 269 * Represents the magnetic field read by the chip in uT in the X, Y, and Z axes
Jamie Smith 1:aac28ffd63ed 270 */
Jamie Smith 1:aac28ffd63ed 271 TVector3 magField;
Jamie Smith 1:aac28ffd63ed 272
Jamie Smith 1:aac28ffd63ed 273 /**
Jamie Smith 1:aac28ffd63ed 274 * Readout from the Magnetic Field Uncalibrated report.
Jamie Smith 1:aac28ffd63ed 275 * Represents the magnetic field read by the chip in uT in the X, Y, and Z axes, without hard iron offsets applied
Jamie Smith 1:aac28ffd63ed 276 */
Jamie Smith 1:aac28ffd63ed 277 TVector3 magFieldUncalibrated;
Jamie Smith 1:aac28ffd63ed 278
Jamie Smith 1:aac28ffd63ed 279 /**
Jamie Smith 1:aac28ffd63ed 280 * Auxiliary readout from the Magnetic Field Uncalibrated report.
Jamie Smith 1:aac28ffd63ed 281 * Represents the hard iron offsets that the chip is using in each axis in uT.
Jamie Smith 1:aac28ffd63ed 282 */
Jamie Smith 1:aac28ffd63ed 283 TVector3 hardIronOffset;
Jamie Smith 1:aac28ffd63ed 284
Jamie Smith 1:aac28ffd63ed 285 /**
Jamie Smith 1:aac28ffd63ed 286 * Readout from the Rotation Vector report.
Jamie Smith 1:aac28ffd63ed 287 * Represents the rotation of the IMU (relative to magnetic north) in radians.
Jamie Smith 1:aac28ffd63ed 288 */
Jamie Smith 1:aac28ffd63ed 289 Quaternion rotationVector;
Jamie Smith 1:aac28ffd63ed 290
Jamie Smith 1:aac28ffd63ed 291 /**
Jamie Smith 1:aac28ffd63ed 292 * Auxiliary accuracy readout from the Rotation Vector report.
Jamie Smith 1:aac28ffd63ed 293 * Represents the estimated accuracy of the rotation vector in radians.
Jamie Smith 1:aac28ffd63ed 294 */
Jamie Smith 1:aac28ffd63ed 295 float rotationAccuracy;
Jamie Smith 1:aac28ffd63ed 296
Jamie Smith 1:aac28ffd63ed 297 /**
Jamie Smith 1:aac28ffd63ed 298 * Readout from the Game Rotation Vector report.
Jamie Smith 1:aac28ffd63ed 299 * Represents the rotation of the IMU in radians. Unlike the regular rotation vector, the Game Rotation Vector
Jamie Smith 1:aac28ffd63ed 300 * is not referenced against the magnetic field and the "zero yaw" point is arbitrary.
Jamie Smith 1:aac28ffd63ed 301 */
Jamie Smith 1:aac28ffd63ed 302 Quaternion gameRotationVector;
Jamie Smith 1:aac28ffd63ed 303
Jamie Smith 1:aac28ffd63ed 304 /**
Jamie Smith 1:aac28ffd63ed 305 * Readout from the Geomagnetic Rotation Vector report.
Jamie Smith 1:aac28ffd63ed 306 * Represents the geomagnetic rotation of the IMU (relative to magnetic north) in radians.
Jamie Smith 1:aac28ffd63ed 307 */
Jamie Smith 1:aac28ffd63ed 308 Quaternion geomagneticRotationVector;
Jamie Smith 1:aac28ffd63ed 309
Jamie Smith 1:aac28ffd63ed 310 /**
Jamie Smith 1:aac28ffd63ed 311 * Auxiliary accuracy readout from the Geomagnetic Rotation Vector report.
Jamie Smith 1:aac28ffd63ed 312 * Represents the estimated accuracy of the rotation vector in radians.
Jamie Smith 1:aac28ffd63ed 313 */
Jamie Smith 1:aac28ffd63ed 314 float geomagneticRotationAccuracy;
Jamie Smith 1:aac28ffd63ed 315
Jamie Smith 1:aac28ffd63ed 316 /**
Jamie Smith 1:aac28ffd63ed 317 * Tap readout from the Tap Detector report. This flag is set to true whenever a tap is detected, and you should
Jamie Smith 1:aac28ffd63ed 318 * manually clear it when you have processed the tap.
Jamie Smith 1:aac28ffd63ed 319 */
Jamie Smith 1:aac28ffd63ed 320 bool tapDetected;
Jamie Smith 1:aac28ffd63ed 321
Jamie Smith 1:aac28ffd63ed 322 /**
Jamie Smith 1:aac28ffd63ed 323 * Whether the last tap detected was a single or double tap.
Jamie Smith 1:aac28ffd63ed 324 */
Jamie Smith 1:aac28ffd63ed 325 bool doubleTap;
Jamie Smith 1:aac28ffd63ed 326
Jamie Smith 1:aac28ffd63ed 327 /**
Jamie Smith 1:aac28ffd63ed 328 * Enum to represent the different stability types.
Jamie Smith 1:aac28ffd63ed 329 *
Jamie Smith 1:aac28ffd63ed 330 * See BNO datasheet section 2.4.1 and SH-2 section 6.5.31.2 for details.
Jamie Smith 1:aac28ffd63ed 331 */
Jamie Smith 2:2269b723d16a 332 enum Stability
Jamie Smith 1:aac28ffd63ed 333 {
Jamie Smith 1:aac28ffd63ed 334 /// Unknown stability type.
Jamie Smith 1:aac28ffd63ed 335 UNKNOWN = 0,
Jamie Smith 1:aac28ffd63ed 336
Jamie Smith 1:aac28ffd63ed 337 /// At rest on a stable surface with very little motion
Jamie Smith 1:aac28ffd63ed 338 ON_TABLE = 1,
Jamie Smith 1:aac28ffd63ed 339
Jamie Smith 1:aac28ffd63ed 340 /// Motion is stable, but the duration requirement for stability has not been met.
Jamie Smith 1:aac28ffd63ed 341 /// Can only occur during gyroscope calibration (why? beats me!)
Jamie Smith 1:aac28ffd63ed 342 STATIONARY = 2,
Jamie Smith 1:aac28ffd63ed 343
Jamie Smith 1:aac28ffd63ed 344 /// Stable (has been below the acceleration threshold for the required duration)
Jamie Smith 1:aac28ffd63ed 345 STABLE = 3,
Jamie Smith 1:aac28ffd63ed 346
Jamie Smith 1:aac28ffd63ed 347 /// IMU is moving.
Jamie Smith 1:aac28ffd63ed 348 MOTION = 4
Jamie Smith 1:aac28ffd63ed 349 };
Jamie Smith 1:aac28ffd63ed 350
Jamie Smith 1:aac28ffd63ed 351 /**
Jamie Smith 1:aac28ffd63ed 352 * Readout from the stability classifier.
Jamie Smith 1:aac28ffd63ed 353 * Current stability status of the IMU.
Jamie Smith 1:aac28ffd63ed 354 */
Jamie Smith 2:2269b723d16a 355 Stability stability;
Jamie Smith 1:aac28ffd63ed 356
Jamie Smith 1:aac28ffd63ed 357 /**
Jamie Smith 1:aac28ffd63ed 358 * Readout from the Step Detector report. This flag is set to true whenever a step is detected, and you should
Jamie Smith 1:aac28ffd63ed 359 * manually clear it when you have processed the step.
Jamie Smith 1:aac28ffd63ed 360 */
Jamie Smith 2:2269b723d16a 361 bool stepDetected;
Jamie Smith 1:aac28ffd63ed 362
Jamie Smith 1:aac28ffd63ed 363 /**
Jamie Smith 1:aac28ffd63ed 364 * Readout from the Step Counter report. This count increases as the user takes steps, but can also decrease
Jamie Smith 1:aac28ffd63ed 365 * if the IMU decides that a motion was not a step.
Jamie Smith 1:aac28ffd63ed 366 */
Jamie Smith 1:aac28ffd63ed 367 uint16_t stepCount;
Jamie Smith 1:aac28ffd63ed 368
Jamie Smith 1:aac28ffd63ed 369 /**
Jamie Smith 1:aac28ffd63ed 370 * Readout from the Significant Motion Detector report. This flag is set to true whenever significant motion is detected, and you should
Jamie Smith 1:aac28ffd63ed 371 * manually clear it when you have processed the event.
Jamie Smith 1:aac28ffd63ed 372 */
Jamie Smith 2:2269b723d16a 373 bool significantMotionDetected;
Jamie Smith 1:aac28ffd63ed 374
Jamie Smith 1:aac28ffd63ed 375 /**
Jamie Smith 1:aac28ffd63ed 376 * Readout from the Shake Detector report. This flag is set to true whenever shaking is detected, and you should
Jamie Smith 1:aac28ffd63ed 377 * manually clear it when you have processed the event.
Jamie Smith 1:aac28ffd63ed 378 */
Jamie Smith 2:2269b723d16a 379 bool shakeDetected;
Jamie Smith 1:aac28ffd63ed 380
Jamie Smith 1:aac28ffd63ed 381 // @{
Jamie Smith 1:aac28ffd63ed 382 /// The axis/axes that shaking was detected in in the latest shaking report.
Jamie Smith 2:2269b723d16a 383 bool xAxisShake;
Jamie Smith 2:2269b723d16a 384 bool yAxisShake;
Jamie Smith 2:2269b723d16a 385 bool zAxisShake;
Jamie Smith 1:aac28ffd63ed 386 // @}
Jamie Smith 1:aac28ffd63ed 387
Jamie Smith 1:aac28ffd63ed 388 // Management functions
Jamie Smith 1:aac28ffd63ed 389 //-----------------------------------------------------------------------------------------------------------------
Jamie Smith 1:aac28ffd63ed 390
Jamie Smith 1:aac28ffd63ed 391 /**
Jamie Smith 1:aac28ffd63ed 392 * Construct a BNO080, providing pins and parameters.
Jamie Smith 1:aac28ffd63ed 393 *
Jamie Smith 1:aac28ffd63ed 394 * This doesn't actally initialize the chip, you will need to call begin() for that.
Jamie Smith 1:aac28ffd63ed 395 *
Jamie Smith 1:aac28ffd63ed 396 * NOTE: while some schematics tell you to connect the BOOTN pin to the processor, this driver does not use or require it.
Jamie Smith 1:aac28ffd63ed 397 * Just tie it to VCC per the datasheet.
Jamie Smith 1:aac28ffd63ed 398 *
Jamie Smith 1:aac28ffd63ed 399 * @param debugPort Serial port to write output to. Cannot be nullptr.
Jamie Smith 1:aac28ffd63ed 400 */
Jamie Smith 8:199c7fad233d 401 BNO080Base(Stream *debugPort, PinName user_INTPin, PinName user_RSTPin);
Jamie Smith 1:aac28ffd63ed 402
Jamie Smith 1:aac28ffd63ed 403 /**
Jamie Smith 1:aac28ffd63ed 404 * Resets and connects to the IMU. Verifies that it's connected, and reads out its version
Jamie Smith 1:aac28ffd63ed 405 * info into the class variables above.
Jamie Smith 1:aac28ffd63ed 406 *
Jamie Smith 1:aac28ffd63ed 407 * If this function is failing, it would be a good idea to turn on BNO_DEBUG in the cpp file to get detailed output.
Jamie Smith 1:aac28ffd63ed 408 *
Jamie Smith 9:430f5302f9e1 409 * Note: this function takes several hundred ms to execute, mainly due to waiting for the BNO to boot.
Jamie Smith 9:430f5302f9e1 410 *
Jamie Smith 1:aac28ffd63ed 411 * @return whether or not initialization was successful
Jamie Smith 1:aac28ffd63ed 412 */
Jamie Smith 9:430f5302f9e1 413 virtual bool begin();
Jamie Smith 1:aac28ffd63ed 414
Jamie Smith 1:aac28ffd63ed 415 /**
Jamie Smith 1:aac28ffd63ed 416 * Tells the IMU to use its current rotation vector as the "zero" rotation vector and to reorient
Jamie Smith 1:aac28ffd63ed 417 * all outputs accordingly.
Jamie Smith 1:aac28ffd63ed 418 *
Jamie Smith 1:aac28ffd63ed 419 * @param zOnly If true, only the rotation about the Z axis (the heading) will be tared.
Jamie Smith 1:aac28ffd63ed 420 */
Jamie Smith 1:aac28ffd63ed 421 void tare(bool zOnly = false);
Jamie Smith 1:aac28ffd63ed 422
Jamie Smith 1:aac28ffd63ed 423 /**
Jamie Smith 1:aac28ffd63ed 424 * Tells the IMU to begin a dynamic sensor calibration. To calibrate the IMU, call this function and move
Jamie Smith 1:aac28ffd63ed 425 * the IMU according to the instructions in the "BNO080 Sensor Calibration Procedure" app note
Jamie Smith 1:aac28ffd63ed 426 * (http://www.hillcrestlabs.com/download/59de9014566d0727bd002ae7).
Jamie Smith 1:aac28ffd63ed 427 *
Jamie Smith 1:aac28ffd63ed 428 * To tell when the calibration is complete, look at the status bits for Game Rotation Vector (for accel and gyro)
Jamie Smith 1:aac28ffd63ed 429 * and Magnetic Field (for the magnetometer).
Jamie Smith 1:aac28ffd63ed 430 *
Jamie Smith 1:aac28ffd63ed 431 * The gyro and accelerometer should only need to be calibrated once, but the magnetometer will need to be recalibrated
Jamie Smith 1:aac28ffd63ed 432 * every time the orientation of ferrous metals around the IMU changes (e.g. when it is put into a new enclosure).
Jamie Smith 1:aac28ffd63ed 433 *
Jamie Smith 1:aac28ffd63ed 434 * The new calibration will not be saved in flash until you call saveCalibration().
Jamie Smith 1:aac28ffd63ed 435 *
Jamie Smith 1:aac28ffd63ed 436 * NOTE: calling this with all false values will cancel any calibration in progress. However, the calibration data being created will
Jamie Smith 1:aac28ffd63ed 437 * remain in use until the next chip reset (I think!)
Jamie Smith 1:aac28ffd63ed 438 *
Jamie Smith 1:aac28ffd63ed 439 * @param calibrateAccel Whether to calibrate the accelerometer.
Jamie Smith 1:aac28ffd63ed 440 * @param calibrateGyro Whether to calibrate the gyro.
Jamie Smith 1:aac28ffd63ed 441 * @param calibrateMag Whether to calibrate the magnetometer.
Jamie Smith 1:aac28ffd63ed 442 *
Jamie Smith 1:aac28ffd63ed 443 * @return whether the operation succeeded
Jamie Smith 1:aac28ffd63ed 444 */
Jamie Smith 1:aac28ffd63ed 445 bool enableCalibration(bool calibrateAccel, bool calibrateGyro, bool calibrateMag);
Jamie Smith 1:aac28ffd63ed 446
Jamie Smith 1:aac28ffd63ed 447 /**
Jamie Smith 1:aac28ffd63ed 448 * Saves the calibration started with startCalibration() and ends the calibration.
Jamie Smith 1:aac28ffd63ed 449 * You will want to call this once the status bits read as "accuracy high".
Jamie Smith 1:aac28ffd63ed 450 *
Jamie Smith 1:aac28ffd63ed 451 * WARNING: if you paid for a factory calibrated IMU, then this WILL OVERWRITE THE FACTORY CALIBRATION in whatever sensors
Jamie Smith 1:aac28ffd63ed 452 * are being calibrated. Use with caution!
Jamie Smith 1:aac28ffd63ed 453 *
Jamie Smith 1:aac28ffd63ed 454 * @return whether the operation succeeded
Jamie Smith 1:aac28ffd63ed 455 */
Jamie Smith 1:aac28ffd63ed 456 bool saveCalibration();
Jamie Smith 1:aac28ffd63ed 457
Jamie Smith 1:aac28ffd63ed 458 /**
Jamie Smith 1:aac28ffd63ed 459 * Sets the orientation quaternion, telling the sensor how it's mounted
Jamie Smith 1:aac28ffd63ed 460 * in relation to world space.
Jamie Smith 1:aac28ffd63ed 461 * See page 40 of the BNO080 datasheet.
Jamie Smith 1:aac28ffd63ed 462 *
Jamie Smith 1:aac28ffd63ed 463 * NOTE: this driver provides the macro SQRT_2 to help with entering values from that table.
Jamie Smith 1:aac28ffd63ed 464 *
Jamie Smith 1:aac28ffd63ed 465 * NOTE 2: this setting does not persist and will have to be re-applied every time the chip is reset.
Jamie Smith 3:197ad972fb7c 466 * Use setPermanentOrientation() for that.
Jamie Smith 1:aac28ffd63ed 467 *
Jamie Smith 1:aac28ffd63ed 468 * @param orientation quaternion mapping from IMU space to world space.
Jamie Smith 1:aac28ffd63ed 469 */
Jamie Smith 1:aac28ffd63ed 470 void setSensorOrientation(Quaternion orientation);
Jamie Smith 1:aac28ffd63ed 471
Jamie Smith 3:197ad972fb7c 472 /**
Jamie Smith 3:197ad972fb7c 473 * Sets the orientation quaternion, telling the sensor how it's mounted
Jamie Smith 3:197ad972fb7c 474 * in relation to world space. See page 40 of the BNO080 datasheet.
Jamie Smith 3:197ad972fb7c 475 *
Jamie Smith 3:197ad972fb7c 476 * Unlike setSensorOrientation(), this setting will persist across sensor restarts.
Jamie Smith 3:197ad972fb7c 477 * However, it will also take a few hundred milliseconds to write.
Jamie Smith 3:197ad972fb7c 478 *
Jamie Smith 3:197ad972fb7c 479 * @param orientation quaternion mapping from IMU space to world space.
Jamie Smith 3:197ad972fb7c 480 *
Jamie Smith 3:197ad972fb7c 481 * @return true if the operation succeeded, false if it failed.
Jamie Smith 3:197ad972fb7c 482 */
Jamie Smith 3:197ad972fb7c 483 bool setPermanentOrientation(Quaternion orientation);
Jamie Smith 9:430f5302f9e1 484
Jamie Smith 9:430f5302f9e1 485 /**
Jamie Smith 9:430f5302f9e1 486 * No-op on synchronous driver. For compatibility with BNO080Async
Jamie Smith 9:430f5302f9e1 487 */
Jamie Smith 9:430f5302f9e1 488 virtual void lockMutex()
Jamie Smith 9:430f5302f9e1 489 {}
Jamie Smith 9:430f5302f9e1 490
Jamie Smith 9:430f5302f9e1 491 /**
Jamie Smith 9:430f5302f9e1 492 * No-op on synchronous driver. For compatibility with BNO080Async
Jamie Smith 9:430f5302f9e1 493 */
Jamie Smith 9:430f5302f9e1 494 virtual void unlockMutex()
Jamie Smith 9:430f5302f9e1 495 {}
Jamie Smith 3:197ad972fb7c 496
Jamie Smith 1:aac28ffd63ed 497 // Report functions
Jamie Smith 1:aac28ffd63ed 498 //-----------------------------------------------------------------------------------------------------------------
Jamie Smith 1:aac28ffd63ed 499
Jamie Smith 1:aac28ffd63ed 500 /**
Jamie Smith 1:aac28ffd63ed 501 * Checks for new data packets queued on the IMU.
Jamie Smith 1:aac28ffd63ed 502 * If there are packets queued, receives all of them and updates
Jamie Smith 1:aac28ffd63ed 503 * the class variables with the results.
Jamie Smith 1:aac28ffd63ed 504 *
Jamie Smith 8:199c7fad233d 505 * Note that with some backends (SPI), sending commands will also update data, which can
Jamie Smith 8:199c7fad233d 506 * cause updateData() to return false even though new data has been received. hasNewData()
Jamie Smith 8:199c7fad233d 507 * is a more reliable way to determine if a sensor has new data.
Jamie Smith 8:199c7fad233d 508 *
Jamie Smith 1:aac28ffd63ed 509 * @return True iff new data packets of any kind were received. If you need more fine-grained data change reporting,
Jamie Smith 1:aac28ffd63ed 510 * check out hasNewData().
Jamie Smith 1:aac28ffd63ed 511 */
Jamie Smith 9:430f5302f9e1 512 virtual bool updateData();
Jamie Smith 1:aac28ffd63ed 513
Jamie Smith 1:aac28ffd63ed 514 /**
Jamie Smith 1:aac28ffd63ed 515 * Gets the status of a report as a 2 bit number.
Jamie Smith 1:aac28ffd63ed 516 * per SH-2 section 6.5.1, this is interpreted as: <br>
Jamie Smith 1:aac28ffd63ed 517 * 0 - unreliable <br>
Jamie Smith 1:aac28ffd63ed 518 * 1 - accuracy low <br>
Jamie Smith 1:aac28ffd63ed 519 * 2 - accuracy medium <br>
Jamie Smith 1:aac28ffd63ed 520 * 3 - accuracy high <br>
Jamie Smith 1:aac28ffd63ed 521 * of course, these are only updated if a given report is enabled.
Jamie Smith 1:aac28ffd63ed 522 * @param report
Jamie Smith 1:aac28ffd63ed 523 * @return
Jamie Smith 1:aac28ffd63ed 524 */
Jamie Smith 1:aac28ffd63ed 525 uint8_t getReportStatus(Report report);
Jamie Smith 1:aac28ffd63ed 526
Jamie Smith 1:aac28ffd63ed 527 /**
Jamie Smith 1:aac28ffd63ed 528 * Get a string for printout describing the status of a sensor.
Jamie Smith 1:aac28ffd63ed 529 * @return
Jamie Smith 1:aac28ffd63ed 530 */
Jamie Smith 1:aac28ffd63ed 531 const char* getReportStatusString(Report report);
Jamie Smith 1:aac28ffd63ed 532
Jamie Smith 1:aac28ffd63ed 533 /**
Jamie Smith 1:aac28ffd63ed 534 * Checks if a specific report has gotten new data since the last call to this function.
Jamie Smith 1:aac28ffd63ed 535 * @param report The report to check.
Jamie Smith 1:aac28ffd63ed 536 * @return Whether the report has received new data.
Jamie Smith 1:aac28ffd63ed 537 */
Jamie Smith 1:aac28ffd63ed 538 bool hasNewData(Report report);
Jamie Smith 1:aac28ffd63ed 539
Jamie Smith 1:aac28ffd63ed 540 /**
Jamie Smith 1:aac28ffd63ed 541 * Enable a data report from the IMU. Look at the comments above to see what the reports do.
Jamie Smith 1:aac28ffd63ed 542 * This function checks your polling period against the report's max speed in the IMU's metadata,
Jamie Smith 1:aac28ffd63ed 543 * and reports an error if you're trying to poll too fast.
Jamie Smith 1:aac28ffd63ed 544 *
Jamie Smith 1:aac28ffd63ed 545 * @param timeBetweenReports time in milliseconds between data updates.
Jamie Smith 1:aac28ffd63ed 546 */
Jamie Smith 1:aac28ffd63ed 547 void enableReport(Report report, uint16_t timeBetweenReports);
Jamie Smith 1:aac28ffd63ed 548
Jamie Smith 1:aac28ffd63ed 549 /**
Jamie Smith 1:aac28ffd63ed 550 * Disable a data report from the IMU.
Jamie Smith 1:aac28ffd63ed 551 *
Jamie Smith 1:aac28ffd63ed 552 * @param report The report to disable.
Jamie Smith 1:aac28ffd63ed 553 */
Jamie Smith 1:aac28ffd63ed 554 void disableReport(Report report);
Jamie Smith 1:aac28ffd63ed 555
Jamie Smith 1:aac28ffd63ed 556 /**
Jamie Smith 1:aac28ffd63ed 557 * Gets the serial number (used to uniquely identify each individual device).
Jamie Smith 1:aac28ffd63ed 558 *
Jamie Smith 1:aac28ffd63ed 559 * NOTE: this function should work according to the datasheet, but the device I was testing with appears to have
Jamie Smith 1:aac28ffd63ed 560 * an empty serial number record as shipped, and I could never get anything out of it. Your mileage may vary.
Jamie Smith 1:aac28ffd63ed 561 *
Jamie Smith 1:aac28ffd63ed 562 * @return The serial number, or 0 on error.
Jamie Smith 1:aac28ffd63ed 563 */
Jamie Smith 1:aac28ffd63ed 564 uint32_t getSerialNumber();
Jamie Smith 1:aac28ffd63ed 565
Jamie Smith 1:aac28ffd63ed 566 // Metadata functions
Jamie Smith 1:aac28ffd63ed 567 //-----------------------------------------------------------------------------------------------------------------
Jamie Smith 1:aac28ffd63ed 568
Jamie Smith 1:aac28ffd63ed 569 /**
Jamie Smith 1:aac28ffd63ed 570 * Gets the range of a report as reported by the IMU. Units are the same as the report's output data.
Jamie Smith 1:aac28ffd63ed 571 * @return
Jamie Smith 1:aac28ffd63ed 572 */
Jamie Smith 1:aac28ffd63ed 573 float getRange(Report report);
Jamie Smith 1:aac28ffd63ed 574
Jamie Smith 1:aac28ffd63ed 575 /**
Jamie Smith 1:aac28ffd63ed 576 * Gets the resolution of a report as reported by the IMU. Units are the same as the report's output data.
Jamie Smith 1:aac28ffd63ed 577 * @param report
Jamie Smith 1:aac28ffd63ed 578 * @return
Jamie Smith 1:aac28ffd63ed 579 */
Jamie Smith 1:aac28ffd63ed 580 float getResolution(Report report);
Jamie Smith 1:aac28ffd63ed 581
Jamie Smith 1:aac28ffd63ed 582 /**
Jamie Smith 1:aac28ffd63ed 583 * Get the power used by a report when it's operating, according to the IMU.
Jamie Smith 1:aac28ffd63ed 584 * @param report
Jamie Smith 1:aac28ffd63ed 585 * @return Power used in mA.
Jamie Smith 1:aac28ffd63ed 586 */
Jamie Smith 1:aac28ffd63ed 587 float getPower(Report report);
Jamie Smith 1:aac28ffd63ed 588
Jamie Smith 1:aac28ffd63ed 589 /**
Jamie Smith 1:aac28ffd63ed 590 * Gets the smallest polling period that a report supports.
Jamie Smith 1:aac28ffd63ed 591 * @return Period in seconds.
Jamie Smith 1:aac28ffd63ed 592 */
Jamie Smith 1:aac28ffd63ed 593 float getMinPeriod(Report report);
Jamie Smith 1:aac28ffd63ed 594
Jamie Smith 1:aac28ffd63ed 595 /**
Jamie Smith 1:aac28ffd63ed 596 * Gets the larges polling period that a report supports.
Jamie Smith 1:aac28ffd63ed 597 * Some reports don't have a max period, in which case this function will return -1.0.
Jamie Smith 1:aac28ffd63ed 598 *
Jamie Smith 1:aac28ffd63ed 599 * @return Period in seconds, or -1.0 on error.
Jamie Smith 1:aac28ffd63ed 600 */
Jamie Smith 1:aac28ffd63ed 601 float getMaxPeriod(Report report);
Jamie Smith 1:aac28ffd63ed 602
Jamie Smith 1:aac28ffd63ed 603 /**
Jamie Smith 1:aac28ffd63ed 604 * Prints a summary of a report's metadata to the
Jamie Smith 1:aac28ffd63ed 605 * debug stream. Should be useful for debugging and setting up reports since lots of this data
Jamie Smith 1:aac28ffd63ed 606 * isn't given in the datasheets.
Jamie Smith 1:aac28ffd63ed 607 *
Jamie Smith 1:aac28ffd63ed 608 * Note: to save string constant space, this function is only available when BNO_DEBUG is 1.
Jamie Smith 1:aac28ffd63ed 609 */
Jamie Smith 1:aac28ffd63ed 610 void printMetadataSummary(Report report);
Jamie Smith 1:aac28ffd63ed 611
Jamie Smith 8:199c7fad233d 612 protected:
Jamie Smith 1:aac28ffd63ed 613
Jamie Smith 1:aac28ffd63ed 614 // Internal metadata functions
Jamie Smith 1:aac28ffd63ed 615 //-----------------------------------------------------------------------------------------------------------------
Jamie Smith 1:aac28ffd63ed 616
Jamie Smith 1:aac28ffd63ed 617 /**
Jamie Smith 1:aac28ffd63ed 618 * Gets the version of the metadata stored in the buffer.
Jamie Smith 1:aac28ffd63ed 619 * We might see version 3 and 4 records, and they have different layouts.
Jamie Smith 1:aac28ffd63ed 620 * @return
Jamie Smith 1:aac28ffd63ed 621 */
Jamie Smith 1:aac28ffd63ed 622 uint16_t getMetaVersion() {return static_cast<uint16_t>(metadataRecord[3] >> 16);}
Jamie Smith 1:aac28ffd63ed 623
Jamie Smith 1:aac28ffd63ed 624 // @{
Jamie Smith 1:aac28ffd63ed 625 /**
Jamie Smith 1:aac28ffd63ed 626 * Gets the Q point from a report's metadata, which essentially defines where the decimal point goes in the sensor's output.
Jamie Smith 1:aac28ffd63ed 627 * The 1/2/3 Q values are used in different places in the metadata, see SH-2 section 5.1 for details.
Jamie Smith 1:aac28ffd63ed 628 * @param report
Jamie Smith 1:aac28ffd63ed 629 * @return
Jamie Smith 1:aac28ffd63ed 630 */
Jamie Smith 1:aac28ffd63ed 631 int16_t getQ1(Report report);
Jamie Smith 1:aac28ffd63ed 632 int16_t getQ2(Report report);
Jamie Smith 1:aac28ffd63ed 633 int16_t getQ3(Report report);
Jamie Smith 1:aac28ffd63ed 634 // @}
Jamie Smith 1:aac28ffd63ed 635
Jamie Smith 1:aac28ffd63ed 636 // internal utility functions
Jamie Smith 1:aac28ffd63ed 637 //-----------------------------------------------------------------------------------------------------------------
Jamie Smith 1:aac28ffd63ed 638
Jamie Smith 1:aac28ffd63ed 639 /**
Jamie Smith 1:aac28ffd63ed 640 * Processes the packet currently stored in the buffer, and updates class variables to reflect the data it contains
Jamie Smith 1:aac28ffd63ed 641 */
Jamie Smith 1:aac28ffd63ed 642 void processPacket();
Jamie Smith 1:aac28ffd63ed 643
Jamie Smith 1:aac28ffd63ed 644 /**
Jamie Smith 1:aac28ffd63ed 645 * Processes the sensor data packet currently stored in the buffer.
Jamie Smith 1:aac28ffd63ed 646 * Only called from processPacket()
Jamie Smith 1:aac28ffd63ed 647 */
Jamie Smith 1:aac28ffd63ed 648 void parseSensorDataPacket();
Jamie Smith 1:aac28ffd63ed 649
Jamie Smith 1:aac28ffd63ed 650 /**
Jamie Smith 1:aac28ffd63ed 651 * Call to wait for a packet with the given parameters to come in.
Jamie Smith 1:aac28ffd63ed 652 *
Jamie Smith 9:430f5302f9e1 653 * Note: on BNO080Async, the received packet data will stay in the RX buffer
Jamie Smith 9:430f5302f9e1 654 * until either the public IMU function that was called returns, or you
Jamie Smith 9:430f5302f9e1 655 * call sendPacket() or waitForPacket() again.
Jamie Smith 9:430f5302f9e1 656 *
Jamie Smith 1:aac28ffd63ed 657 * @param channel Channel of the packet
Jamie Smith 1:aac28ffd63ed 658 * @param reportID Report ID (first data byte) of the packet
Jamie Smith 1:aac28ffd63ed 659 * @param timeout how long to wait for the packet
Jamie Smith 1:aac28ffd63ed 660 * @return true if the packet has been received, false if it timed out
Jamie Smith 1:aac28ffd63ed 661 */
Jamie Smith 9:430f5302f9e1 662 virtual bool waitForPacket(int channel, uint8_t reportID, std::chrono::milliseconds timeout = 125ms);
Jamie Smith 1:aac28ffd63ed 663
Jamie Smith 1:aac28ffd63ed 664 /**
Jamie Smith 1:aac28ffd63ed 665 * Given a Q value, converts fixed point floating to regular floating point number.
Jamie Smith 1:aac28ffd63ed 666 * @param fixedPointValue
Jamie Smith 1:aac28ffd63ed 667 * @param qPoint
Jamie Smith 1:aac28ffd63ed 668 * @return
Jamie Smith 1:aac28ffd63ed 669 */
Jamie Smith 1:aac28ffd63ed 670 float qToFloat(int16_t fixedPointValue, uint8_t qPoint);
Jamie Smith 1:aac28ffd63ed 671
Jamie Smith 1:aac28ffd63ed 672 /**
Jamie Smith 1:aac28ffd63ed 673 * Given a Q value, converts fixed point floating to regular floating point number.
Jamie Smith 1:aac28ffd63ed 674 * This version is used for the unsigned 32-bit values in metadata records.
Jamie Smith 1:aac28ffd63ed 675 * @param fixedPointValue
Jamie Smith 1:aac28ffd63ed 676 * @param qPoint
Jamie Smith 1:aac28ffd63ed 677 * @return
Jamie Smith 1:aac28ffd63ed 678 */
Jamie Smith 1:aac28ffd63ed 679 float qToFloat_dword(uint32_t fixedPointValue, int16_t qPoint);
Jamie Smith 1:aac28ffd63ed 680
Jamie Smith 1:aac28ffd63ed 681 /**
Jamie Smith 1:aac28ffd63ed 682 * Given a floating point value and a Q point, convert to Q
Jamie Smith 1:aac28ffd63ed 683 * See https://en.wikipedia.org/wiki/Q_(number_format)
Jamie Smith 1:aac28ffd63ed 684 * @param qFloat
Jamie Smith 1:aac28ffd63ed 685 * @param qPoint
Jamie Smith 1:aac28ffd63ed 686 * @return
Jamie Smith 1:aac28ffd63ed 687 */
Jamie Smith 1:aac28ffd63ed 688 int16_t floatToQ(float qFloat, uint8_t qPoint);
Jamie Smith 1:aac28ffd63ed 689
Jamie Smith 1:aac28ffd63ed 690 /**
Jamie Smith 3:197ad972fb7c 691 * Given a floating point value and a Q point, convert to Q
Jamie Smith 3:197ad972fb7c 692 * See https://en.wikipedia.org/wiki/Q_(number_format)
Jamie Smith 3:197ad972fb7c 693 *
Jamie Smith 3:197ad972fb7c 694 * This version is used for the signed 32-bit values in metadata records.
Jamie Smith 3:197ad972fb7c 695 *
Jamie Smith 3:197ad972fb7c 696 * @param qFloat
Jamie Smith 3:197ad972fb7c 697 * @param qPoint
Jamie Smith 3:197ad972fb7c 698 * @return
Jamie Smith 3:197ad972fb7c 699 */
Jamie Smith 3:197ad972fb7c 700 int32_t floatToQ_dword(float qFloat, uint16_t qPoint);
Jamie Smith 3:197ad972fb7c 701
Jamie Smith 3:197ad972fb7c 702 /**
Jamie Smith 1:aac28ffd63ed 703 * Tell the sensor to do a command.
Jamie Smith 1:aac28ffd63ed 704 * See SH-2 Reference Manual section 6.3.8 page 42, Command request
Jamie Smith 1:aac28ffd63ed 705 * The caller is expected to set shtpData 3 though 11 prior to calling
Jamie Smith 1:aac28ffd63ed 706 */
Jamie Smith 1:aac28ffd63ed 707 void sendCommand(uint8_t command);
Jamie Smith 1:aac28ffd63ed 708
Jamie Smith 1:aac28ffd63ed 709 /**
Jamie Smith 1:aac28ffd63ed 710 * Given a sensor's report ID, this tells the BNO080 to begin reporting the values.
Jamie Smith 1:aac28ffd63ed 711 *
Jamie Smith 1:aac28ffd63ed 712 * @param reportID
Jamie Smith 1:aac28ffd63ed 713 * @param timeBetweenReports
Jamie Smith 1:aac28ffd63ed 714 * @param specificConfig the specific config word. Useful for personal activity classifier.
Jamie Smith 1:aac28ffd63ed 715 */
Jamie Smith 1:aac28ffd63ed 716 void setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports, uint32_t specificConfig = 0);
Jamie Smith 1:aac28ffd63ed 717
Jamie Smith 1:aac28ffd63ed 718 /**
Jamie Smith 1:aac28ffd63ed 719 * Read a record from the FRS (Flash Record System) on the IMU. FRS records are composed of 32-bit words,
Jamie Smith 1:aac28ffd63ed 720 * with the size of each record determined by the record type.
Jamie Smith 1:aac28ffd63ed 721 *
Jamie Smith 1:aac28ffd63ed 722 * Will block until the entire record has been read.
Jamie Smith 1:aac28ffd63ed 723 * @param recordID Record ID to read. See SH-2 figures 28 and 29 for a list of these. Sometimes also called
Jamie Smith 1:aac28ffd63ed 724 * the "FRS Type" by the datasheet (???).
Jamie Smith 1:aac28ffd63ed 725 * @param readBuffer Buffer to read data into.
Jamie Smith 1:aac28ffd63ed 726 * @param readLength Amount of words to read from the record. Must be <= the length of the record.
Jamie Smith 1:aac28ffd63ed 727 *
Jamie Smith 1:aac28ffd63ed 728 * @return whether the request succeeded
Jamie Smith 1:aac28ffd63ed 729 */
Jamie Smith 1:aac28ffd63ed 730 bool readFRSRecord(uint16_t recordID, uint32_t* readBuffer, uint16_t readLength);
Jamie Smith 1:aac28ffd63ed 731
Jamie Smith 1:aac28ffd63ed 732 /**
Jamie Smith 3:197ad972fb7c 733 * Write a record to the FRS (Flash Record System) on the IMU. FRS records are composed of 32-bit words,
Jamie Smith 3:197ad972fb7c 734 * with the size of each record determined by the record type.
Jamie Smith 3:197ad972fb7c 735 *
Jamie Smith 3:197ad972fb7c 736 * Will block until the entire record has been written.
Jamie Smith 3:197ad972fb7c 737 * @param recordID Record ID to write. See SH-2 figures 28 and 29 for a list of these. Sometimes also called
Jamie Smith 3:197ad972fb7c 738 * the "FRS Type" by the datasheet (???).
Jamie Smith 3:197ad972fb7c 739 * @param buffer Buffer to write data into.
Jamie Smith 3:197ad972fb7c 740 * @param length Amount of words to write to the record. Must be <= the length of the record.
Jamie Smith 3:197ad972fb7c 741 *
Jamie Smith 3:197ad972fb7c 742 * @return whether the request succeeded
Jamie Smith 3:197ad972fb7c 743 */
Jamie Smith 3:197ad972fb7c 744 bool writeFRSRecord(uint16_t recordID, uint32_t* buffer, uint16_t length);
Jamie Smith 3:197ad972fb7c 745
Jamie Smith 3:197ad972fb7c 746 /**
Jamie Smith 1:aac28ffd63ed 747 * Reads a packet from the IMU and stores it in the class variables.
Jamie Smith 1:aac28ffd63ed 748 *
Jamie Smith 1:aac28ffd63ed 749 * @param timeout how long to wait for there to be a packet
Jamie Smith 1:aac28ffd63ed 750 *
Jamie Smith 1:aac28ffd63ed 751 * @return whether a packet was recieved.
Jamie Smith 1:aac28ffd63ed 752 */
Jamie Smith 8:199c7fad233d 753 virtual bool receivePacket(std::chrono::milliseconds timeout=200ms) = 0;
Jamie Smith 1:aac28ffd63ed 754
Jamie Smith 1:aac28ffd63ed 755 /**
Jamie Smith 1:aac28ffd63ed 756 * Sends the current shtpData contents to the BNO. It's a good idea to disable interrupts before you call this.
Jamie Smith 1:aac28ffd63ed 757 *
Jamie Smith 1:aac28ffd63ed 758 * @param channelNumber the channel to send on
Jamie Smith 1:aac28ffd63ed 759 * @param dataLength How many bits of shtpData to send
Jamie Smith 1:aac28ffd63ed 760 * @return
Jamie Smith 1:aac28ffd63ed 761 */
Jamie Smith 8:199c7fad233d 762 virtual bool sendPacket(uint8_t channelNumber, uint8_t dataLength) = 0;
Jamie Smith 1:aac28ffd63ed 763
Jamie Smith 1:aac28ffd63ed 764 /**
Jamie Smith 1:aac28ffd63ed 765 * Prints the current shtp packet stored in the buffer.
Jamie Smith 1:aac28ffd63ed 766 * @param length
Jamie Smith 1:aac28ffd63ed 767 */
Jamie Smith 8:199c7fad233d 768 void printPacket(uint8_t * buffer);
Jamie Smith 1:aac28ffd63ed 769
Jamie Smith 1:aac28ffd63ed 770 /**
Jamie Smith 9:430f5302f9e1 771 * Erases the current SHTP TX packet buffer.
Jamie Smith 9:430f5302f9e1 772 * In BNO080Async, this blocks until the buffer is available.
Jamie Smith 1:aac28ffd63ed 773 */
Jamie Smith 9:430f5302f9e1 774 virtual void clearSendBuffer();
Jamie Smith 1:aac28ffd63ed 775
Jamie Smith 1:aac28ffd63ed 776 /**
Jamie Smith 1:aac28ffd63ed 777 * Loads the metadata for this report into the metadata buffer.
Jamie Smith 1:aac28ffd63ed 778 * @param report
Jamie Smith 1:aac28ffd63ed 779 * @return Whether the operation succeeded.
Jamie Smith 1:aac28ffd63ed 780 */
Jamie Smith 1:aac28ffd63ed 781 bool loadReportMetadata(Report report);
Jamie Smith 1:aac28ffd63ed 782
Jamie Smith 1:aac28ffd63ed 783 };
Jamie Smith 1:aac28ffd63ed 784
Jamie Smith 8:199c7fad233d 785 /**
Jamie Smith 8:199c7fad233d 786 * Version of the BNO080 driver which uses the I2C interface
Jamie Smith 8:199c7fad233d 787 */
Jamie Smith 8:199c7fad233d 788 class BNO080I2C : public BNO080Base
Jamie Smith 8:199c7fad233d 789 {
Jamie Smith 8:199c7fad233d 790 /**
Jamie Smith 8:199c7fad233d 791 * I2C port object. Provides physical layer communications with the chip.
Jamie Smith 8:199c7fad233d 792 */
Jamie Smith 8:199c7fad233d 793 I2C _i2cPort;
Jamie Smith 8:199c7fad233d 794
Jamie Smith 8:199c7fad233d 795 /// user defined port speed
Jamie Smith 8:199c7fad233d 796 int _i2cPortSpeed;
Jamie Smith 8:199c7fad233d 797
Jamie Smith 8:199c7fad233d 798 /// i2c address of IMU (7 bits)
Jamie Smith 8:199c7fad233d 799 uint8_t _i2cAddress;
Jamie Smith 8:199c7fad233d 800 public:
Jamie Smith 8:199c7fad233d 801
Jamie Smith 8:199c7fad233d 802 /**
Jamie Smith 8:199c7fad233d 803 * Construct a BNO080 driver for the I2C bus, providing pins and parameters.
Jamie Smith 8:199c7fad233d 804 *
Jamie Smith 8:199c7fad233d 805 * This doesn't actally initialize the chip, you will need to call begin() for that.
Jamie Smith 8:199c7fad233d 806 *
Jamie Smith 8:199c7fad233d 807 * NOTE: while some schematics tell you to connect the BOOTN pin to the processor, this driver does not use or require it.
Jamie Smith 8:199c7fad233d 808 * Just tie it to VCC per the datasheet.
Jamie Smith 8:199c7fad233d 809 *
Jamie Smith 8:199c7fad233d 810 * @param debugPort Serial port to write output to. Cannot be nullptr.
Jamie Smith 8:199c7fad233d 811 * @param user_SDApin Hardware I2C SDA pin connected to the IMU
Jamie Smith 8:199c7fad233d 812 * @param user_SCLpin Hardware I2C SCL pin connected to the IMU
Jamie Smith 8:199c7fad233d 813 * @param user_INTPin Input pin connected to HINTN
Jamie Smith 8:199c7fad233d 814 * @param user_RSTPin Output pin connected to NRST
Jamie Smith 8:199c7fad233d 815 * @param i2cAddress I2C address. The BNO defaults to 0x4a, but can also be set to 0x4b via a pin.
Jamie Smith 8:199c7fad233d 816 * @param i2cPortSpeed I2C frequency. The BNO's max is 400kHz.
Jamie Smith 8:199c7fad233d 817 */
Jamie Smith 8:199c7fad233d 818 BNO080I2C(Stream *debugPort, PinName user_SDApin, PinName user_SCLpin, PinName user_INTPin, PinName user_RSTPin, uint8_t i2cAddress=0x4a, int i2cPortSpeed=400000);
Jamie Smith 8:199c7fad233d 819
Jamie Smith 8:199c7fad233d 820 private:
Jamie Smith 8:199c7fad233d 821
Jamie Smith 8:199c7fad233d 822 bool receivePacket(std::chrono::milliseconds timeout=200ms) override;
Jamie Smith 8:199c7fad233d 823
Jamie Smith 8:199c7fad233d 824 bool sendPacket(uint8_t channelNumber, uint8_t dataLength) override;
Jamie Smith 8:199c7fad233d 825 };
Jamie Smith 8:199c7fad233d 826
Jamie Smith 8:199c7fad233d 827 // typedef for compatibility with old version of driver where there was no SPI
Jamie Smith 8:199c7fad233d 828 typedef BNO080I2C BNO080;
Jamie Smith 8:199c7fad233d 829
Jamie Smith 8:199c7fad233d 830 /**
Jamie Smith 8:199c7fad233d 831 * Version of the BNO080 driver which uses the SPI interface.
Jamie Smith 8:199c7fad233d 832 * WARNING: The SPI interface, unlike the I2C interface, of this chip
Jamie Smith 8:199c7fad233d 833 * has some god-awful timing requirements that are difficult to satisfy.
Jamie Smith 8:199c7fad233d 834 *
Jamie Smith 8:199c7fad233d 835 * In order for the chip to produce data, you must call updateData() at at more than
Jamie Smith 8:199c7fad233d 836 * twice the frequency of the fastest sensor poll rate you have set.
Jamie Smith 8:199c7fad233d 837 * Otherwise, for reasons that I don't exactly understand, the IMU
Jamie Smith 8:199c7fad233d 838 * will have some kind of internal watchdog timeout error and shut itself down.
Jamie Smith 8:199c7fad233d 839 * Also, you have about 500ms after calling begin() to configure reports and start
Jamie Smith 8:199c7fad233d 840 * receiving data, or the same thing happens.
Jamie Smith 8:199c7fad233d 841 *
Jamie Smith 8:199c7fad233d 842 * If this timing error happens to you, the symptoms are strange: the IMU will just stop sending data, several seconds later.
Jamie Smith 8:199c7fad233d 843 * No error or anything, just no data.
Jamie Smith 8:199c7fad233d 844 * To recover from the error, you would have to call begin() again and reconfigure it from scratch.
Jamie Smith 8:199c7fad233d 845 *
Jamie Smith 8:199c7fad233d 846 */
Jamie Smith 8:199c7fad233d 847 class BNO080SPI : public BNO080Base
Jamie Smith 8:199c7fad233d 848 {
Jamie Smith 9:430f5302f9e1 849 protected:
Jamie Smith 8:199c7fad233d 850 /**
Jamie Smith 8:199c7fad233d 851 * I2C port object. Provides physical layer communications with the chip.
Jamie Smith 8:199c7fad233d 852 */
Jamie Smith 8:199c7fad233d 853 SPI _spiPort;
Jamie Smith 8:199c7fad233d 854
Jamie Smith 8:199c7fad233d 855 // Wake pin to signal the IMU to wake up
Jamie Smith 8:199c7fad233d 856 DigitalOut _wakePin;
Jamie Smith 8:199c7fad233d 857
Jamie Smith 8:199c7fad233d 858 /// user defined port speed
Jamie Smith 8:199c7fad233d 859 int _spiSpeed;
Jamie Smith 8:199c7fad233d 860 public:
Jamie Smith 8:199c7fad233d 861
Jamie Smith 8:199c7fad233d 862 /**
Jamie Smith 8:199c7fad233d 863 * Construct a BNO080 driver for the SPI bus, providing pins and parameters.
Jamie Smith 8:199c7fad233d 864 *
Jamie Smith 8:199c7fad233d 865 * This doesn't actually initialize the chip, you will need to call begin() for that.
Jamie Smith 8:199c7fad233d 866 *
Jamie Smith 8:199c7fad233d 867 * NOTE: while some schematics tell you to connect the BOOTN pin to the processor, this driver does not use or require it.
Jamie Smith 8:199c7fad233d 868 * Just tie it to VCC per the datasheet.
Jamie Smith 8:199c7fad233d 869 *
Jamie Smith 8:199c7fad233d 870 * @param debugPort Serial port to write output to. Cannot be nullptr.
Jamie Smith 8:199c7fad233d 871 * @param rstPin Hardware reset pin, resets the IMU
Jamie Smith 8:199c7fad233d 872 * @param intPin Hardware interrupt pin, this is used for the IMU to signal the host that it has a message to send
Jamie Smith 8:199c7fad233d 873 * @param wakePin Hardware wake pin, this is used by the processor to signal the BNO to wake up and receive a message
Jamie Smith 8:199c7fad233d 874 * @param misoPin SPI MISO pin
Jamie Smith 8:199c7fad233d 875 * @param mosiPin SPI MOSI pin
Jamie Smith 8:199c7fad233d 876 * @param sclkPin SPI SCLK pin
Jamie Smith 8:199c7fad233d 877 * @param csPin SPI CS pin
Jamie Smith 8:199c7fad233d 878 * @param spiSpeed SPI frequency. The BNO's max is 3MHz.
Jamie Smith 8:199c7fad233d 879 */
Jamie Smith 8:199c7fad233d 880 BNO080SPI(Stream *debugPort, PinName rstPin, PinName intPin, PinName wakePin, PinName misoPin, PinName mosiPin, PinName sclkPin, PinName csPin, int spiSpeed=3000000);
Jamie Smith 8:199c7fad233d 881
Jamie Smith 9:430f5302f9e1 882 protected:
Jamie Smith 8:199c7fad233d 883
Jamie Smith 8:199c7fad233d 884 bool receivePacket(std::chrono::milliseconds timeout=200ms) override;
Jamie Smith 8:199c7fad233d 885
Jamie Smith 8:199c7fad233d 886 bool sendPacket(uint8_t channelNumber, uint8_t dataLength) override;
Jamie Smith 8:199c7fad233d 887
Jamie Smith 8:199c7fad233d 888 /**
Jamie Smith 8:199c7fad233d 889 * Assuming that at least a packet header has been read into the RX buffer, receive the remainder of the packet.
Jamie Smith 8:199c7fad233d 890 * @param bytesRead The number of bytes (including the header) of the packet that have already been read.
Jamie Smith 8:199c7fad233d 891 * @return
Jamie Smith 8:199c7fad233d 892 */
Jamie Smith 8:199c7fad233d 893 bool receiveCompletePacket(size_t bytesRead, std::chrono::milliseconds timeout=200ms);
Jamie Smith 9:430f5302f9e1 894
Jamie Smith 9:430f5302f9e1 895 #if USE_ASYNC_SPI
Jamie Smith 9:430f5302f9e1 896
Jamie Smith 9:430f5302f9e1 897 /**
Jamie Smith 9:430f5302f9e1 898 * Start an SPI transfer and suspend the current thread until it is complete.
Jamie Smith 9:430f5302f9e1 899 * Used by functions in BNO080SPI.
Jamie Smith 9:430f5302f9e1 900 * Note: should only be called by one thread at a time.
Jamie Smith 9:430f5302f9e1 901 * @param tx_buffer
Jamie Smith 9:430f5302f9e1 902 * @param tx_length
Jamie Smith 9:430f5302f9e1 903 * @param rx_buffer
Jamie Smith 9:430f5302f9e1 904 * @param rx_length
Jamie Smith 9:430f5302f9e1 905 */
Jamie Smith 9:430f5302f9e1 906 void spiTransferAndWait(const uint8_t *tx_buffer, int tx_length, uint8_t *rx_buffer, int rx_length);
Jamie Smith 9:430f5302f9e1 907
Jamie Smith 9:430f5302f9e1 908 // callback for finished SPI transfers
Jamie Smith 9:430f5302f9e1 909 void onSPITransferComplete(int event);
Jamie Smith 9:430f5302f9e1 910
Jamie Smith 9:430f5302f9e1 911 // Signal whan an SPI transfer is complete.
Jamie Smith 9:430f5302f9e1 912 EventFlags spiCompleteFlag;
Jamie Smith 9:430f5302f9e1 913
Jamie Smith 9:430f5302f9e1 914 #else
Jamie Smith 9:430f5302f9e1 915
Jamie Smith 9:430f5302f9e1 916 /**
Jamie Smith 9:430f5302f9e1 917 * Start an SPI transfer and wait for it to complete.
Jamie Smith 9:430f5302f9e1 918 * BNO080Async swaps in a threaded implementation here.
Jamie Smith 9:430f5302f9e1 919 * API same as SPI::write().
Jamie Smith 9:430f5302f9e1 920 */
Jamie Smith 9:430f5302f9e1 921 void spiTransferAndWait(const uint8_t *tx_buffer, int tx_length, uint8_t *rx_buffer, int rx_length)
Jamie Smith 9:430f5302f9e1 922 {
Jamie Smith 9:430f5302f9e1 923 _spiPort.write(reinterpret_cast<const char *>(tx_buffer), tx_length, reinterpret_cast<char *>(rx_buffer), rx_length);
Jamie Smith 9:430f5302f9e1 924 }
Jamie Smith 9:430f5302f9e1 925 #endif
Jamie Smith 8:199c7fad233d 926 };
Jamie Smith 8:199c7fad233d 927
Jamie Smith 1:aac28ffd63ed 928 #endif //HAMSTER_BNO080_H