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
BNO080.h@9:430f5302f9e1, 2020-11-24 (annotated)
- 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?
User | Revision | Line number | New 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 |