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
BNO080Constants.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 | // Constants used in communication with the BNO080 |
Jamie Smith |
1:aac28ffd63ed | 3 | // |
Jamie Smith |
1:aac28ffd63ed | 4 | |
Jamie Smith |
1:aac28ffd63ed | 5 | #ifndef HAMSTER_BNO080CONSTANTS_H |
Jamie Smith |
1:aac28ffd63ed | 6 | #define HAMSTER_BNO080CONSTANTS_H |
Jamie Smith |
1:aac28ffd63ed | 7 | |
Jamie Smith |
1:aac28ffd63ed | 8 | |
Jamie Smith |
1:aac28ffd63ed | 9 | //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= |
Jamie Smith |
1:aac28ffd63ed | 10 | |
Jamie Smith |
3:197ad972fb7c | 11 | // Channels |
Jamie Smith |
1:aac28ffd63ed | 12 | #define CHANNEL_COMMAND 0 |
Jamie Smith |
1:aac28ffd63ed | 13 | #define CHANNEL_EXECUTABLE 1 |
Jamie Smith |
1:aac28ffd63ed | 14 | #define CHANNEL_CONTROL 2 |
Jamie Smith |
1:aac28ffd63ed | 15 | #define CHANNEL_REPORTS 3 |
Jamie Smith |
1:aac28ffd63ed | 16 | #define CHANNEL_WAKE_REPORTS 4 |
Jamie Smith |
1:aac28ffd63ed | 17 | #define CHANNEL_GYRO 5 |
Jamie Smith |
1:aac28ffd63ed | 18 | |
Jamie Smith |
1:aac28ffd63ed | 19 | // Report IDs on the command channel. |
Jamie Smith |
1:aac28ffd63ed | 20 | // Unlike the other constants, these come from the Sensor Hub Transport Protocol datasheet, section 5.1 |
Jamie Smith |
1:aac28ffd63ed | 21 | #define COMMAND_REPORTID_ADVERTISEMENT 0x0 |
Jamie Smith |
1:aac28ffd63ed | 22 | #define COMMAND_REPORTID_ERRORLIST 0x1 |
Jamie Smith |
1:aac28ffd63ed | 23 | |
Jamie Smith |
1:aac28ffd63ed | 24 | //All the ways we can configure or talk to the BNO080, figure 34, page 36 reference manual |
Jamie Smith |
1:aac28ffd63ed | 25 | //These are used for low level communication with the sensor, on channel 2 |
Jamie Smith |
1:aac28ffd63ed | 26 | #define SHTP_REPORT_COMMAND_RESPONSE 0xF1 |
Jamie Smith |
1:aac28ffd63ed | 27 | #define SHTP_REPORT_COMMAND_REQUEST 0xF2 |
Jamie Smith |
1:aac28ffd63ed | 28 | #define SHTP_REPORT_FRS_READ_RESPONSE 0xF3 |
Jamie Smith |
1:aac28ffd63ed | 29 | #define SHTP_REPORT_FRS_READ_REQUEST 0xF4 |
Jamie Smith |
3:197ad972fb7c | 30 | #define SHTP_REPORT_FRS_WRITE_RESPONSE 0xF5 |
Jamie Smith |
3:197ad972fb7c | 31 | #define SHTP_REPORT_FRS_WRITE_DATA 0xF6 |
Jamie Smith |
3:197ad972fb7c | 32 | #define SHTP_REPORT_FRS_WRITE_REQUEST 0xF7 |
Jamie Smith |
1:aac28ffd63ed | 33 | #define SHTP_REPORT_PRODUCT_ID_RESPONSE 0xF8 |
Jamie Smith |
1:aac28ffd63ed | 34 | #define SHTP_REPORT_PRODUCT_ID_REQUEST 0xF9 |
Jamie Smith |
1:aac28ffd63ed | 35 | #define SHTP_REPORT_BASE_TIMESTAMP 0xFB |
Jamie Smith |
1:aac28ffd63ed | 36 | #define SHTP_REPORT_SET_FEATURE_COMMAND 0xFD |
Jamie Smith |
1:aac28ffd63ed | 37 | #define SHTP_REPORT_GET_FEATURE_RESPONSE 0xFC |
Jamie Smith |
1:aac28ffd63ed | 38 | |
Jamie Smith |
1:aac28ffd63ed | 39 | //All the different sensors and features we can get reports from |
Jamie Smith |
1:aac28ffd63ed | 40 | //These are used when enabling a given sensor |
Jamie Smith |
1:aac28ffd63ed | 41 | #define SENSOR_REPORTID_TIMESTAMP_REBASE 0xFA |
Jamie Smith |
1:aac28ffd63ed | 42 | #define SENSOR_REPORTID_ACCELEROMETER 0x01 |
Jamie Smith |
1:aac28ffd63ed | 43 | #define SENSOR_REPORTID_GYROSCOPE_CALIBRATED 0x02 |
Jamie Smith |
1:aac28ffd63ed | 44 | #define SENSOR_REPORTID_MAGNETIC_FIELD_CALIBRATED 0x03 |
Jamie Smith |
1:aac28ffd63ed | 45 | #define SENSOR_REPORTID_LINEAR_ACCELERATION 0x04 |
Jamie Smith |
1:aac28ffd63ed | 46 | #define SENSOR_REPORTID_ROTATION_VECTOR 0x05 |
Jamie Smith |
1:aac28ffd63ed | 47 | #define SENSOR_REPORTID_GRAVITY 0x06 |
Jamie Smith |
1:aac28ffd63ed | 48 | #define SENSOR_REPORTID_GAME_ROTATION_VECTOR 0x08 |
Jamie Smith |
1:aac28ffd63ed | 49 | #define SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR 0x09 |
Jamie Smith |
1:aac28ffd63ed | 50 | #define SENSOR_REPORTID_MAGNETIC_FIELD_UNCALIBRATED 0x0F |
Jamie Smith |
1:aac28ffd63ed | 51 | #define SENSOR_REPORTID_TAP_DETECTOR 0x10 |
Jamie Smith |
1:aac28ffd63ed | 52 | #define SENSOR_REPORTID_STEP_COUNTER 0x11 |
Jamie Smith |
1:aac28ffd63ed | 53 | #define SENSOR_REPORTID_SIGNIFICANT_MOTION 0x12 |
Jamie Smith |
1:aac28ffd63ed | 54 | #define SENSOR_REPORTID_STABILITY_CLASSIFIER 0x13 |
Jamie Smith |
1:aac28ffd63ed | 55 | #define SENSOR_REPORTID_STEP_DETECTOR 0x18 |
Jamie Smith |
1:aac28ffd63ed | 56 | #define SENSOR_REPORTID_SHAKE_DETECTOR 0x19 |
Jamie Smith |
1:aac28ffd63ed | 57 | |
Jamie Smith |
1:aac28ffd63ed | 58 | // sensor report ID with the largest numeric value |
Jamie Smith |
1:aac28ffd63ed | 59 | #define MAX_SENSOR_REPORTID SENSOR_REPORTID_SHAKE_DETECTOR |
Jamie Smith |
1:aac28ffd63ed | 60 | |
Jamie Smith |
1:aac28ffd63ed | 61 | // Q points for various sensor data elements |
Jamie Smith |
1:aac28ffd63ed | 62 | #define ACCELEROMETER_Q_POINT 8 // for accelerometer based data |
Jamie Smith |
1:aac28ffd63ed | 63 | #define GYRO_Q_POINT 9 // for gyroscope data |
Jamie Smith |
1:aac28ffd63ed | 64 | #define MAGNETOMETER_Q_POINT 4 // for magnetometer data |
Jamie Smith |
1:aac28ffd63ed | 65 | #define ROTATION_Q_POINT 14 // for rotation data |
Jamie Smith |
1:aac28ffd63ed | 66 | #define ROTATION_ACCURACY_Q_POINT 12 // for rotation accuracy data |
Jamie Smith |
1:aac28ffd63ed | 67 | #define POWER_Q_POINT 10 // for power information in the metadata |
Jamie Smith |
1:aac28ffd63ed | 68 | #define ORIENTATION_QUAT_Q_POINT 14 // for the set orientation command |
Jamie Smith |
3:197ad972fb7c | 69 | #define FRS_ORIENTATION_Q_POINT 30 // for the sensor orientation FRS record |
Jamie Smith |
1:aac28ffd63ed | 70 | |
Jamie Smith |
1:aac28ffd63ed | 71 | // Report IDs on the Executable channel |
Jamie Smith |
1:aac28ffd63ed | 72 | // See Figure 1-27 in the BNO080 datasheet |
Jamie Smith |
1:aac28ffd63ed | 73 | #define EXECUTABLE_REPORTID_RESET 0x1 |
Jamie Smith |
1:aac28ffd63ed | 74 | |
Jamie Smith |
1:aac28ffd63ed | 75 | //Record IDs from SH-2 figure 28 |
Jamie Smith |
1:aac28ffd63ed | 76 | //These are used to read and set various configuration options |
Jamie Smith |
1:aac28ffd63ed | 77 | #define FRS_RECORDID_SERIAL_NUMBER 0x4B4B |
Jamie Smith |
3:197ad972fb7c | 78 | #define FRS_RECORDID_SYSTEM_ORIENTATION 0x2D3E |
Jamie Smith |
1:aac28ffd63ed | 79 | |
Jamie Smith |
1:aac28ffd63ed | 80 | //Command IDs from section 6.4, page 42 |
Jamie Smith |
1:aac28ffd63ed | 81 | //These are used to calibrate, initialize, set orientation, tare etc the sensor |
Jamie Smith |
1:aac28ffd63ed | 82 | #define COMMAND_ERRORS 1 |
Jamie Smith |
1:aac28ffd63ed | 83 | #define COMMAND_COUNTER 2 |
Jamie Smith |
1:aac28ffd63ed | 84 | #define COMMAND_TARE 3 |
Jamie Smith |
1:aac28ffd63ed | 85 | #define COMMAND_INITIALIZE 4 |
Jamie Smith |
1:aac28ffd63ed | 86 | #define COMMAND_SAVE_DCD 6 |
Jamie Smith |
1:aac28ffd63ed | 87 | #define COMMAND_ME_CALIBRATE 7 |
Jamie Smith |
1:aac28ffd63ed | 88 | #define COMMAND_DCD_PERIOD_SAVE 9 |
Jamie Smith |
1:aac28ffd63ed | 89 | #define COMMAND_OSCILLATOR 10 |
Jamie Smith |
1:aac28ffd63ed | 90 | #define COMMAND_CLEAR_DCD 11 |
Jamie Smith |
1:aac28ffd63ed | 91 | #define COMMAND_UNSOLICITED_INITIALIZE 0x84 |
Jamie Smith |
1:aac28ffd63ed | 92 | |
Jamie Smith |
1:aac28ffd63ed | 93 | #define CALIBRATE_ACCEL 0 |
Jamie Smith |
1:aac28ffd63ed | 94 | #define CALIBRATE_GYRO 1 |
Jamie Smith |
1:aac28ffd63ed | 95 | #define CALIBRATE_MAG 2 |
Jamie Smith |
1:aac28ffd63ed | 96 | #define CALIBRATE_PLANAR_ACCEL 3 |
Jamie Smith |
1:aac28ffd63ed | 97 | #define CALIBRATE_ACCEL_GYRO_MAG 4 |
Jamie Smith |
1:aac28ffd63ed | 98 | #define CALIBRATE_STOP 5 |
Jamie Smith |
1:aac28ffd63ed | 99 | |
Jamie Smith |
1:aac28ffd63ed | 100 | // timing for reset |
Jamie Smith |
1:aac28ffd63ed | 101 | // per my measurement, reset takes about 90ms, so let's take twice that |
Jamie Smith |
3:197ad972fb7c | 102 | // By the way, I discovered (by accident) that a symptom of brownout is the chip taking |
Jamie Smith |
3:197ad972fb7c | 103 | // a long time to reset. So if you had to increase this, check that your Vcc is |
Jamie Smith |
3:197ad972fb7c | 104 | // within the allowed range. |
Jamie Smith |
8:199c7fad233d | 105 | #define BNO080_RESET_TIMEOUT 180ms |
Jamie Smith |
1:aac28ffd63ed | 106 | |
Jamie Smith |
1:aac28ffd63ed | 107 | #endif //HAMSTER_BNO080CONSTANTS_H |