├── .gitattributes ├── .github └── workflows │ └── add_issue_to_project.yml ├── .gitignore ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE.md ├── LICENSE.md ├── README.md ├── examples ├── Example_01_RotationVector │ └── Example_01_RotationVector.ino ├── Example_02_Accelerometer │ └── Example_02_Accelerometer.ino ├── Example_03_Gyro │ └── Example_03_Gyro.ino ├── Example_04_Magnetometer │ └── Example_04_Magnetometer.ino ├── Example_05_StepCounter │ └── Example_05_StepCounter.ino ├── Example_06_StabilityClassifier │ └── Example_06_StabilityClassifier.ino ├── Example_07_ActivityClassifier │ └── Example_07_ActivityClassifier.ino ├── Example_08_AdvancedConfig │ └── Example_08_AdvancedConfig.ino ├── Example_09_LinearAccelerometer │ └── Example_09_LinearAccelerometer.ino ├── Example_10_TimeStamp │ └── Example_10_TimeStamp.ino ├── Example_11_RawReadings │ └── Example_11_RawReadings.ino ├── Example_12_GyroIntegratedRotationVector │ └── Example_12_GyroIntegratedRotationVector.ino ├── Example_13_EulerAngles │ └── Example_13_EulerAngles.ino ├── Example_14_Tare │ └── Example_14_Tare.ino ├── Example_15_Gravity │ └── Example_15_Gravity.ino ├── Example_16_UncalibratedGyro │ └── Example_16_UncalibratedGyro.ino ├── Example_17_ResetCheck │ └── Example_17_ResetCheck.ino ├── Example_18_Sleep │ └── Example_18_Sleep.ino ├── Example_19_GeomagneticRotationVector_to_EulerAngles │ └── Example_19_GeomagneticRotationVector_to_EulerAngles.ino ├── Example_20_CalibrationSettings │ └── Example_20_CalibrationSettings.ino └── SPI │ ├── Example_01_SPI_RotationVector │ └── Example_01_SPI_RotationVector.ino │ ├── Example_02_SPI_ResetCheck │ └── Example_02_SPI_ResetCheck.ino │ └── Example_03_SPI_Sleep │ └── Example_03_SPI_Sleep.ino ├── keywords.txt ├── library.properties └── src ├── NOTICE.txt ├── SparkFun_BNO08x_Arduino_Library.cpp ├── SparkFun_BNO08x_Arduino_Library.h ├── sh2.c ├── sh2.h ├── sh2_SensorValue.c ├── sh2_SensorValue.h ├── sh2_err.h ├── sh2_hal.h ├── sh2_util.c ├── sh2_util.h ├── shtp.c └── shtp.h /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.github/workflows/add_issue_to_project.yml: -------------------------------------------------------------------------------- 1 | name: Add new issue to our main project 2 | 3 | on: 4 | issues: 5 | types: 6 | - opened 7 | 8 | jobs: 9 | add-to-project: 10 | name: Add issue to project 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/add-to-project@main 14 | with: 15 | # You can target a project in a different organization 16 | # to the issue 17 | project-url: https://github.com/orgs/sparkfun/projects/19 18 | github-token: ${{ secrets.DEFECT_ADD_TO_PROJECT }} 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear in the root of a volume 35 | .DocumentRevisions-V100 36 | .fseventsd 37 | .Spotlight-V100 38 | .TemporaryItems 39 | .Trashes 40 | .VolumeIcon.icns 41 | 42 | # Directories potentially created on remote AFP share 43 | .AppleDB 44 | .AppleDesktop 45 | Network Trash Folder 46 | Temporary Items 47 | .apdisk 48 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ### How to Contribute 2 | 3 | Thank you so *much* for offering to help out. We truly appreciate it. 4 | 5 | If you'd like to contribute, start by searching through the [issues](https://github.com/sparkfun/SparkFun_BNO08x_Arduino_Library/issues) and [pull requests](https://github.com/sparkfun/SparkFun_BNO08x_Arduino_Library/pulls) to see whether someone else has raised a similar idea or question. 6 | 7 | If you decide to add a feature to this library, please create a PR following these best practices: 8 | 9 | - Change as little as possible. Do not sumbit a PR that changes 100 lines of whitespace. Break up into multiple PRs if necessary. 10 | - If you've added a new feature document it with a simple example sketch. This serves both as a test of your PR and as a quick way for users to quickly learn how to use your new feature. 11 | - If you add new functions also add them to keywords.txt so that they are properly highlighted in Arduino. [Read more](https://www.arduino.cc/en/Hacking/libraryTutorial). 12 | - Please submit your PR using the [release-candidate branch](https://github.com/sparkfun/SparkFun_BNO08x_Arduino_Library/tree/release-candidate). That way, we can merge and test your PR quickly without changing the _main_ branch 13 | 14 | ## Style guide 15 | 16 | Please read and follow the [Arduino API style guide](https://www.arduino.cc/en/Reference/APIStyleGuide). Also read and consider the [Arduino style guide](https://www.arduino.cc/en/Reference/StyleGuide). 17 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Subject of the issue 2 | Describe your issue here. 3 | 4 | ### Your workbench 5 | * What development board or microcontroller are you using? 6 | * What version of hardware or breakout board are you using? 7 | * How is the breakout board to your microcontroller? 8 | * How is everything being powered? 9 | * Are there any additional details that may help us help you? 10 | 11 | ### Steps to reproduce 12 | Tell us how to reproduce this issue. Please post stripped down example code demonstrating your issue. 13 | 14 | ### Expected behavior 15 | Tell us what should happen 16 | 17 | ### Actual behavior 18 | Tell us what happens instead 19 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | SparkFun License Information 2 | ============================ 3 | 4 | SparkFun uses two different licenses for our files — one for hardware and one for code. 5 | 6 | Hardware 7 | --------- 8 | 9 | **SparkFun hardware is released under [Creative Commons Share-alike 4.0 International](http://creativecommons.org/licenses/by-sa/4.0/).** 10 | 11 | Note: This is a human-readable summary of (and not a substitute for) the [license](http://creativecommons.org/licenses/by-sa/4.0/legalcode). 12 | 13 | You are free to: 14 | 15 | Share — copy and redistribute the material in any medium or format 16 | Adapt — remix, transform, and build upon the material 17 | for any purpose, even commercially. 18 | The licensor cannot revoke these freedoms as long as you follow the license terms. 19 | Under the following terms: 20 | 21 | Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. 22 | ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 23 | No additional restrictions — You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits. 24 | Notices: 25 | 26 | You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation. 27 | No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material. 28 | 29 | 30 | Code 31 | -------- 32 | 33 | **SparkFun code, firmware, and software is released under the MIT License(http://opensource.org/licenses/MIT).** 34 | 35 | The MIT License (MIT) 36 | 37 | Copyright (c) 2023 SparkFun Electronics 38 | 39 | Permission is hereby granted, free of charge, to any person obtaining a copy 40 | of this software and associated documentation files (the "Software"), to deal 41 | in the Software without restriction, including without limitation the rights 42 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 43 | copies of the Software, and to permit persons to whom the Software is 44 | furnished to do so, subject to the following conditions: 45 | 46 | The above copyright notice and this permission notice shall be included in all 47 | copies or substantial portions of the Software. 48 | 49 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 50 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 51 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 52 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 53 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 54 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 55 | SOFTWARE. 56 | 57 | /************* Attribution to prior included work ****************/ 58 | 59 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 60 | 61 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 62 | CEVA Sensor Hub Driver, found here: 63 | https://github.com/ceva-dsp/sh2 64 | 65 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 66 | for Adafruit Industries. Found here: 67 | https://github.com/adafruit/Adafruit_BNO08x 68 | 69 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 70 | BusIO library found here: 71 | https://github.com/adafruit/Adafruit_BusIO -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | SparkFun VR IMU BNO08X Arduino Library 2 | =========================================================== 3 | 4 | [![SparkFun VR IMU Breakout - BNO086 (Qwiic)](https://cdn.sparkfun.com/r/600-600/assets/parts/2/3/0/2/7/22857-SEN_SparkFun_VR_IMU_Breakout-BNO086_Qwiic-_01.jpg)](https://www.sparkfun.com/products/22857) 5 | 6 | [*SparkFun VR IMU Breakout - BNO086 (Qwiic)(SEN-22857)*](https://www.sparkfun.com/products/22857) 7 | 8 | An Arduino Library for the BNO08x IMU combination triple axis accelerometer/gyro/magnetometer packaged with an ARM Cortex M0+ running powerful algorithms. 9 | 10 | The BNO08x IMU has a combination triple axis accelerometer/gyro/magnetometer packaged with an ARM© Cortex™ M0+ running powerful algorithms. This enables the BNO08x Inertial Measurement Unit (IMU) to produce accurate rotation vector headings with an error of 2 degrees or less. It's what we've been waiting for: all the sensor data is combined into meaningful, accurate IMU information. 11 | 12 | This IC was designed to be implemented in Android based cellular phones to handle all the computations necessary for virtual reality goggles using only your phone. The sensor is quite powerful but with power comes a complex interface. We've written an I2C based library that provides the rotation vector (the reading most folks want from an IMU) as well as raw acceleration, gyro, and magnetometer readings. The sensor is capable of communicating over SPI and UART as well! 13 | 14 | In addition the BNO08x IMU provides a built-in step counter, tap detector, activity classifier (are you running, walking, or sitting still?), and a shake detector. We are duly impressed. 15 | 16 | This Arduino Library was built off the [original library](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library) written by Nathan Seidle ([SparkFun](http://www.sparkfun.com)). 17 | 18 | Thanks to all those who have helped improve this library! 19 | 20 | This BNO086 Library - CEVA-DSP Sh2 Driver-based improvements: 21 | * SFSailor for providing code for Geomagnetic Rotation Vector [issue #10](https://github.com/sparkfun/SparkFun_BNO08x_Arduino_Library/issues/10) 22 | * LazaroFilm for adding setReorientation() [PR15](https://github.com/sparkfun/SparkFun_BNO08x_Arduino_Library/pull/15) 23 | * rah2501 for fixing an INT/RST pin bug [PR13](https://github.com/sparkfun/SparkFun_BNO08x_Arduino_Library/pull/13) 24 | 25 | Original BNO080 Library improvements: 26 | * blendmaster for adding [Linear Accel report](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/4) 27 | * per1234 for fixing our [keywords file](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/12) 28 | * fm4dd for typo - [PR 19](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/19) 29 | * tstellanova for heading accuracy correction - [PR 40](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/40) 30 | * badVibes for gyro integrated rotation vector support - [PR 41](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/41) 31 | * Filimindji for AR/VR Stabilized RotationVector and AR/VR Stabilized GameRotationVector support - [PR 46](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/46) 32 | * ya-mouse for the getreadings improvements - [PR 55](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/55) 33 | * Guillaume for the read-multiple-values helper functions and the interrupt example - [PR56](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/56) & [PR59](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/59) 34 | * aedancullen for the tap detector - [PR 64](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/64) 35 | * mattbradford83 for the hasReset code and example - [PR 92](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/92) 36 | 37 | 38 | 39 | Repository Contents 40 | ------------------- 41 | 42 | * **/examples** - Example sketches for the library (.ino). Run these from the Arduino IDE. 43 | * **/src** - Source files for the library (.cpp, .h). 44 | * **keywords.txt** - Keywords from this library that will be highlighted in the Arduino IDE. 45 | * **library.properties** - General library properties for the Arduino package manager. 46 | * **[CONTRIBUTING.md](./CONTRIBUTING.md)** - guidance on how to contribute to this library. 47 | 48 | Documentation 49 | -------------- 50 | 51 | * **[Installing an Arduino Library Guide](https://learn.sparkfun.com/tutorials/installing-an-arduino-library)** - Basic information on how to install an Arduino library. 52 | * **[Hookup Guide](https://docs.sparkfun.com/SparkFun_VR_IMU_Breakout_BNO086_QWIIC/)** - Basic hookup guide for the SparkFun VR IMU Breakout - BNO086. 53 | * **[Product Repository](https://github.com/sparkfun/SparkFun_VR_IMU_Breakout_BNO086_QWIIC)** - Main repository for the BNO086 (including hardware files) 54 | 55 | License Information 56 | ------------------- 57 | 58 | This product is _**open source**_! 59 | 60 | Please review the LICENSE.md file for license information. 61 | 62 | If you have any questions or concerns on licensing, please contact technical support on our [SparkFun forums](https://forum.sparkfun.com/viewforum.php?f=152). 63 | 64 | Distributed as-is; no warranty is given. 65 | 66 | - Your friends at SparkFun. 67 | 68 | __ 69 | -------------------------------------------------------------------------------- /examples/Example_01_RotationVector/Example_01_RotationVector.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to output the i/j/k/real parts of the rotation vector. 5 | https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation 6 | 7 | By: Nathan Seidle 8 | SparkFun Electronics 9 | Date: December 21st, 2017 10 | SparkFun code, firmware, and software is released under the MIT License. 11 | Please see LICENSE.md for further details. 12 | 13 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 14 | 15 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 16 | CEVA Sensor Hub Driver, found here: 17 | https://github.com/ceva-dsp/sh2 18 | 19 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 20 | for Adafruit Industries. Found here: 21 | https://github.com/adafruit/Adafruit_BNO08x 22 | 23 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 24 | BusIO library found here: 25 | https://github.com/adafruit/Adafruit_BusIO 26 | 27 | Hardware Connections: 28 | IoT RedBoard --> BNO08x 29 | QWIIC --> QWIIC 30 | A4 --> INT 31 | A5 --> RST 32 | 33 | BNO08x "mode" jumpers set for I2C (default): 34 | PSO: OPEN 35 | PS1: OPEN 36 | 37 | Serial.print it out at 115200 baud to serial monitor. 38 | 39 | Feel like supporting our work? Buy a board from SparkFun! 40 | https://www.sparkfun.com/products/22857 41 | */ 42 | 43 | #include 44 | 45 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 46 | BNO08x myIMU; 47 | 48 | // For the most reliable interaction with the SHTP bus, we need 49 | // to use hardware reset control, and to monitor the H_INT pin. 50 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 51 | // Note, these can be other GPIO if you like. 52 | // Define as -1 to disable these features. 53 | #define BNO08X_INT A4 54 | //#define BNO08X_INT -1 55 | #define BNO08X_RST A5 56 | //#define BNO08X_RST -1 57 | 58 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 59 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 60 | 61 | void setup() { 62 | Serial.begin(115200); 63 | 64 | while(!Serial) delay(10); // Wait for Serial to become available. 65 | // Necessary for boards with native USB (like the SAMD51 Thing+). 66 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 67 | // Comment out this while loop, or it will prevent the remaining code from running. 68 | 69 | Serial.println(); 70 | Serial.println("BNO08x Read Example"); 71 | 72 | Wire.begin(); 73 | 74 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 75 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 76 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 77 | while (1) 78 | ; 79 | } 80 | Serial.println("BNO08x found!"); 81 | 82 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 83 | 84 | setReports(); 85 | 86 | Serial.println("Reading events"); 87 | delay(100); 88 | } 89 | 90 | // Here is where you define the sensor outputs you want to receive 91 | void setReports(void) { 92 | Serial.println("Setting desired reports"); 93 | if (myIMU.enableRotationVector() == true) { 94 | Serial.println(F("Rotation vector enabled")); 95 | Serial.println(F("Output in form i, j, k, real, accuracy")); 96 | } else { 97 | Serial.println("Could not enable rotation vector"); 98 | } 99 | } 100 | 101 | void loop() { 102 | delay(10); 103 | 104 | if (myIMU.wasReset()) { 105 | Serial.print("sensor was reset "); 106 | setReports(); 107 | } 108 | 109 | // Has a new event come in on the Sensor Hub Bus? 110 | if (myIMU.getSensorEvent() == true) { 111 | 112 | // is it the correct sensor data we want? 113 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_ROTATION_VECTOR) { 114 | 115 | float quatI = myIMU.getQuatI(); 116 | float quatJ = myIMU.getQuatJ(); 117 | float quatK = myIMU.getQuatK(); 118 | float quatReal = myIMU.getQuatReal(); 119 | float quatRadianAccuracy = myIMU.getQuatRadianAccuracy(); 120 | 121 | Serial.print(quatI, 2); 122 | Serial.print(F(",")); 123 | Serial.print(quatJ, 2); 124 | Serial.print(F(",")); 125 | Serial.print(quatK, 2); 126 | Serial.print(F(",")); 127 | Serial.print(quatReal, 2); 128 | Serial.print(F(",")); 129 | Serial.print(quatRadianAccuracy, 2); 130 | 131 | Serial.println(); 132 | } 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /examples/Example_02_Accelerometer/Example_02_Accelerometer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to output accelerometer values. 5 | 6 | By: Nathan Seidle 7 | SparkFun Electronics 8 | Date: December 21st, 2017 9 | SparkFun code, firmware, and software is released under the MIT License. 10 | Please see LICENSE.md for further details. 11 | 12 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 13 | 14 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 15 | CEVA Sensor Hub Driver, found here: 16 | https://github.com/ceva-dsp/sh2 17 | 18 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 19 | for Adafruit Industries. Found here: 20 | https://github.com/adafruit/Adafruit_BNO08x 21 | 22 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 23 | BusIO library found here: 24 | https://github.com/adafruit/Adafruit_BusIO 25 | 26 | Hardware Connections: 27 | IoT RedBoard --> BNO08x 28 | QWIIC --> QWIIC 29 | A4 --> INT 30 | A5 --> RST 31 | 32 | BNO08x "mode" jumpers set for I2C (default): 33 | PSO: OPEN 34 | PS1: OPEN 35 | 36 | Serial.print it out at 115200 baud to serial monitor. 37 | 38 | Feel like supporting our work? Buy a board from SparkFun! 39 | https://www.sparkfun.com/products/22857 40 | */ 41 | 42 | #include 43 | 44 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 45 | BNO08x myIMU; 46 | 47 | // For the most reliable interaction with the SHTP bus, we need 48 | // to use hardware reset control, and to monitor the H_INT pin. 49 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 50 | // Note, these can be other GPIO if you like. 51 | // Define as -1 to disable these features. 52 | #define BNO08X_INT A4 53 | //#define BNO08X_INT -1 54 | #define BNO08X_RST A5 55 | //#define BNO08X_RST -1 56 | 57 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 58 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 59 | 60 | void setup() { 61 | Serial.begin(115200); 62 | 63 | while(!Serial) delay(10); // Wait for Serial to become available. 64 | // Necessary for boards with native USB (like the SAMD51 Thing+). 65 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 66 | // Comment out this while loop, or it will prevent the remaining code from running. 67 | 68 | Serial.println(); 69 | Serial.println("BNO08x Read Example"); 70 | 71 | Wire.begin(); 72 | 73 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 74 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 75 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 76 | while (1) 77 | ; 78 | } 79 | Serial.println("BNO08x found!"); 80 | 81 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 82 | 83 | setReports(); 84 | 85 | Serial.println("Reading events"); 86 | delay(100); 87 | } 88 | 89 | // Here is where you define the sensor outputs you want to receive 90 | void setReports(void) { 91 | Serial.println("Setting desired reports"); 92 | if (myIMU.enableAccelerometer() == true) { 93 | Serial.println(F("Accelerometer enabled")); 94 | Serial.println(F("Output in form x, y, z, in m/s^2")); 95 | } else { 96 | Serial.println("Could not enable accelerometer"); 97 | } 98 | } 99 | 100 | void loop() { 101 | delay(10); 102 | 103 | if (myIMU.wasReset()) { 104 | Serial.print("sensor was reset "); 105 | setReports(); 106 | } 107 | 108 | // Has a new event come in on the Sensor Hub Bus? 109 | if (myIMU.getSensorEvent() == true) { 110 | 111 | // is it the correct sensor data we want? 112 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_ACCELEROMETER) { 113 | 114 | float x = myIMU.getAccelX(); 115 | float y = myIMU.getAccelY(); 116 | float z = myIMU.getAccelZ(); 117 | 118 | Serial.print(x, 2); 119 | Serial.print(F(",")); 120 | Serial.print(y, 2); 121 | Serial.print(F(",")); 122 | Serial.print(z, 2); 123 | 124 | Serial.println(); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /examples/Example_03_Gyro/Example_03_Gyro.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to output the parts of the calibrated gyro. 5 | 6 | By: Nathan Seidle 7 | SparkFun Electronics 8 | Date: December 21st, 2017 9 | SparkFun code, firmware, and software is released under the MIT License. 10 | Please see LICENSE.md for further details. 11 | 12 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 13 | 14 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 15 | CEVA Sensor Hub Driver, found here: 16 | https://github.com/ceva-dsp/sh2 17 | 18 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 19 | for Adafruit Industries. Found here: 20 | https://github.com/adafruit/Adafruit_BNO08x 21 | 22 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 23 | BusIO library found here: 24 | https://github.com/adafruit/Adafruit_BusIO 25 | 26 | Hardware Connections: 27 | IoT RedBoard --> BNO08x 28 | QWIIC --> QWIIC 29 | A4 --> INT 30 | A5 --> RST 31 | 32 | BNO08x "mode" jumpers set for I2C (default): 33 | PSO: OPEN 34 | PS1: OPEN 35 | 36 | Serial.print it out at 115200 baud to serial monitor. 37 | 38 | Feel like supporting our work? Buy a board from SparkFun! 39 | https://www.sparkfun.com/products/22857 40 | */ 41 | 42 | #include 43 | 44 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 45 | 46 | BNO08x myIMU; 47 | 48 | // For the most reliable interaction with the SHTP bus, we need 49 | // to use hardware reset control, and to monitor the H_INT pin. 50 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 51 | // Note, these can be other GPIO if you like. 52 | // Define as -1 to disable these features. 53 | #define BNO08X_INT A4 54 | //#define BNO08X_INT -1 55 | #define BNO08X_RST A5 56 | //#define BNO08X_RST -1 57 | 58 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 59 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 60 | 61 | void setup() { 62 | Serial.begin(115200); 63 | 64 | while(!Serial) delay(10); // Wait for Serial to become available. 65 | // Necessary for boards with native USB (like the SAMD51 Thing+). 66 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 67 | // Comment out this while loop, or it will prevent the remaining code from running. 68 | 69 | Serial.println(); 70 | Serial.println("BNO08x Read Example"); 71 | 72 | Wire.begin(); 73 | 74 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 75 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 76 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 77 | while (1) 78 | ; 79 | } 80 | Serial.println("BNO08x found!"); 81 | 82 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 83 | 84 | setReports(); 85 | 86 | Serial.println("Reading events"); 87 | delay(100); 88 | } 89 | 90 | // Here is where you define the sensor outputs you want to receive 91 | void setReports(void) { 92 | Serial.println("Setting desired reports"); 93 | if (myIMU.enableGyro() == true) { 94 | Serial.println(F("Gyro enabled")); 95 | Serial.println(F("Output in form x, y, z, in radians per second")); 96 | } else { 97 | Serial.println("Could not enable gyro"); 98 | } 99 | } 100 | 101 | void loop() { 102 | delay(10); 103 | 104 | if (myIMU.wasReset()) { 105 | Serial.print("sensor was reset "); 106 | setReports(); 107 | } 108 | 109 | // Has a new event come in on the Sensor Hub Bus? 110 | if (myIMU.getSensorEvent() == true) { 111 | 112 | // is it the correct sensor data we want? 113 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_GYROSCOPE_CALIBRATED) { 114 | 115 | float x = myIMU.getGyroX(); 116 | float y = myIMU.getGyroY(); 117 | float z = myIMU.getGyroZ(); 118 | 119 | Serial.print(x, 2); 120 | Serial.print(F(",")); 121 | Serial.print(y, 2); 122 | Serial.print(F(",")); 123 | Serial.print(z, 2); 124 | 125 | Serial.println(); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /examples/Example_04_Magnetometer/Example_04_Magnetometer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to output the parts of the magnetometer. 5 | 6 | By: Nathan Seidle 7 | SparkFun Electronics 8 | Date: December 21st, 2017 9 | SparkFun code, firmware, and software is released under the MIT License. 10 | Please see LICENSE.md for further details. 11 | 12 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 13 | 14 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 15 | CEVA Sensor Hub Driver, found here: 16 | https://github.com/ceva-dsp/sh2 17 | 18 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 19 | for Adafruit Industries. Found here: 20 | https://github.com/adafruit/Adafruit_BNO08x 21 | 22 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 23 | BusIO library found here: 24 | https://github.com/adafruit/Adafruit_BusIO 25 | 26 | Hardware Connections: 27 | IoT RedBoard --> BNO08x 28 | QWIIC --> QWIIC 29 | A4 --> INT 30 | A5 --> RST 31 | 32 | BNO08x "mode" jumpers set for I2C (default): 33 | PSO: OPEN 34 | PS1: OPEN 35 | 36 | Serial.print it out at 115200 baud to serial monitor. 37 | 38 | Feel like supporting our work? Buy a board from SparkFun! 39 | https://www.sparkfun.com/products/22857 40 | */ 41 | 42 | #include 43 | 44 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 45 | 46 | BNO08x myIMU; 47 | 48 | // For the most reliable interaction with the SHTP bus, we need 49 | // to use hardware reset control, and to monitor the H_INT pin. 50 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 51 | // Note, these can be other GPIO if you like. 52 | // Define as -1 to disable these features. 53 | #define BNO08X_INT A4 54 | //#define BNO08X_INT -1 55 | #define BNO08X_RST A5 56 | //#define BNO08X_RST -1 57 | 58 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 59 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 60 | 61 | void setup() { 62 | Serial.begin(115200); 63 | 64 | while(!Serial) delay(10); // Wait for Serial to become available. 65 | // Necessary for boards with native USB (like the SAMD51 Thing+). 66 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 67 | // Comment out this while loop, or it will prevent the remaining code from running. 68 | 69 | Serial.println(); 70 | Serial.println("BNO08x Read Example"); 71 | 72 | Wire.begin(); 73 | 74 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 75 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 76 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 77 | while (1) 78 | ; 79 | } 80 | Serial.println("BNO08x found!"); 81 | 82 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 83 | 84 | setReports(); 85 | 86 | Serial.println("Reading events"); 87 | delay(100); 88 | } 89 | 90 | // Here is where you define the sensor outputs you want to receive 91 | void setReports(void) { 92 | Serial.println("Setting desired reports"); 93 | if (myIMU.enableMagnetometer() == true) { 94 | Serial.println(F("Magnetometer enabled")); 95 | Serial.println(F("Output in form x, y, z, in uTesla")); 96 | } else { 97 | Serial.println("Could not enable magnetometer"); 98 | } 99 | } 100 | 101 | void loop() { 102 | delay(10); 103 | 104 | if (myIMU.wasReset()) { 105 | Serial.print("sensor was reset "); 106 | setReports(); 107 | } 108 | 109 | // Has a new event come in on the Sensor Hub Bus? 110 | if (myIMU.getSensorEvent() == true) { 111 | 112 | // is it the correct sensor data we want? 113 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_MAGNETIC_FIELD) { 114 | 115 | float x = myIMU.getMagX(); 116 | float y = myIMU.getMagY(); 117 | float z = myIMU.getMagZ(); 118 | byte accuracy = myIMU.getMagAccuracy(); 119 | 120 | Serial.print(x, 2); 121 | Serial.print(F(",")); 122 | Serial.print(y, 2); 123 | Serial.print(F(",")); 124 | Serial.print(z, 2); 125 | Serial.print(F(",")); 126 | printAccuracyLevel(accuracy); 127 | 128 | Serial.println(); 129 | } 130 | } 131 | } 132 | 133 | //Given a accuracy number, print what it means 134 | void printAccuracyLevel(byte accuracyNumber) 135 | { 136 | if(accuracyNumber == 0) Serial.print(F("Unreliable")); 137 | else if(accuracyNumber == 1) Serial.print(F("Low")); 138 | else if(accuracyNumber == 2) Serial.print(F("Medium")); 139 | else if(accuracyNumber == 3) Serial.print(F("High")); 140 | } 141 | -------------------------------------------------------------------------------- /examples/Example_05_StepCounter/Example_05_StepCounter.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows the step count. Tap the IC a few times to emulate a step. 5 | 6 | By: Nathan Seidle 7 | SparkFun Electronics 8 | Date: December 21st, 2017 9 | SparkFun code, firmware, and software is released under the MIT License. 10 | Please see LICENSE.md for further details. 11 | 12 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 13 | 14 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 15 | CEVA Sensor Hub Driver, found here: 16 | https://github.com/ceva-dsp/sh2 17 | 18 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 19 | for Adafruit Industries. Found here: 20 | https://github.com/adafruit/Adafruit_BNO08x 21 | 22 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 23 | BusIO library found here: 24 | https://github.com/adafruit/Adafruit_BusIO 25 | 26 | Hardware Connections: 27 | IoT RedBoard --> BNO08x 28 | QWIIC --> QWIIC 29 | A4 --> INT 30 | A5 --> RST 31 | 32 | BNO08x "mode" jumpers set for I2C (default): 33 | PSO: OPEN 34 | PS1: OPEN 35 | 36 | Serial.print it out at 115200 baud to serial monitor. 37 | 38 | Feel like supporting our work? Buy a board from SparkFun! 39 | https://www.sparkfun.com/products/22857 40 | */ 41 | 42 | #include 43 | 44 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 45 | BNO08x myIMU; 46 | 47 | // For the most reliable interaction with the SHTP bus, we need 48 | // to use hardware reset control, and to monitor the H_INT pin. 49 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 50 | // Note, these can be other GPIO if you like. 51 | // Define as -1 to disable these features. 52 | #define BNO08X_INT A4 53 | //#define BNO08X_INT -1 54 | #define BNO08X_RST A5 55 | //#define BNO08X_RST -1 56 | 57 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 58 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 59 | 60 | void setup() { 61 | Serial.begin(115200); 62 | 63 | while(!Serial) delay(10); // Wait for Serial to become available. 64 | // Necessary for boards with native USB (like the SAMD51 Thing+). 65 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 66 | // Comment out this while loop, or it will prevent the remaining code from running. 67 | 68 | Serial.println(); 69 | Serial.println("BNO08x Read Example"); 70 | 71 | Wire.begin(); 72 | 73 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 74 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 75 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 76 | while (1) 77 | ; 78 | } 79 | Serial.println("BNO08x found!"); 80 | 81 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 82 | 83 | setReports(); 84 | 85 | Serial.println("Reading events"); 86 | delay(100); 87 | } 88 | 89 | // Here is where you define the sensor outputs you want to receive 90 | void setReports(void) { 91 | Serial.println("Setting desired reports"); 92 | if (myIMU.enableStepCounter(500) == true) { //Send data update every 500ms 93 | Serial.println(F("Step Counter enabled")); 94 | Serial.println(F("Step count since sketch started:")); 95 | } else { 96 | Serial.println("Could not step counter"); 97 | } 98 | } 99 | 100 | void loop() { 101 | delay(500); // step counter needs a little longer of delay (200ms or more) 102 | 103 | if (myIMU.wasReset()) { 104 | Serial.print("sensor was reset "); 105 | setReports(); 106 | } 107 | 108 | // Has a new event come in on the Sensor Hub Bus? 109 | if (myIMU.getSensorEvent() == true) { 110 | 111 | // is it the correct sensor data we want? 112 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_STEP_COUNTER) { 113 | 114 | unsigned int steps = myIMU.getStepCount(); 115 | 116 | Serial.print(steps); 117 | 118 | Serial.println(); 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /examples/Example_06_StabilityClassifier/Example_06_StabilityClassifier.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to use the stability classifier: 5 | Are we on a table, stationary, stable, or moving? 6 | 7 | By: Nathan Seidle 8 | SparkFun Electronics 9 | Date: December 21st, 2017 10 | SparkFun code, firmware, and software is released under the MIT License. 11 | Please see LICENSE.md for further details. 12 | 13 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 14 | 15 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 16 | CEVA Sensor Hub Driver, found here: 17 | https://github.com/ceva-dsp/sh2 18 | 19 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 20 | for Adafruit Industries. Found here: 21 | https://github.com/adafruit/Adafruit_BNO08x 22 | 23 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 24 | BusIO library found here: 25 | https://github.com/adafruit/Adafruit_BusIO 26 | 27 | Hardware Connections: 28 | IoT RedBoard --> BNO08x 29 | QWIIC --> QWIIC 30 | A4 --> INT 31 | A5 --> RST 32 | 33 | BNO08x "mode" jumpers set for I2C (default): 34 | PSO: OPEN 35 | PS1: OPEN 36 | 37 | Serial.print it out at 115200 baud to serial monitor. 38 | 39 | Feel like supporting our work? Buy a board from SparkFun! 40 | https://www.sparkfun.com/products/22857 41 | */ 42 | 43 | #include 44 | 45 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 46 | BNO08x myIMU; 47 | 48 | // For the most reliable interaction with the SHTP bus, we need 49 | // to use hardware reset control, and to monitor the H_INT pin. 50 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 51 | // Note, these can be other GPIO if you like. 52 | // Define as -1 to disable these features. 53 | #define BNO08X_INT A4 54 | //#define BNO08X_INT -1 55 | #define BNO08X_RST A5 56 | //#define BNO08X_RST -1 57 | 58 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 59 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 60 | 61 | void setup() { 62 | Serial.begin(115200); 63 | 64 | while(!Serial) delay(10); // Wait for Serial to become available. 65 | // Necessary for boards with native USB (like the SAMD51 Thing+). 66 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 67 | // Comment out this while loop, or it will prevent the remaining code from running. 68 | 69 | Serial.println(); 70 | Serial.println("BNO08x Read Example"); 71 | 72 | Wire.begin(); 73 | 74 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 75 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 76 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 77 | while (1) 78 | ; 79 | } 80 | Serial.println("BNO08x found!"); 81 | 82 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 83 | 84 | setReports(); 85 | 86 | Serial.println("Reading events"); 87 | delay(100); 88 | } 89 | 90 | // Here is where you define the sensor outputs you want to receive 91 | void setReports(void) { 92 | Serial.println("Setting desired reports"); 93 | 94 | if (myIMU.enableStabilityClassifier() == true) { 95 | Serial.println(F("Stability Classifier enabled")); 96 | } else { 97 | Serial.println("Could not enable Stability Classifier"); 98 | } 99 | } 100 | 101 | void loop() { 102 | delay(10); 103 | 104 | if (myIMU.wasReset()) { 105 | Serial.print("sensor was reset "); 106 | setReports(); 107 | } 108 | 109 | // Has a new event come in on the Sensor Hub Bus? 110 | if (myIMU.getSensorEvent() == true) { 111 | 112 | // is it the correct sensor data we want? 113 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_STABILITY_CLASSIFIER) { 114 | 115 | byte classification = myIMU.getStabilityClassifier(); 116 | 117 | if(classification == STABILITY_CLASSIFIER_UNKNOWN) Serial.print(F("Unknown classification")); 118 | else if(classification == STABILITY_CLASSIFIER_ON_TABLE) Serial.print(F("On table")); 119 | else if(classification == STABILITY_CLASSIFIER_STATIONARY) Serial.print(F("Stationary")); 120 | else if(classification == STABILITY_CLASSIFIER_STABLE) Serial.print(F("Stable")); 121 | else if(classification == STABILITY_CLASSIFIER_MOTION) Serial.print(F("Motion")); 122 | else if(classification == STABILITY_CLASSIFIER_RESERVED) Serial.print(F("[Reserved]")); 123 | 124 | Serial.println(); 125 | } 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /examples/Example_07_ActivityClassifier/Example_07_ActivityClassifier.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This is a fun one! The BNO08x can guess at what activity you are doing: 5 | 6 | In vehicle 7 | On bicycle 8 | On foot 9 | Still 10 | Tilting 11 | Walking 12 | Running 13 | On stairs 14 | This example shows how to read the confidence levels of each activity 15 | 16 | By: Nathan Seidle 17 | SparkFun Electronics 18 | Date: December 21st, 2017 19 | SparkFun code, firmware, and software is released under the MIT License. 20 | Please see LICENSE.md for further details. 21 | 22 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 23 | 24 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 25 | CEVA Sensor Hub Driver, found here: 26 | https://github.com/ceva-dsp/sh2 27 | 28 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 29 | for Adafruit Industries. Found here: 30 | https://github.com/adafruit/Adafruit_BNO08x 31 | 32 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 33 | BusIO library found here: 34 | https://github.com/adafruit/Adafruit_BusIO 35 | 36 | Hardware Connections: 37 | IoT RedBoard --> BNO08x 38 | QWIIC --> QWIIC 39 | A4 --> INT 40 | A5 --> RST 41 | 42 | BNO08x "mode" jumpers set for I2C (default): 43 | PSO: OPEN 44 | PS1: OPEN 45 | 46 | Serial.print it out at 115200 baud to serial monitor. 47 | 48 | Feel like supporting our work? Buy a board from SparkFun! 49 | https://www.sparkfun.com/products/22857 50 | */ 51 | 52 | #include 53 | 54 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 55 | 56 | BNO08x myIMU; 57 | 58 | // For the most reliable interaction with the SHTP bus, we need 59 | // to use hardware reset control, and to monitor the H_INT pin. 60 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 61 | // Note, these can be other GPIO if you like. 62 | // Define as -1 to disable these features. 63 | #define BNO08X_INT A4 64 | //#define BNO08X_INT -1 65 | #define BNO08X_RST A5 66 | //#define BNO08X_RST -1 67 | 68 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 69 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 70 | 71 | void setup() { 72 | Serial.begin(115200); 73 | 74 | while(!Serial) delay(10); // Wait for Serial to become available. 75 | // Necessary for boards with native USB (like the SAMD51 Thing+). 76 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 77 | // Comment out this while loop, or it will prevent the remaining code from running. 78 | 79 | Serial.println(); 80 | Serial.println("BNO08x Read Example"); 81 | 82 | Wire.begin(); 83 | 84 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 85 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 86 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 87 | while (1) 88 | ; 89 | } 90 | Serial.println("BNO08x found!"); 91 | 92 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 93 | 94 | setReports(); 95 | 96 | Serial.println("Reading events"); 97 | delay(100); 98 | } 99 | 100 | // Here is where you define the sensor outputs you want to receive 101 | void setReports(void) { 102 | 103 | Serial.println("Setting desired reports"); 104 | 105 | //See page 73 of reference manual. There is a 32 bit word where each 106 | //bit enables a different possible activity. Currently there are only 8 107 | //possible. Let's enable all of them! 108 | uint32_t enableActivities = 0x1F; //Enable all 9 possible activities including Unknown 109 | 110 | //Send data update every 1000ms, with sensor specific config word 111 | 112 | if (myIMU.enableActivityClassifier(1000, enableActivities) == true) { 113 | Serial.println(F("Activity Classifier enabled")); 114 | } else { 115 | Serial.println("Could not enable Activity Classifier"); 116 | } 117 | } 118 | 119 | void loop() { 120 | delay(1000); // Personal Activity Classifier needs longer delay here than other examples 121 | 122 | if (myIMU.wasReset()) { 123 | Serial.print("sensor was reset "); 124 | setReports(); 125 | } 126 | 127 | // Has a new event come in on the Sensor Hub Bus? 128 | if (myIMU.getSensorEvent() == true) { 129 | 130 | // is it the correct sensor data we want? 131 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER) { 132 | 133 | byte mostLikelyActivity = myIMU.getActivityClassifier(); 134 | 135 | Serial.print("Most likely activity: "); 136 | printActivityName(mostLikelyActivity); 137 | Serial.println(); 138 | 139 | Serial.println("Confidence levels:"); 140 | for(int x = 0 ; x < 9 ; x++) 141 | { 142 | printActivityName(x); 143 | Serial.print(F(") ")); 144 | Serial.print(myIMU.getActivityConfidence(x)); 145 | Serial.print(F("%")); 146 | Serial.println(); 147 | } 148 | 149 | Serial.println(); 150 | } 151 | } 152 | } 153 | 154 | //Given a number between 0 and 8, print the name of the activity 155 | //See page 73 of reference manual for activity list 156 | void printActivityName(byte activityNumber) 157 | { 158 | if(activityNumber == 0) Serial.print("Unknown"); 159 | else if(activityNumber == 1) Serial.print("In vehicle"); 160 | else if(activityNumber == 2) Serial.print("On bicycle"); 161 | else if(activityNumber == 3) Serial.print("On foot"); 162 | else if(activityNumber == 4) Serial.print("Still"); 163 | else if(activityNumber == 5) Serial.print("Tilting"); 164 | else if(activityNumber == 6) Serial.print("Walking"); 165 | else if(activityNumber == 7) Serial.print("Running"); 166 | else if(activityNumber == 8) Serial.print("On stairs"); 167 | } 168 | -------------------------------------------------------------------------------- /examples/Example_08_AdvancedConfig/Example_08_AdvancedConfig.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to configure the sensor with different I2C address 5 | (0x4A) and different Wire ports (Wire1, on SDA:25, SCL:17). 6 | 7 | Note, for this example to work, you must close the address jumper on the 8 | bottom of the PCB, and wire up SDA/SCL to their newly defined pins (25/17). 9 | 10 | It will output the i/j/k/real parts of the rotation vector. 11 | https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation 12 | 13 | By: Nathan Seidle 14 | SparkFun Electronics 15 | Date: December 21st, 2017 16 | SparkFun code, firmware, and software is released under the MIT License. 17 | Please see LICENSE.md for further details. 18 | 19 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 20 | 21 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 22 | CEVA Sensor Hub Driver, found here: 23 | https://github.com/ceva-dsp/sh2 24 | 25 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 26 | for Adafruit Industries. Found here: 27 | https://github.com/adafruit/Adafruit_BNO08x 28 | 29 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 30 | BusIO library found here: 31 | https://github.com/adafruit/Adafruit_BusIO 32 | 33 | IoT RedBoard --> BNO08x 34 | 3.3V --> 3.3V 35 | GND --> GND 36 | SCL1 (D17) --> SCL 37 | SDA1 (D25) --> SDA 38 | A4 --> INT 39 | A5 --> RST 40 | 41 | Note: Make sure to close the ADR jumper on the back of the board as well. 42 | 43 | Serial.print it out at 115200 baud to serial monitor. 44 | 45 | Feel like supporting our work? Buy a board from SparkFun! 46 | https://www.sparkfun.com/products/22857 47 | */ 48 | 49 | #include 50 | 51 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 52 | BNO08x myIMU; 53 | 54 | // For the most reliable interaction with the SHTP bus, we need 55 | // to use hardware reset control, and to monitor the H_INT pin. 56 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 57 | // Note, these can be other GPIO if you like. 58 | // Define as -1 to disable these features. 59 | #define BNO08X_INT A4 60 | //#define BNO08X_INT -1 61 | #define BNO08X_RST A5 62 | //#define BNO08X_RST -1 63 | 64 | //#define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 65 | #define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 66 | 67 | // define some pins for our new I2C port, aka "Wire1" 68 | // on a SparkFun ESP32 IoT REdboard, these can be most pins, except those that 69 | // are only inputs. 70 | #define I2C_SDA1 25 71 | #define I2C_SCL1 17 72 | 73 | void setup() { 74 | Serial.begin(115200); 75 | 76 | while(!Serial) delay(10); // Wait for Serial to become available. 77 | // Necessary for boards with native USB (like the SAMD51 Thing+). 78 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 79 | // Comment out this while loop, or it will prevent the remaining code from running. 80 | 81 | Serial.println(); 82 | Serial.println("BNO08x Read Example"); 83 | 84 | Wire1.begin(I2C_SDA1, I2C_SCL1, 100000); 85 | 86 | // Wire1.begin(); // Some Arduino boards have pre-defined Wire1 SDA/SCL pins, 87 | // When using these, you don't have to supply the pin arguments, and they 88 | // are usually labled on the board as "SDA1" and "SCL1". 89 | 90 | // The first argument of our BNO08x begin() function is the I2C address of the 91 | // sensor, either 0x4B (default) or 0x4A. The second is the TwoWire I2C port 92 | // to use. Wire, Wire1, etc. 93 | if (myIMU.begin(BNO08X_ADDR, Wire1, BNO08X_INT, BNO08X_RST) == false) { 94 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 95 | while (1) 96 | ; 97 | } 98 | Serial.println("BNO08x found!"); 99 | 100 | // Wire1.setClock(400000); //Increase I2C data rate to 400kHz 101 | 102 | setReports(); 103 | 104 | Serial.println("Reading events"); 105 | delay(100); 106 | } 107 | 108 | // Here is where you define the sensor outputs you want to receive 109 | void setReports(void) { 110 | Serial.println("Setting desired reports"); 111 | if (myIMU.enableRotationVector() == true) { 112 | Serial.println(F("Rotation vector enabled")); 113 | Serial.println(F("Output in form i, j, k, real, accuracy")); 114 | } else { 115 | Serial.println("Could not enable rotation vector"); 116 | } 117 | } 118 | 119 | void loop() { 120 | delay(10); 121 | 122 | if (myIMU.wasReset()) { 123 | Serial.print("sensor was reset "); 124 | setReports(); 125 | } 126 | 127 | // Has a new event come in on the Sensor Hub Bus? 128 | if (myIMU.getSensorEvent() == true) { 129 | 130 | // is it the correct sensor data we want? 131 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_ROTATION_VECTOR) { 132 | 133 | float quatI = myIMU.getQuatI(); 134 | float quatJ = myIMU.getQuatJ(); 135 | float quatK = myIMU.getQuatK(); 136 | float quatReal = myIMU.getQuatReal(); 137 | float quatRadianAccuracy = myIMU.getQuatRadianAccuracy(); 138 | 139 | Serial.print(quatI, 2); 140 | Serial.print(F(",")); 141 | Serial.print(quatJ, 2); 142 | Serial.print(F(",")); 143 | Serial.print(quatK, 2); 144 | Serial.print(F(",")); 145 | Serial.print(quatReal, 2); 146 | Serial.print(F(",")); 147 | Serial.print(quatRadianAccuracy, 2); 148 | 149 | Serial.println(); 150 | } 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /examples/Example_09_LinearAccelerometer/Example_09_LinearAccelerometer.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to output linear accelerometer values. 5 | 6 | By: Nathan Seidle 7 | SparkFun Electronics 8 | Date: December 21st, 2017 9 | SparkFun code, firmware, and software is released under the MIT License. 10 | Please see LICENSE.md for further details. 11 | 12 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 13 | 14 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 15 | CEVA Sensor Hub Driver, found here: 16 | https://github.com/ceva-dsp/sh2 17 | 18 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 19 | for Adafruit Industries. Found here: 20 | https://github.com/adafruit/Adafruit_BNO08x 21 | 22 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 23 | BusIO library found here: 24 | https://github.com/adafruit/Adafruit_BusIO 25 | 26 | Hardware Connections: 27 | IoT RedBoard --> BNO08x 28 | QWIIC --> QWIIC 29 | A4 --> INT 30 | A5 --> RST 31 | 32 | BNO08x "mode" jumpers set for I2C (default): 33 | PSO: OPEN 34 | PS1: OPEN 35 | 36 | Serial.print it out at 115200 baud to serial monitor. 37 | 38 | Feel like supporting our work? Buy a board from SparkFun! 39 | https://www.sparkfun.com/products/22857 40 | */ 41 | 42 | #include 43 | 44 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 45 | 46 | BNO08x myIMU; 47 | 48 | // For the most reliable interaction with the SHTP bus, we need 49 | // to use hardware reset control, and to monitor the H_INT pin. 50 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 51 | // Note, these can be other GPIO if you like. 52 | // Define as -1 to disable these features. 53 | #define BNO08X_INT A4 54 | //#define BNO08X_INT -1 55 | #define BNO08X_RST A5 56 | //#define BNO08X_RST -1 57 | 58 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 59 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 60 | 61 | void setup() { 62 | Serial.begin(115200); 63 | 64 | while(!Serial) delay(10); // Wait for Serial to become available. 65 | // Necessary for boards with native USB (like the SAMD51 Thing+). 66 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 67 | // Comment out this while loop, or it will prevent the remaining code from running. 68 | 69 | Serial.println(); 70 | Serial.println("BNO08x Read Example"); 71 | 72 | Wire.begin(); 73 | 74 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 75 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 76 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 77 | while (1) 78 | ; 79 | } 80 | Serial.println("BNO08x found!"); 81 | 82 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 83 | 84 | setReports(); 85 | 86 | Serial.println("Reading events"); 87 | delay(100); 88 | } 89 | 90 | // Here is where you define the sensor outputs you want to receive 91 | void setReports(void) { 92 | Serial.println("Setting desired reports"); 93 | if (myIMU.enableLinearAccelerometer() == true) { 94 | Serial.println(F("Linear Accelerometer enabled")); 95 | Serial.println(F("Output in form x, y, z, in m/s^2")); 96 | } else { 97 | Serial.println("Could not enable linear accelerometer"); 98 | } 99 | } 100 | 101 | void loop() { 102 | delay(10); 103 | 104 | if (myIMU.wasReset()) { 105 | Serial.print("sensor was reset "); 106 | setReports(); 107 | } 108 | 109 | // Has a new event come in on the Sensor Hub Bus? 110 | if (myIMU.getSensorEvent() == true) { 111 | 112 | // is it the correct sensor data we want? 113 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_LINEAR_ACCELERATION) { 114 | 115 | float x = myIMU.getLinAccelX(); 116 | float y = myIMU.getLinAccelY(); 117 | float z = myIMU.getLinAccelZ(); 118 | byte linAccuracy = myIMU.getLinAccelAccuracy(); 119 | 120 | Serial.print(x, 2); 121 | Serial.print(F(",")); 122 | Serial.print(y, 2); 123 | Serial.print(F(",")); 124 | Serial.print(z, 2); 125 | Serial.print(F(",")); 126 | Serial.print(linAccuracy); 127 | 128 | Serial.println(); 129 | } 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /examples/Example_10_TimeStamp/Example_10_TimeStamp.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to output the timestamp for each reading. 5 | 6 | It outputs the timestampe/i/j/k/real/accuracy parts of the rotation vector. 7 | https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation 8 | 9 | By: Nathan Seidle 10 | SparkFun Electronics 11 | Date: December 21st, 2017 12 | SparkFun code, firmware, and software is released under the MIT License. 13 | Please see LICENSE.md for further details. 14 | 15 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 16 | 17 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 18 | CEVA Sensor Hub Driver, found here: 19 | https://github.com/ceva-dsp/sh2 20 | 21 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 22 | for Adafruit Industries. Found here: 23 | https://github.com/adafruit/Adafruit_BNO08x 24 | 25 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 26 | BusIO library found here: 27 | https://github.com/adafruit/Adafruit_BusIO 28 | 29 | Hardware Connections: 30 | IoT RedBoard --> BNO08x 31 | QWIIC --> QWIIC 32 | A4 --> INT 33 | A5 --> RST 34 | 35 | BNO08x "mode" jumpers set for I2C (default): 36 | PSO: OPEN 37 | PS1: OPEN 38 | 39 | Serial.print it out at 115200 baud to serial monitor. 40 | 41 | Feel like supporting our work? Buy a board from SparkFun! 42 | https://www.sparkfun.com/products/22857 43 | */ 44 | 45 | #include 46 | 47 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 48 | BNO08x myIMU; 49 | 50 | // For the most reliable interaction with the SHTP bus, we need 51 | // to use hardware reset control, and to monitor the H_INT pin. 52 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 53 | // Note, these can be other GPIO if you like. 54 | // Define as -1 to disable these features. 55 | #define BNO08X_INT A4 56 | //#define BNO08X_INT -1 57 | #define BNO08X_RST A5 58 | //#define BNO08X_RST -1 59 | 60 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 61 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 62 | 63 | void setup() { 64 | Serial.begin(115200); 65 | 66 | while(!Serial) delay(10); // Wait for Serial to become available. 67 | // Necessary for boards with native USB (like the SAMD51 Thing+). 68 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 69 | // Comment out this while loop, or it will prevent the remaining code from running. 70 | 71 | Serial.println(); 72 | Serial.println("BNO08x Read Example"); 73 | 74 | Wire.begin(); 75 | 76 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 77 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 78 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 79 | while (1) 80 | ; 81 | } 82 | Serial.println("BNO08x found!"); 83 | 84 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 85 | 86 | setReports(); 87 | 88 | Serial.println("Reading events"); 89 | delay(100); 90 | } 91 | 92 | // Here is where you define the sensor outputs you want to receive 93 | void setReports(void) { 94 | Serial.println("Setting desired reports"); 95 | if (myIMU.enableRotationVector() == true) { 96 | Serial.println(F("Rotation vector enabled")); 97 | Serial.println(F("Output in form i, j, k, real, accuracy")); 98 | } else { 99 | Serial.println("Could not enable rotation vector"); 100 | } 101 | } 102 | 103 | void loop() { 104 | delay(10); 105 | 106 | if (myIMU.wasReset()) { 107 | Serial.print("sensor was reset "); 108 | setReports(); 109 | } 110 | 111 | // Has a new event come in on the Sensor Hub Bus? 112 | if (myIMU.getSensorEvent() == true) { 113 | 114 | // is it the correct sensor data we want? 115 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_ROTATION_VECTOR) { 116 | 117 | uint64_t timeStamp = myIMU.getTimeStamp(); 118 | float quatI = myIMU.getQuatI(); 119 | float quatJ = myIMU.getQuatJ(); 120 | float quatK = myIMU.getQuatK(); 121 | float quatReal = myIMU.getQuatReal(); 122 | float quatRadianAccuracy = myIMU.getQuatRadianAccuracy(); 123 | 124 | Serial.print(timeStamp); 125 | Serial.print(F(",")); 126 | Serial.print(quatI, 2); 127 | Serial.print(F(",")); 128 | Serial.print(quatJ, 2); 129 | Serial.print(F(",")); 130 | Serial.print(quatK, 2); 131 | Serial.print(F(",")); 132 | Serial.print(quatReal, 2); 133 | Serial.print(F(",")); 134 | Serial.print(quatRadianAccuracy, 2); 135 | 136 | Serial.println(); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /examples/Example_11_RawReadings/Example_11_RawReadings.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to output the raw accel, gryo and mag values. 5 | 6 | It outputs the timestampe/i/j/k/real/accuracy parts of the rotation vector. 7 | https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation 8 | 9 | By: Nathan Seidle 10 | SparkFun Electronics 11 | Date: December 21st, 2017 12 | SparkFun code, firmware, and software is released under the MIT License. 13 | Please see LICENSE.md for further details. 14 | 15 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 16 | 17 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 18 | CEVA Sensor Hub Driver, found here: 19 | https://github.com/ceva-dsp/sh2 20 | 21 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 22 | for Adafruit Industries. Found here: 23 | https://github.com/adafruit/Adafruit_BNO08x 24 | 25 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 26 | BusIO library found here: 27 | https://github.com/adafruit/Adafruit_BusIO 28 | 29 | Hardware Connections: 30 | IoT RedBoard --> BNO08x 31 | QWIIC --> QWIIC 32 | A4 --> INT 33 | A5 --> RST 34 | 35 | BNO08x "mode" jumpers set for I2C (default): 36 | PSO: OPEN 37 | PS1: OPEN 38 | 39 | Serial.print it out at 115200 baud to serial monitor. 40 | 41 | Feel like supporting our work? Buy a board from SparkFun! 42 | https://www.sparkfun.com/products/22857 43 | */ 44 | 45 | #include 46 | 47 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 48 | 49 | BNO08x myIMU; 50 | 51 | // For the most reliable interaction with the SHTP bus, we need 52 | // to use hardware reset control, and to monitor the H_INT pin. 53 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 54 | // Note, these can be other GPIO if you like. 55 | // Define as -1 to disable these features. 56 | #define BNO08X_INT A4 57 | //#define BNO08X_INT -1 58 | #define BNO08X_RST A5 59 | //#define BNO08X_RST -1 60 | 61 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 62 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 63 | 64 | // variables to store all our incoming values 65 | 66 | // raw accel 67 | int16_t x; 68 | int16_t y; 69 | int16_t z; 70 | 71 | // raw gyros 72 | int16_t gx; 73 | int16_t gy; 74 | int16_t gz; 75 | 76 | // raw mags 77 | int16_t mx; 78 | int16_t my; 79 | int16_t mz; 80 | 81 | unsigned long previousDebugMillis = 0; 82 | #define DEBUG_INTERVAL_MILLISECONDS 30 83 | 84 | void setup() { 85 | Serial.begin(115200); 86 | 87 | while(!Serial) delay(10); // Wait for Serial to become available. 88 | // Necessary for boards with native USB (like the SAMD51 Thing+). 89 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 90 | // Comment out this while loop, or it will prevent the remaining code from running. 91 | 92 | Serial.println(); 93 | Serial.println("BNO08x Read Example"); 94 | 95 | Wire.begin(); 96 | 97 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 98 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 99 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 100 | while (1) 101 | ; 102 | } 103 | Serial.println("BNO08x found!"); 104 | 105 | //Wire.setClock(400000); //Increase I2C data rate to 400kHz 106 | 107 | setReports(); 108 | 109 | Serial.println("Reading events"); 110 | delay(100); 111 | } 112 | 113 | // Here is where you define the sensor outputs you want to receive 114 | void setReports(void) { 115 | Serial.println("Setting desired reports"); 116 | 117 | if (myIMU.enableAccelerometer(1) == true) { 118 | Serial.println(F("Accelerometer enabled")); 119 | } else { 120 | Serial.println("Could not enable accelerometer"); 121 | } 122 | 123 | if (myIMU.enableRawAccelerometer(1) == true) { 124 | Serial.println(F("Raw Accelerometer enabled")); 125 | } else { 126 | Serial.println("Could not enable raw accelerometer"); 127 | } 128 | 129 | if (myIMU.enableGyro(1) == true) { 130 | Serial.println(F("Gyro enabled")); 131 | } else { 132 | Serial.println("Could not enable gyro"); 133 | } 134 | 135 | if (myIMU.enableRawGyro(1) == true) { 136 | Serial.println(F("Raw Gyro enabled")); 137 | } else { 138 | Serial.println("Could not enable raw gyro"); 139 | } 140 | 141 | if (myIMU.enableMagnetometer(1) == true) { 142 | Serial.println(F("Magnetometer enabled")); 143 | } else { 144 | Serial.println("Could not enable Magnetometer"); 145 | } 146 | 147 | if (myIMU.enableRawMagnetometer(1) == true) { 148 | Serial.println(F("Raw Magnetometer enabled")); 149 | } else { 150 | Serial.println("Could not enable Raw Magnetometer"); 151 | } 152 | 153 | Serial.println(F("Raw MEMS readings enabled")); 154 | Serial.println(F("Output is: (accel) x y z (gyro) x y z (mag) x y z")); 155 | } 156 | 157 | void loop() { 158 | delayMicroseconds(10); 159 | 160 | if (myIMU.wasReset()) { 161 | Serial.print("sensor was reset "); 162 | setReports(); 163 | } 164 | 165 | // Has a new event come in on the Sensor Hub Bus? 166 | if (myIMU.getSensorEvent() == true) 167 | { 168 | 169 | // keep track of if we've recieved an updated value on any one of the 170 | // reports we're looking for. 171 | uint8_t reportID = myIMU.getSensorEventID(); 172 | 173 | switch (reportID) 174 | { 175 | case SENSOR_REPORTID_RAW_ACCELEROMETER: 176 | x = myIMU.getRawAccelX(); 177 | y = myIMU.getRawAccelY(); 178 | z = myIMU.getRawAccelZ(); 179 | break; 180 | case SENSOR_REPORTID_RAW_GYROSCOPE: 181 | gx = myIMU.getRawGyroX(); 182 | gy = myIMU.getRawGyroY(); 183 | gz = myIMU.getRawGyroZ(); 184 | break; 185 | case SENSOR_REPORTID_RAW_MAGNETOMETER: 186 | mx = myIMU.getRawMagX(); 187 | my = myIMU.getRawMagY(); 188 | mz = myIMU.getRawMagZ(); 189 | break; 190 | default: 191 | break; 192 | } 193 | 194 | // Only print data to the terminal at a user defined interval 195 | // Each data type (accel or gyro or mag) is reported from the 196 | // BNO086 as separate messages. 197 | // To allow for all these separate messages to arrive, and thus 198 | // have updated data on all axis/types, 199 | // The report intervals for each datatype must be much faster 200 | // than our debug interval. 201 | 202 | // time since last debug data printed to terminal 203 | int timeSinceLastSerialPrint = (millis() - previousDebugMillis); 204 | 205 | // Only print data to the terminal at a user deficed interval 206 | if(timeSinceLastSerialPrint > DEBUG_INTERVAL_MILLISECONDS) 207 | { 208 | Serial.print(x); 209 | Serial.print("\t"); 210 | Serial.print(y); 211 | Serial.print("\t"); 212 | Serial.print(z); 213 | Serial.print("\t"); 214 | 215 | Serial.print(gx); 216 | Serial.print("\t"); 217 | Serial.print(gy); 218 | Serial.print("\t"); 219 | Serial.print(gz); 220 | Serial.print("\t"); 221 | 222 | Serial.print(mx); 223 | Serial.print("\t"); 224 | Serial.print(my); 225 | Serial.print("\t"); 226 | Serial.print(mz); 227 | Serial.print("\t"); 228 | 229 | Serial.print(timeSinceLastSerialPrint); 230 | 231 | Serial.println(); 232 | 233 | previousDebugMillis = millis(); 234 | 235 | } 236 | } 237 | } 238 | -------------------------------------------------------------------------------- /examples/Example_12_GyroIntegratedRotationVector/Example_12_GyroIntegratedRotationVector.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to use the gyro integrated rotation vector. 5 | 6 | It outputs the GyroIntegrated i/j/k/real/angVelX/angVelY/angVelZ parts of the 7 | rotation vector. 8 | https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation 9 | 10 | By: Boštjan Čadež (@badVibes--) 11 | Date: April 3rd, 2020 12 | 13 | By: Nathan Seidle 14 | SparkFun Electronics 15 | Date: December 21st, 2017 16 | SparkFun code, firmware, and software is released under the MIT License. 17 | Please see LICENSE.md for further details. 18 | 19 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 20 | 21 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 22 | CEVA Sensor Hub Driver, found here: 23 | https://github.com/ceva-dsp/sh2 24 | 25 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 26 | for Adafruit Industries. Found here: 27 | https://github.com/adafruit/Adafruit_BNO08x 28 | 29 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 30 | BusIO library found here: 31 | https://github.com/adafruit/Adafruit_BusIO 32 | 33 | Hardware Connections: 34 | IoT RedBoard --> BNO08x 35 | QWIIC --> QWIIC 36 | A4 --> INT 37 | A5 --> RST 38 | 39 | BNO08x "mode" jumpers set for I2C (default): 40 | PSO: OPEN 41 | PS1: OPEN 42 | 43 | Serial.print it out at 115200 baud to serial monitor. 44 | 45 | Feel like supporting our work? Buy a board from SparkFun! 46 | https://www.sparkfun.com/products/22857 47 | */ 48 | 49 | #include 50 | 51 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 52 | BNO08x myIMU; 53 | 54 | // For the most reliable interaction with the SHTP bus, we need 55 | // to use hardware reset control, and to monitor the H_INT pin. 56 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 57 | // Note, these can be other GPIO if you like. 58 | // Define as -1 to disable these features. 59 | #define BNO08X_INT A4 60 | //#define BNO08X_INT -1 61 | #define BNO08X_RST A5 62 | //#define BNO08X_RST -1 63 | 64 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 65 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 66 | 67 | void setup() { 68 | Serial.begin(115200); 69 | 70 | while(!Serial) delay(10); // Wait for Serial to become available. 71 | // Necessary for boards with native USB (like the SAMD51 Thing+). 72 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 73 | // Comment out this while loop, or it will prevent the remaining code from running. 74 | 75 | Serial.println(); 76 | Serial.println("BNO08x Read Example"); 77 | 78 | Wire.begin(); 79 | 80 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 81 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 82 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 83 | while (1) 84 | ; 85 | } 86 | Serial.println("BNO08x found!"); 87 | 88 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 89 | 90 | setReports(); 91 | 92 | Serial.println("Reading events"); 93 | delay(100); 94 | } 95 | 96 | // Here is where you define the sensor outputs you want to receive 97 | void setReports(void) { 98 | Serial.println("Setting desired reports"); 99 | if (myIMU.enableGyroIntegratedRotationVector() == true) { 100 | Serial.println(F("Gryo Integrated Rotation vector enabled")); 101 | Serial.println(F("Output in form i, j, k, real, gyroX, gyroY, gyroZ")); 102 | } else { 103 | Serial.println("Could not enable gyro integrated rotation vector"); 104 | } 105 | } 106 | 107 | void loop() { 108 | delay(10); 109 | 110 | if (myIMU.wasReset()) { 111 | Serial.print("sensor was reset "); 112 | setReports(); 113 | } 114 | 115 | // Has a new event come in on the Sensor Hub Bus? 116 | if (myIMU.getSensorEvent() == true) { 117 | 118 | // is it the correct sensor data we want? 119 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_GYRO_INTEGRATED_ROTATION_VECTOR) { 120 | 121 | float RVI = myIMU.getGyroIntegratedRVI(); 122 | float RVJ = myIMU.getGyroIntegratedRVJ(); 123 | float RVK = myIMU.getGyroIntegratedRVK(); 124 | float RVReal = myIMU.getGyroIntegratedRVReal(); 125 | float gyroX = myIMU.getGyroIntegratedRVangVelX(); 126 | float gyroY = myIMU.getGyroIntegratedRVangVelY(); 127 | float gyroZ = myIMU.getGyroIntegratedRVangVelZ(); 128 | 129 | Serial.print(RVI, 2); 130 | Serial.print(F(",")); 131 | Serial.print(RVJ, 2); 132 | Serial.print(F(",")); 133 | Serial.print(RVK, 2); 134 | Serial.print(F(",")); 135 | Serial.print(RVReal, 2); 136 | Serial.print(F(",")); 137 | Serial.print(gyroX, 2); 138 | Serial.print(F(",")); 139 | Serial.print(gyroY, 2); 140 | Serial.print(F(",")); 141 | Serial.print(gyroZ, 2); 142 | 143 | Serial.println(); 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /examples/Example_13_EulerAngles/Example_13_EulerAngles.ino: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Using the BNO08x IMU 4 | 5 | Example : Euler Angles 6 | By: Paul Clark 7 | Date: April 28th, 2020 8 | 9 | This example shows how to output the Euler angles: roll, pitch and yaw. 10 | The yaw (compass heading) is tilt-compensated, which is nice. 11 | https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles 12 | https://github.com/sparkfun/SparkFun_MPU-9250-DMP_Arduino_Library/issues/5#issuecomment-306509440 13 | 14 | By: Nathan Seidle 15 | SparkFun Electronics 16 | Date: December 21st, 2017 17 | SparkFun code, firmware, and software is released under the MIT License. 18 | Please see LICENSE.md for further details. 19 | 20 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 21 | 22 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 23 | CEVA Sensor Hub Driver, found here: 24 | https://github.com/ceva-dsp/sh2 25 | 26 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 27 | for Adafruit Industries. Found here: 28 | https://github.com/adafruit/Adafruit_BNO08x 29 | 30 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 31 | BusIO library found here: 32 | https://github.com/adafruit/Adafruit_BusIO 33 | 34 | Hardware Connections: 35 | IoT RedBoard --> BNO08x 36 | QWIIC --> QWIIC 37 | A4 --> INT 38 | A5 --> RST 39 | 40 | BNO08x "mode" jumpers set for I2C (default): 41 | PSO: OPEN 42 | PS1: OPEN 43 | 44 | Serial.print it out at 115200 baud to serial monitor. 45 | 46 | Feel like supporting our work? Buy a board from SparkFun! 47 | https://www.sparkfun.com/products/22857 48 | */ 49 | 50 | #include 51 | 52 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 53 | BNO08x myIMU; 54 | 55 | // For the most reliable interaction with the SHTP bus, we need 56 | // to use hardware reset control, and to monitor the H_INT pin. 57 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 58 | // Note, these can be other GPIO if you like. 59 | // Define as -1 to disable these features. 60 | #define BNO08X_INT A4 61 | //#define BNO08X_INT -1 62 | #define BNO08X_RST A5 63 | //#define BNO08X_RST -1 64 | 65 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 66 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 67 | 68 | void setup() { 69 | Serial.begin(115200); 70 | 71 | while(!Serial) delay(10); // Wait for Serial to become available. 72 | // Necessary for boards with native USB (like the SAMD51 Thing+). 73 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 74 | // Comment out this while loop, or it will prevent the remaining code from running. 75 | 76 | Serial.println(); 77 | Serial.println("BNO08x Read Example"); 78 | 79 | Wire.begin(); 80 | 81 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 82 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 83 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 84 | while (1) 85 | ; 86 | } 87 | Serial.println("BNO08x found!"); 88 | 89 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 90 | 91 | setReports(); 92 | 93 | Serial.println("Reading events"); 94 | delay(100); 95 | } 96 | 97 | // Here is where you define the sensor outputs you want to receive 98 | void setReports(void) { 99 | Serial.println("Setting desired reports"); 100 | if (myIMU.enableRotationVector() == true) { 101 | Serial.println(F("Rotation vector enabled")); 102 | Serial.println(F("Output in form roll, pitch, yaw")); 103 | } else { 104 | Serial.println("Could not enable rotation vector"); 105 | } 106 | } 107 | 108 | void loop() { 109 | delay(10); 110 | 111 | if (myIMU.wasReset()) { 112 | Serial.print("sensor was reset "); 113 | setReports(); 114 | } 115 | 116 | // Has a new event come in on the Sensor Hub Bus? 117 | if (myIMU.getSensorEvent() == true) { 118 | 119 | // is it the correct sensor data we want? 120 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_ROTATION_VECTOR) { 121 | 122 | float roll = (myIMU.getRoll()) * 180.0 / PI; // Convert roll to degrees 123 | float pitch = (myIMU.getPitch()) * 180.0 / PI; // Convert pitch to degrees 124 | float yaw = (myIMU.getYaw()) * 180.0 / PI; // Convert yaw / heading to degrees 125 | 126 | Serial.print(roll, 1); 127 | Serial.print(F(",")); 128 | Serial.print(pitch, 1); 129 | Serial.print(F(",")); 130 | Serial.print(yaw, 1); 131 | 132 | Serial.println(); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /examples/Example_14_Tare/Example_14_Tare.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to use the Tare features of the sensor. 5 | It outputs the roll, pitch and yaw. 6 | Type letters into the terminal to execute Tare commands. 7 | 8 | Example : Tare function 9 | By: Sofian Audry 10 | Date: March 2nd, 2022 11 | 12 | Based on: Example9-Calibrate 13 | By: Nathan Seidle 14 | SparkFun Electronics 15 | Date: December 21st, 2017 16 | SparkFun code, firmware, and software is released under the MIT License. 17 | Please see LICENSE.md for further details. 18 | 19 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 20 | 21 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 22 | CEVA Sensor Hub Driver, found here: 23 | https://github.com/ceva-dsp/sh2 24 | 25 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 26 | for Adafruit Industries. Found here: 27 | https://github.com/adafruit/Adafruit_BNO08x 28 | 29 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 30 | BusIO library found here: 31 | https://github.com/adafruit/Adafruit_BusIO 32 | 33 | Hardware Connections: 34 | IoT RedBoard --> BNO08x 35 | QWIIC --> QWIIC 36 | A4 --> INT 37 | A5 --> RST 38 | 39 | BNO08x "mode" jumpers set for I2C (default): 40 | PSO: OPEN 41 | PS1: OPEN 42 | 43 | Serial.print it out at 115200 baud to serial monitor. 44 | 45 | Feel like supporting our work? Buy a board from SparkFun! 46 | https://www.sparkfun.com/products/22857 47 | */ 48 | 49 | #include 50 | 51 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 52 | BNO08x myIMU; 53 | 54 | // For the most reliable interaction with the SHTP bus, we need 55 | // to use hardware reset control, and to monitor the H_INT pin. 56 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 57 | // Note, these can be other GPIO if you like. 58 | // Define as -1 to disable these features. 59 | #define BNO08X_INT A4 60 | //#define BNO08X_INT -1 61 | #define BNO08X_RST A5 62 | //#define BNO08X_RST -1 63 | 64 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 65 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 66 | 67 | void setup() { 68 | Serial.begin(115200); 69 | 70 | while(!Serial) delay(10); // Wait for Serial to become available. 71 | // Necessary for boards with native USB (like the SAMD51 Thing+). 72 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 73 | // Comment out this while loop, or it will prevent the remaining code from running. 74 | 75 | Serial.println(); 76 | Serial.println("BNO08x Read Example"); 77 | 78 | //Once magnetic field is 2 or 3, run the Save DCD Now command 79 | Serial.println(F("'t' to tare according to xyz")); 80 | Serial.println(F("'z' to tare according to z axis only")); 81 | Serial.println(F("'s' to save tare settings")); 82 | Serial.println(F("'r' to reset/clear tare orientation registry")); 83 | Serial.println(F("Output in form x, y, z, in uTesla")); 84 | 85 | delay(1000); // you have one second to read the menu in the terminal. 86 | // or simply look at the code above, and take all the time you want. 87 | 88 | Wire.begin(); 89 | 90 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 91 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 92 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 93 | while (1) 94 | ; 95 | } 96 | Serial.println("BNO08x found!"); 97 | 98 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 99 | 100 | setReports(); 101 | 102 | Serial.println("Reading events"); 103 | delay(100); 104 | } 105 | 106 | // Here is where you define the sensor outputs you want to receive 107 | void setReports(void) { 108 | Serial.println("Setting desired reports"); 109 | if (myIMU.enableRotationVector() == true) { 110 | Serial.println(F("Rotation vector enabled")); 111 | Serial.println(F("Output in form roll, pitch, yaw")); 112 | } else { 113 | Serial.println("Could not enable rotation vector"); 114 | } 115 | } 116 | 117 | void loop() { 118 | if(Serial.available()) 119 | { 120 | byte incoming = Serial.read(); 121 | 122 | switch (incoming) { 123 | case 't': 124 | if(myIMU.tareNow()) {Serial.println("TareXYZ Success");} 125 | else {Serial.print ("TareXYZ Failure");} 126 | break; 127 | case 'z': 128 | if(myIMU.tareNow(true)) {Serial.println("TareZ Success");} 129 | else {Serial.print ("TareZ Failure");} 130 | break; 131 | case 's': 132 | if(myIMU.saveTare()) {Serial.println("Save Tare Success");} 133 | else {Serial.print ("Save Tare Failure");} 134 | break; 135 | case 'r': 136 | if(myIMU.clearTare()) {Serial.println("Clear Tare Success");} 137 | else {Serial.print ("Clear Tare Failure");} 138 | break; 139 | default:; 140 | } 141 | } 142 | 143 | delay(10); 144 | 145 | if (myIMU.wasReset()) { 146 | Serial.print("sensor was reset "); 147 | setReports(); 148 | } 149 | 150 | // Has a new event come in on the Sensor Hub Bus? 151 | if (myIMU.getSensorEvent() == true) { 152 | 153 | // is it the correct sensor data we want? 154 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_ROTATION_VECTOR) { 155 | 156 | float roll = (myIMU.getRoll()) * 180.0 / PI; // Convert roll to degrees 157 | float pitch = (myIMU.getPitch()) * 180.0 / PI; // Convert pitch to degrees 158 | float yaw = (myIMU.getYaw()) * 180.0 / PI; // Convert yaw / heading to degrees 159 | 160 | Serial.print(roll, 1); 161 | Serial.print(F(",")); 162 | Serial.print(pitch, 1); 163 | Serial.print(F(",")); 164 | Serial.print(yaw, 1); 165 | 166 | Serial.println(); 167 | } 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /examples/Example_15_Gravity/Example_15_Gravity.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to output sensor data to find the direction of gravity. 5 | 6 | By: Anant Sharma 7 | Date: January 23rd, 2023 8 | 9 | Based on other code written by: Nathan Seidle 10 | SparkFun Electronics 11 | Date: December 21st, 2017 12 | SparkFun code, firmware, and software is released under the MIT License. 13 | Please see LICENSE.md for further details. 14 | 15 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 16 | 17 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 18 | CEVA Sensor Hub Driver, found here: 19 | https://github.com/ceva-dsp/sh2 20 | 21 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 22 | for Adafruit Industries. Found here: 23 | https://github.com/adafruit/Adafruit_BNO08x 24 | 25 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 26 | BusIO library found here: 27 | https://github.com/adafruit/Adafruit_BusIO 28 | 29 | Hardware Connections: 30 | IoT RedBoard --> BNO08x 31 | QWIIC --> QWIIC 32 | A4 --> INT 33 | A5 --> RST 34 | 35 | BNO08x "mode" jumpers set for I2C (default): 36 | PSO: OPEN 37 | PS1: OPEN 38 | 39 | Serial.print it out at 115200 baud to serial monitor. 40 | 41 | Feel like supporting our work? Buy a board from SparkFun! 42 | https://www.sparkfun.com/products/22857 43 | */ 44 | 45 | #include 46 | 47 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 48 | BNO08x myIMU; 49 | 50 | // For the most reliable interaction with the SHTP bus, we need 51 | // to use hardware reset control, and to monitor the H_INT pin. 52 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 53 | // Note, these can be other GPIO if you like. 54 | // Define as -1 to disable these features. 55 | #define BNO08X_INT A4 56 | //#define BNO08X_INT -1 57 | #define BNO08X_RST A5 58 | //#define BNO08X_RST -1 59 | 60 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 61 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 62 | 63 | void setup() { 64 | Serial.begin(115200); 65 | 66 | while(!Serial) delay(10); // Wait for Serial to become available. 67 | // Necessary for boards with native USB (like the SAMD51 Thing+). 68 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 69 | // Comment out this while loop, or it will prevent the remaining code from running. 70 | 71 | Serial.println(); 72 | Serial.println("BNO08x Read Example"); 73 | 74 | Wire.begin(); 75 | 76 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 77 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 78 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 79 | while (1) 80 | ; 81 | } 82 | Serial.println("BNO08x found!"); 83 | 84 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 85 | 86 | setReports(); 87 | 88 | Serial.println("Reading events"); 89 | delay(100); 90 | } 91 | 92 | // Here is where you define the sensor outputs you want to receive 93 | void setReports(void) { 94 | Serial.println("Setting desired reports"); 95 | if (myIMU.enableGravity() == true) { 96 | Serial.println(F("Gravity enabled")); 97 | Serial.println(F("Output in form x, y, z, accuracy")); 98 | } else { 99 | Serial.println("Could not enable gravity"); 100 | } 101 | } 102 | 103 | void loop() { 104 | delay(10); 105 | 106 | if (myIMU.wasReset()) { 107 | Serial.print("sensor was reset "); 108 | setReports(); 109 | } 110 | 111 | // Has a new event come in on the Sensor Hub Bus? 112 | if (myIMU.getSensorEvent() == true) { 113 | 114 | // is it the correct sensor data we want? 115 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_GRAVITY) { 116 | 117 | float gravityX = myIMU.getGravityX(); 118 | float gravityY = myIMU.getGravityY(); 119 | float gravityZ = myIMU.getGravityZ(); 120 | float gravityAccuracy = myIMU.getGravityAccuracy(); 121 | 122 | Serial.print(gravityX, 2); 123 | Serial.print(F(",")); 124 | Serial.print(gravityY, 2); 125 | Serial.print(F(",")); 126 | Serial.print(gravityZ, 2); 127 | Serial.print(F(",")); 128 | Serial.print(gravityAccuracy, 2); 129 | 130 | Serial.println(); 131 | } 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /examples/Example_16_UncalibratedGyro/Example_16_UncalibratedGyro.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to output the parts of the uncalibrated gyro. 5 | 6 | By: Nathan Seidle 7 | SparkFun Electronics 8 | Date: December 21st, 2017 9 | SparkFun code, firmware, and software is released under the MIT License. 10 | Please see LICENSE.md for further details. 11 | 12 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 13 | 14 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 15 | CEVA Sensor Hub Driver, found here: 16 | https://github.com/ceva-dsp/sh2 17 | 18 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 19 | for Adafruit Industries. Found here: 20 | https://github.com/adafruit/Adafruit_BNO08x 21 | 22 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 23 | BusIO library found here: 24 | https://github.com/adafruit/Adafruit_BusIO 25 | 26 | Hardware Connections: 27 | IoT RedBoard --> BNO08x 28 | QWIIC --> QWIIC 29 | A4 --> INT 30 | A5 --> RST 31 | 32 | BNO08x "mode" jumpers set for I2C (default): 33 | PSO: OPEN 34 | PS1: OPEN 35 | 36 | Serial.print it out at 115200 baud to serial monitor. 37 | 38 | Feel like supporting our work? Buy a board from SparkFun! 39 | https://www.sparkfun.com/products/22857 40 | */ 41 | 42 | #include 43 | 44 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 45 | 46 | BNO08x myIMU; 47 | 48 | // For the most reliable interaction with the SHTP bus, we need 49 | // to use hardware reset control, and to monitor the H_INT pin. 50 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 51 | // Note, these can be other GPIO if you like. 52 | // Define as -1 to disable these features. 53 | #define BNO08X_INT A4 54 | //#define BNO08X_INT -1 55 | #define BNO08X_RST A5 56 | //#define BNO08X_RST -1 57 | 58 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 59 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 60 | 61 | void setup() { 62 | Serial.begin(115200); 63 | 64 | while(!Serial) delay(10); // Wait for Serial to become available. 65 | // Necessary for boards with native USB (like the SAMD51 Thing+). 66 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 67 | // Comment out this while loop, or it will prevent the remaining code from running. 68 | 69 | Serial.println(); 70 | Serial.println("BNO08x Read Example"); 71 | 72 | Wire.begin(); 73 | 74 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 75 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 76 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 77 | while (1) 78 | ; 79 | } 80 | Serial.println("BNO08x found!"); 81 | 82 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 83 | 84 | setReports(); 85 | 86 | Serial.println("Reading events"); 87 | delay(100); 88 | } 89 | 90 | // Here is where you define the sensor outputs you want to receive 91 | void setReports(void) { 92 | Serial.println("Setting desired reports"); 93 | if (myIMU.enableUncalibratedGyro() == true) { 94 | Serial.println(F("Uncalibrated Gyro enabled")); 95 | Serial.println(F("Output in form x, y, z, bx, by, bz in radians per second")); 96 | } else { 97 | Serial.println("Could not enable uncalibrated gyro"); 98 | } 99 | } 100 | 101 | void loop() { 102 | delay(10); 103 | 104 | if (myIMU.wasReset()) { 105 | Serial.print("sensor was reset "); 106 | setReports(); 107 | } 108 | 109 | // Has a new event come in on the Sensor Hub Bus? 110 | if (myIMU.getSensorEvent() == true) { 111 | 112 | // is it the correct sensor data we want? 113 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_UNCALIBRATED_GYRO) { 114 | 115 | float x = myIMU.getUncalibratedGyroX(); 116 | float y = myIMU.getUncalibratedGyroY(); 117 | float z = myIMU.getUncalibratedGyroZ(); 118 | float bx = myIMU.getUncalibratedGyroBiasX(); 119 | float by = myIMU.getUncalibratedGyroBiasY(); 120 | float bz = myIMU.getUncalibratedGyroBiasZ(); 121 | 122 | 123 | Serial.print(x, 2); 124 | Serial.print(F(",")); 125 | Serial.print(y, 2); 126 | Serial.print(F(",")); 127 | Serial.print(z, 2); 128 | Serial.print(F(",")); 129 | 130 | Serial.print(bx, 4); 131 | Serial.print(F(",")); 132 | Serial.print(by, 4); 133 | Serial.print(F(",")); 134 | Serial.print(bz, 4); 135 | 136 | Serial.println(); 137 | } 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /examples/Example_17_ResetCheck/Example_17_ResetCheck.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to reset the sensor and read back the Reset Cause. 5 | The sensor will be reset each time 100 readings are received to demonstrate. 6 | 7 | It outputs the x/y/z of the gyro. 8 | 9 | By: @mattbradford83 10 | Date: 1 August 2021 11 | 12 | By: Nathan Seidle 13 | SparkFun Electronics 14 | Date: December 21st, 2017 15 | SparkFun code, firmware, and software is released under the MIT License. 16 | Please see LICENSE.md for further details. 17 | 18 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 19 | 20 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 21 | CEVA Sensor Hub Driver, found here: 22 | https://github.com/ceva-dsp/sh2 23 | 24 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 25 | for Adafruit Industries. Found here: 26 | https://github.com/adafruit/Adafruit_BNO08x 27 | 28 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 29 | BusIO library found here: 30 | https://github.com/adafruit/Adafruit_BusIO 31 | 32 | Hardware Connections: 33 | IoT RedBoard --> BNO08x 34 | QWIIC --> QWIIC 35 | A4 --> INT 36 | A5 --> RST 37 | 38 | BNO08x "mode" jumpers set for I2C (default): 39 | PSO: OPEN 40 | PS1: OPEN 41 | 42 | Serial.print it out at 115200 baud to serial monitor. 43 | 44 | Feel like supporting our work? Buy a board from SparkFun! 45 | https://www.sparkfun.com/products/22857 46 | */ 47 | 48 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 49 | BNO08x myIMU; 50 | 51 | // For the most reliable interaction with the SHTP bus, we need 52 | // to use hardware reset control, and to monitor the H_INT pin. 53 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 54 | // Note, these can be other GPIO if you like. 55 | // Define as -1 to disable these features. 56 | #define BNO08X_INT A4 57 | //#define BNO08X_INT -1 58 | #define BNO08X_RST A5 59 | //#define BNO08X_RST -1 60 | 61 | int cyclecount = 0; 62 | 63 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 64 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 65 | 66 | void setup() { 67 | Serial.begin(115200); 68 | 69 | while(!Serial) delay(10); // Wait for Serial to become available. 70 | // Necessary for boards with native USB (like the SAMD51 Thing+). 71 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 72 | // Comment out this while loop, or it will prevent the remaining code from running. 73 | 74 | Serial.println(); 75 | Serial.println("BNO08x Read Example"); 76 | 77 | Wire.begin(); 78 | 79 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 80 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 81 | while (1) 82 | ; 83 | } 84 | Serial.println("BNO08x found!"); 85 | 86 | Serial.print(F("Reset Reason: ")); 87 | printResetReasonName(myIMU.getResetReason()); 88 | Serial.println(); 89 | 90 | setReports(); 91 | 92 | Serial.println("Reading events"); 93 | delay(100); 94 | } 95 | 96 | // Here is where you define the sensor outputs you want to receive 97 | void setReports(void) { 98 | Serial.println("Setting desired reports"); 99 | if (myIMU.enableGyro() == true) { 100 | Serial.println(F("Gyro enabled")); 101 | Serial.println(F("Output in form x, y, z, in radians per second")); 102 | } else { 103 | Serial.println("Could not enable gyro"); 104 | } 105 | } 106 | 107 | void loop() { 108 | delay(1); 109 | myIMU.serviceBus(); 110 | 111 | // One of these will appear at the very start because of the power on reset. 112 | // Use getResetReason() for the difference between different resets. 113 | if (myIMU.wasReset()) { 114 | Serial.println(" ------------------ BNO08x has reset. ------------------ "); 115 | Serial.print(F("Reset Reason: ")); 116 | printResetReasonName(myIMU.getResetReason()); 117 | Serial.println(); 118 | 119 | setReports(); // We'll need to re-enable reports after any reset. 120 | } 121 | 122 | // Has a new event come in on the Sensor Hub Bus? 123 | if (myIMU.getSensorEvent() == true) { 124 | 125 | // is it the correct sensor data we want? 126 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_GYROSCOPE_CALIBRATED) { 127 | 128 | cyclecount++; 129 | 130 | Serial.print(F("[")); 131 | if (cyclecount < 10) Serial.print(F("0")); 132 | Serial.print(cyclecount); 133 | Serial.print(F("] ")); 134 | 135 | float x = myIMU.getGyroX(); 136 | float y = myIMU.getGyroY(); 137 | float z = myIMU.getGyroZ(); 138 | 139 | Serial.print(x, 2); 140 | Serial.print(F(",")); 141 | Serial.print(y, 2); 142 | Serial.print(F(",")); 143 | Serial.print(z, 2); 144 | 145 | Serial.println(); 146 | 147 | if (cyclecount == 100) { 148 | myIMU.softReset(); 149 | cyclecount = 0; 150 | } 151 | } 152 | } 153 | } 154 | 155 | //Given a number between 0 and 5, print the name of the reset reason 156 | //1 = POR, 2 = Internal reset, 3 = Watchdog, 4 = External reset, 5 = Other 157 | void printResetReasonName(byte resetReasonNumber) 158 | { 159 | if(resetReasonNumber == 1) Serial.print("POR"); 160 | else if(resetReasonNumber == 2) Serial.print("Internal reset"); 161 | else if(resetReasonNumber == 3) Serial.print("Watchdog"); 162 | else if(resetReasonNumber == 4) Serial.print("External reset"); 163 | else if(resetReasonNumber == 5) Serial.print("Other"); 164 | } 165 | -------------------------------------------------------------------------------- /examples/Example_18_Sleep/Example_18_Sleep.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to use the sleep features of the sensor. 5 | 6 | *Note, in addition to the qwiic cable it also requires INT and RST. 7 | 8 | It toggles the sleep mode on/off every 5 seconds. 9 | 10 | When awake, this example outputs the i/j/k/real parts of the rotation vector. 11 | https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation 12 | 13 | By: Nathan Seidle 14 | SparkFun Electronics 15 | Date: December 21st, 2017 16 | SparkFun code, firmware, and software is released under the MIT License. 17 | Please see LICENSE.md for further details. 18 | 19 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 20 | 21 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 22 | CEVA Sensor Hub Driver, found here: 23 | https://github.com/ceva-dsp/sh2 24 | 25 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 26 | for Adafruit Industries. Found here: 27 | https://github.com/adafruit/Adafruit_BNO08x 28 | 29 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 30 | BusIO library found here: 31 | https://github.com/adafruit/Adafruit_BusIO 32 | 33 | Hardware Connections: 34 | IoT RedBoard --> BNO08x 35 | QWIIC --> QWIIC 36 | A4 --> INT 37 | A5 --> RST 38 | 39 | BNO08x "mode" jumpers set for I2C (default): 40 | PSO: OPEN 41 | PS1: OPEN 42 | 43 | Plug the sensor into IoT RedBoard via QWIIC cable. 44 | Serial.print it out at 115200 baud to serial monitor. 45 | 46 | Feel like supporting our work? Buy a board from SparkFun! 47 | https://www.sparkfun.com/products/22857 48 | */ 49 | 50 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 51 | BNO08x myIMU; 52 | 53 | // For the most reliable interaction with the SHTP bus, we need 54 | // to use hardware reset control, and to monitor the H_INT pin. 55 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 56 | // Note, these can be other GPIO if you like. 57 | // Define as -1 to disable these features. 58 | #define BNO08X_INT A4 59 | //#define BNO08X_INT -1 60 | #define BNO08X_RST A5 61 | //#define BNO08X_RST -1 62 | 63 | unsigned long lastMillis = 0; // Keep track of time 64 | bool lastPowerState = true; // Toggle between "On" and "Sleep" 65 | 66 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 67 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 68 | 69 | void setup() { 70 | Serial.begin(115200); 71 | 72 | while(!Serial) delay(10); // Wait for Serial to become available. 73 | // Necessary for boards with native USB (like the SAMD51 Thing+). 74 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 75 | // Comment out this while loop, or it will prevent the remaining code from running. 76 | 77 | Serial.println(); 78 | Serial.println("BNO08x Sleep Example"); 79 | 80 | Wire.begin(); 81 | 82 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 83 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 84 | while (1) 85 | ; 86 | } 87 | Serial.println("BNO08x found!"); 88 | 89 | setReports(); 90 | 91 | Serial.println("Reading events"); 92 | delay(100); 93 | 94 | lastMillis = millis(); // Keep track of time 95 | } 96 | 97 | // Here is where you define the sensor outputs you want to receive 98 | void setReports(void) { 99 | Serial.println("Setting desired reports"); 100 | if (myIMU.enableRotationVector() == true) { 101 | Serial.println(F("Rotation vector enabled")); 102 | Serial.println(F("Output in form i, j, k, real, accuracy")); 103 | } else { 104 | Serial.println("Could not enable rotation vector"); 105 | } 106 | } 107 | 108 | void loop() { 109 | delay(10); 110 | 111 | if (lastPowerState) // Are we "On"? 112 | { 113 | 114 | if (myIMU.wasReset()) { 115 | Serial.print("sensor was reset "); 116 | setReports(); 117 | } 118 | 119 | // Has a new event come in on the Sensor Hub Bus? 120 | if (myIMU.getSensorEvent() == true) { 121 | 122 | // is it the correct sensor data we want? 123 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_ROTATION_VECTOR) { 124 | 125 | float quatI = myIMU.getQuatI(); 126 | float quatJ = myIMU.getQuatJ(); 127 | float quatK = myIMU.getQuatK(); 128 | float quatReal = myIMU.getQuatReal(); 129 | float quatRadianAccuracy = myIMU.getQuatRadianAccuracy(); 130 | 131 | Serial.print(quatI, 2); 132 | Serial.print(F(",")); 133 | Serial.print(quatJ, 2); 134 | Serial.print(F(",")); 135 | Serial.print(quatK, 2); 136 | Serial.print(F(",")); 137 | Serial.print(quatReal, 2); 138 | Serial.print(F(",")); 139 | Serial.print(quatRadianAccuracy, 2); 140 | 141 | Serial.println(); 142 | } 143 | } 144 | } 145 | 146 | //Check if it is time to change the power state 147 | if (millis() > (lastMillis + 5000)) // Change state every 5 seconds 148 | { 149 | lastMillis = millis(); // Keep track of time 150 | 151 | if (lastPowerState) // Are we "On"? 152 | { 153 | Serial.println("Putting BNO08x to sleep..."); 154 | myIMU.modeSleep(); // Put BNO to sleep 155 | } else { 156 | Serial.println("Waking up BNO08x"); 157 | myIMU.modeOn(); // Turn BNO back on 158 | } 159 | 160 | lastPowerState ^= 1; // Invert lastPowerState (using ex-or) 161 | } 162 | } 163 | -------------------------------------------------------------------------------- /examples/Example_19_GeomagneticRotationVector_to_EulerAngles/Example_19_GeomagneticRotationVector_to_EulerAngles.ino: -------------------------------------------------------------------------------- 1 | 2 | /* 3 | Using the BNO08x IMU 4 | 5 | Example : Geomagnetic Rotation Vector to Euler Angles 6 | 7 | This example was initially created by github user SFSailor November 2023 8 | https://github.com/sparkfun/SparkFun_BNO08x_Arduino_Library/issues/10 9 | https://forum.sparkfun.com/viewtopic.php?f=83&t=60523&p=245145#p245145 10 | 11 | Modified from original example of Euler Angles 12 | By: Paul Clark 13 | Date: April 28th, 2020 14 | 15 | Using the Geomagnetic Rotation vectors, 16 | This example shows how to output the Euler angles: roll, pitch and yaw. 17 | The yaw (compass heading) is tilt-compensated, which is nice. 18 | https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles 19 | https://github.com/sparkfun/SparkFun_MPU-9250-DMP_Arduino_Library/issues/5#issuecomment-306509440 20 | 21 | By: Nathan Seidle 22 | SparkFun Electronics 23 | Date: December 21st, 2017 24 | SparkFun code, firmware, and software is released under the MIT License. 25 | Please see LICENSE.md for further details. 26 | 27 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 28 | 29 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 30 | CEVA Sensor Hub Driver, found here: 31 | https://github.com/ceva-dsp/sh2 32 | 33 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 34 | for Adafruit Industries. Found here: 35 | https://github.com/adafruit/Adafruit_BNO08x 36 | 37 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 38 | BusIO library found here: 39 | https://github.com/adafruit/Adafruit_BusIO 40 | 41 | Hardware Connections: 42 | IoT RedBoard --> BNO08x 43 | QWIIC --> QWIIC 44 | A4 --> INT 45 | A5 --> RST 46 | 47 | BNO08x "mode" jumpers set for I2C (default): 48 | PSO: OPEN 49 | PS1: OPEN 50 | 51 | Serial.print it out at 115200 baud to serial monitor. 52 | 53 | Feel like supporting our work? Buy a board from SparkFun! 54 | https://www.sparkfun.com/products/22857 55 | */ 56 | 57 | #include 58 | 59 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 60 | BNO08x myIMU; 61 | 62 | // For the most reliable interaction with the SHTP bus, we need 63 | // to use hardware reset control, and to monitor the H_INT pin. 64 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 65 | // Note, these can be other GPIO if you like. 66 | // Define as -1 to disable these features. 67 | #define BNO08X_INT A4 68 | //#define BNO08X_INT -1 69 | #define BNO08X_RST A5 70 | //#define BNO08X_RST -1 71 | 72 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 73 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 74 | 75 | void setup() { 76 | Serial.begin(115200); 77 | 78 | while(!Serial) delay(10); // Wait for Serial to become available. 79 | // Necessary for boards with native USB (like the SAMD51 Thing+). 80 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 81 | // Comment out this while loop, or it will prevent the remaining code from running. 82 | 83 | Serial.println(); 84 | Serial.println("BNO08x Read Example"); 85 | 86 | Wire.begin(); 87 | 88 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 89 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 90 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 91 | while (1) 92 | ; 93 | } 94 | Serial.println("BNO08x found!"); 95 | 96 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 97 | 98 | setReports(); 99 | 100 | Serial.println("Reading events"); 101 | delay(100); 102 | } 103 | 104 | // Here is where you define the sensor outputs you want to receive 105 | void setReports(void) { 106 | Serial.println("Setting desired reports"); 107 | if (myIMU.enableGeomagneticRotationVector() == true) { 108 | Serial.println(F("Geomagnetic Rotation vector enabled")); 109 | Serial.println(F("Output in form roll, pitch, yaw")); 110 | } else { 111 | Serial.println("Could not enable geomagnetic rotation vector"); 112 | } 113 | } 114 | 115 | void loop() { 116 | delay(10); 117 | 118 | if (myIMU.wasReset()) { 119 | Serial.print("sensor was reset "); 120 | setReports(); 121 | } 122 | 123 | // Has a new event come in on the Sensor Hub Bus? 124 | if (myIMU.getSensorEvent() == true) { 125 | 126 | // is it the correct sensor data we want? 127 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR) { 128 | 129 | float roll = (myIMU.getRoll()) * 180.0 / PI; // Convert roll to degrees 130 | float pitch = (myIMU.getPitch()) * 180.0 / PI; // Convert pitch to degrees 131 | float yaw = (myIMU.getYaw()) * 180.0 / PI; // Convert yaw / heading to degrees 132 | 133 | Serial.print(roll, 1); 134 | Serial.print(F(",")); 135 | Serial.print(pitch, 1); 136 | Serial.print(F(",")); 137 | Serial.print(yaw, 1); 138 | 139 | Serial.println(); 140 | } 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /examples/Example_20_CalibrationSettings/Example_20_CalibrationSettings.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to adjust settings of the dynamic calibration of the 5 | BNO08x. 6 | 7 | The BNO08x allows you to turn on/off dynamic calibration for each sensor in 8 | the IMU (accel, gyro, or mag). 9 | 10 | Please refer to the BNO08X data sheet Section 3 (page 37) 11 | https://docs.sparkfun.com/SparkFun_VR_IMU_Breakout_BNO086_QWIIC/assets/component_documentation/BNO080_085-Datasheet_v1.16.pdf 12 | 13 | Note, by default, dynamic calibration is enabled for accel and mag. 14 | Some special use cases may require turning on all or any special combo of sensor 15 | dynamic calibration. 16 | 17 | After the calibration settings are set, this example will output the 18 | x/y/z/accuracy of the mag and the i/j/k/real parts of the game rotation vector. 19 | https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation 20 | 21 | Note, the "simple calibration" feature, sh2_startCal(), is not available on 22 | the BNO08x. See this issue for more info: 23 | https://github.com/ceva-dsp/sh2/issues/11 24 | 25 | By: Nathan Seidle 26 | SparkFun Electronics 27 | Date: December 21st, 2017 28 | SparkFun code, firmware, and software is released under the MIT License. 29 | Please see LICENSE.md for further details. 30 | 31 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 32 | 33 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 34 | CEVA Sensor Hub Driver, found here: 35 | https://github.com/ceva-dsp/sh2 36 | 37 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 38 | for Adafruit Industries. Found here: 39 | https://github.com/adafruit/Adafruit_BNO08x 40 | 41 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 42 | BusIO library found here: 43 | https://github.com/adafruit/Adafruit_BusIO 44 | 45 | Hardware Connections: 46 | IoT RedBoard --> BNO08x 47 | QWIIC --> QWIIC 48 | A4 --> INT 49 | A5 --> RST 50 | 51 | BNO08x "mode" jumpers set for I2C (default): 52 | PSO: OPEN 53 | PS1: OPEN 54 | 55 | Serial.print it out at 115200 baud to serial monitor. 56 | 57 | Feel like supporting our work? Buy a board from SparkFun! 58 | https://www.sparkfun.com/products/22857 59 | */ 60 | 61 | #include 62 | 63 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 64 | BNO08x myIMU; 65 | 66 | // For the most reliable interaction with the SHTP bus, we need 67 | // to use hardware reset control, and to monitor the H_INT pin. 68 | // The H_INT pin will go low when its okay to talk on the SHTP bus. 69 | // Note, these can be other GPIO if you like. 70 | // Define as -1 to disable these features. 71 | #define BNO08X_INT A4 72 | //#define BNO08X_INT -1 73 | #define BNO08X_RST A5 74 | //#define BNO08X_RST -1 75 | 76 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 77 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 78 | 79 | // variables to store all our incoming values 80 | 81 | // mags 82 | float mx; 83 | float my; 84 | float mz; 85 | byte magAccuracy; 86 | 87 | // quats 88 | float quatI; 89 | float quatJ; 90 | float quatK; 91 | float quatReal; 92 | 93 | unsigned long previousDebugMicros = 0; 94 | #define DEBUG_INTERVAL_MICROSECONDS 10000 95 | 96 | void setup() { 97 | Serial.begin(115200); 98 | 99 | while(!Serial) delay(10); // Wait for Serial to become available. 100 | // Necessary for boards with native USB (like the SAMD51 Thing+). 101 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 102 | // Comment out this while loop, or it will prevent the remaining code from running. 103 | 104 | Serial.println(); 105 | Serial.println("BNO08x Calibration Example"); 106 | 107 | Wire.begin(); 108 | 109 | //if (myIMU.begin() == false) { // Setup without INT/RST control (Not Recommended) 110 | if (myIMU.begin(BNO08X_ADDR, Wire, BNO08X_INT, BNO08X_RST) == false) { 111 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 112 | while (1) 113 | ; 114 | } 115 | Serial.println("BNO08x found!"); 116 | 117 | // Wire.setClock(400000); //Increase I2C data rate to 400kHz 118 | 119 | // Enable dynamic calibration for desired sensors (accel, gyro, and mag) 120 | // uncomment/comment out as needed to try various options 121 | if (myIMU.setCalibrationConfig(SH2_CAL_ACCEL || SH2_CAL_GYRO || SH2_CAL_MAG) == true) { // all three sensors 122 | //if (myIMU.setCalibrationConfig(SH2_CAL_ACCEL || SH2_CAL_MAG) == true) { // Default settings 123 | //if (myIMU.setCalibrationConfig(SH2_CAL_ACCEL) == true) { // only accel 124 | Serial.println(F("Calibration Command Sent Successfully")); 125 | } else { 126 | Serial.println("Could not send Calibration Command. Freezing..."); 127 | while(1) delay(10); 128 | } 129 | 130 | setReports(); 131 | 132 | Serial.println("Reading events"); 133 | delay(100); 134 | } 135 | 136 | // Here is where you define the sensor outputs you want to receive 137 | void setReports(void) { 138 | Serial.println("Setting desired reports"); 139 | 140 | if (myIMU.enableMagnetometer(1) == true) { 141 | Serial.println(F("Magnetometer enabled")); 142 | Serial.println(F("Output in form x, y, z, in uTesla")); 143 | } else { 144 | Serial.println("Could not enable magnetometer"); 145 | } 146 | 147 | if (myIMU.enableGameRotationVector(1) == true) { 148 | Serial.println(F("Game Rotation vector enabled")); 149 | Serial.println(F("Output in form i, j, k, real")); 150 | } else { 151 | Serial.println("Could not enable game rotation vector"); 152 | } 153 | } 154 | 155 | void loop() { 156 | delayMicroseconds(10); 157 | 158 | if (myIMU.wasReset()) { 159 | Serial.print("sensor was reset "); 160 | setReports(); 161 | } 162 | 163 | // Has a new event come in on the Sensor Hub Bus? 164 | if (myIMU.getSensorEvent() == true) { 165 | // is the event a report of the magnetometer? 166 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_MAGNETIC_FIELD) { 167 | mx = myIMU.getMagX(); 168 | my = myIMU.getMagY(); 169 | mz = myIMU.getMagZ(); 170 | magAccuracy = myIMU.getMagAccuracy(); 171 | } 172 | // is the event a report of the game rotation vector? 173 | else if (myIMU.getSensorEventID() == SENSOR_REPORTID_GAME_ROTATION_VECTOR) { 174 | quatI = myIMU.getGameQuatI(); 175 | quatJ = myIMU.getGameQuatJ(); 176 | quatK = myIMU.getGameQuatK(); 177 | quatReal = myIMU.getGameQuatReal(); 178 | } 179 | } 180 | 181 | // Only print data to the terminal at a user defined interval 182 | // Each data type (accel or gyro or mag) is reported from the 183 | // BNO086 as separate messages. 184 | // To allow for all these separate messages to arrive, and thus 185 | // have updated data on all axis/types, 186 | // The report intervals for each datatype must be much faster 187 | // than our debug interval. 188 | 189 | // time since last debug data printed to terminal 190 | unsigned long microsSinceLastSerialPrint = (micros() - previousDebugMicros); 191 | 192 | // Only print data to the terminal at a user deficed interval 193 | if(microsSinceLastSerialPrint > DEBUG_INTERVAL_MICROSECONDS) 194 | { 195 | Serial.print(mx, 2); 196 | Serial.print("\t\t"); 197 | Serial.print(my, 2); 198 | Serial.print("\t\t"); 199 | Serial.print(mz, 2); 200 | Serial.print("\t\t"); 201 | printAccuracyLevel(magAccuracy); 202 | Serial.print("\t\t"); 203 | 204 | Serial.print(quatI, 2); 205 | Serial.print("\t\t"); 206 | Serial.print(quatJ, 2); 207 | Serial.print("\t\t"); 208 | Serial.print(quatK, 2); 209 | Serial.print("\t\t"); 210 | Serial.print(quatReal, 2); 211 | Serial.print("\t\t"); 212 | 213 | Serial.print(microsSinceLastSerialPrint); 214 | Serial.println(); 215 | previousDebugMicros = micros(); 216 | } 217 | 218 | if(Serial.available()) 219 | { 220 | byte incoming = Serial.read(); 221 | 222 | if(incoming == 's') 223 | { 224 | // Saves the current dynamic calibration data (DCD) to memory 225 | // Note, The BNO08X stores updated Dynamic Calibration Data (DCD) to RAM 226 | // frequently (every 5 seconds), so this command may not be necessary 227 | // depending on your application. 228 | if (myIMU.saveCalibration() == true) { 229 | Serial.println(F("Calibration data was saved successfully")); 230 | } else { 231 | Serial.println("Save Calibration Failure"); 232 | } 233 | } 234 | } 235 | } 236 | 237 | //Given a accuracy number, print what it means 238 | void printAccuracyLevel(byte accuracyNumber) 239 | { 240 | if(accuracyNumber == 0) Serial.print(F("Unreliable")); 241 | else if(accuracyNumber == 1) Serial.print(F("Low")); 242 | else if(accuracyNumber == 2) Serial.print(F("Medium")); 243 | else if(accuracyNumber == 3) Serial.print(F("High")); 244 | } -------------------------------------------------------------------------------- /examples/SPI/Example_01_SPI_RotationVector/Example_01_SPI_RotationVector.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to communicate with the sensor over SPI. 5 | 6 | It requires a few more connections than the qwiic cable. 7 | In addition to your usual SPI lines (CS/PICO/POCI/SCK), 8 | This also requires INT and RST. These are crucial for timing when talking to 9 | this sensor. 10 | 11 | It outputs the i/j/k/real parts of the rotation vector. 12 | https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation 13 | 14 | By: Nathan Seidle 15 | SparkFun Electronics 16 | Date: December 21st, 2017 17 | SparkFun code, firmware, and software is released under the MIT License. 18 | Please see LICENSE.md for further details. 19 | 20 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 21 | 22 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 23 | CEVA Sensor Hub Driver, found here: 24 | https://github.com/ceva-dsp/sh2 25 | 26 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 27 | for Adafruit Industries. Found here: 28 | https://github.com/adafruit/Adafruit_BNO08x 29 | 30 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 31 | BusIO library found here: 32 | https://github.com/adafruit/Adafruit_BusIO 33 | 34 | Hardware Connections: 35 | IoT RedBoard --> BNO08x 36 | D5 --> CS 37 | PICO --> SI 38 | POCI --> SO 39 | SCK --> SCK 40 | A4 --> INT 41 | A5 --> RST 42 | 3V3 --> 3V3 43 | GND --> GND 44 | 45 | BNO08x "mode" pins set for SPI: 46 | PSO --> 3V3 47 | PS1 --> 3V3 48 | 49 | Serial.print it out at 115200 baud to serial monitor. 50 | 51 | Feel like supporting our work? Buy a board from SparkFun! 52 | https://www.sparkfun.com/products/22857 53 | */ 54 | 55 | //#include 56 | 57 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 58 | BNO08x myIMU; 59 | 60 | // For SPI, we need some extra pins defined: 61 | // Note, these can be other GPIO if you like. 62 | #define BNO08X_CS 5 63 | #define BNO08X_INT A4 64 | #define BNO08X_RST A5 65 | 66 | // If using the MicroMod Machine Learning Carrier Board, use these pins: 67 | // for more info see https://github.com/sparkfun/SparkFun_BNO08x_Arduino_Library/issues/19 68 | //#define BNO08X_CS PWM0 69 | //#define BNO08X_INT D0 // Note, D0 is also the CS pin for the camera, so you'll need to change that if you're using both. 70 | // a good alternative for D0 is PWM1, (A0 and A1 are only inputs on the carrier board). 71 | //#define BNO08X_RST D1 72 | 73 | void setup() { 74 | Serial.begin(115200); 75 | 76 | while(!Serial) delay(10); // Wait for Serial to become available. 77 | // Necessary for boards with native USB (like the SAMD51 Thing+). 78 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 79 | // Comment out this while loop, or it will prevent the remaining code from running. 80 | 81 | Serial.println(); 82 | Serial.println("BNO08x Read Example"); 83 | 84 | if (myIMU.beginSPI(BNO08X_CS, BNO08X_INT, BNO08X_RST) == false) { 85 | Serial.println("BNO08x not detected. Check your jumpers and the hookup guide. Freezing..."); 86 | while (1) 87 | ; 88 | } 89 | Serial.println("BNO08x found!"); 90 | 91 | setReports(); 92 | 93 | Serial.println("Reading events"); 94 | delay(100); 95 | } 96 | 97 | // Here is where you define the sensor outputs you want to receive 98 | void setReports(void) { 99 | Serial.println("Setting desired reports"); 100 | if (myIMU.enableRotationVector() == true) { 101 | Serial.println(F("Rotation vector enabled")); 102 | Serial.println(F("Output in form i, j, k, real, accuracy")); 103 | } else { 104 | Serial.println("Could not enable rotation vector"); 105 | } 106 | delay(100); // This delay allows enough time for the BNO086 to accept the new 107 | // configuration and clear its reset status 108 | } 109 | 110 | void loop() { 111 | delay(10); 112 | 113 | if (myIMU.wasReset()) { 114 | Serial.print("sensor was reset "); 115 | setReports(); 116 | } 117 | 118 | // Has a new event come in on the Sensor Hub Bus? 119 | if (myIMU.getSensorEvent() == true) { 120 | 121 | // is it the correct sensor data we want? 122 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_ROTATION_VECTOR) { 123 | 124 | float quatI = myIMU.getQuatI(); 125 | float quatJ = myIMU.getQuatJ(); 126 | float quatK = myIMU.getQuatK(); 127 | float quatReal = myIMU.getQuatReal(); 128 | float quatRadianAccuracy = myIMU.getQuatRadianAccuracy(); 129 | 130 | Serial.print(quatI, 2); 131 | Serial.print(F(",")); 132 | Serial.print(quatJ, 2); 133 | Serial.print(F(",")); 134 | Serial.print(quatK, 2); 135 | Serial.print(F(",")); 136 | Serial.print(quatReal, 2); 137 | Serial.print(F(",")); 138 | Serial.print(quatRadianAccuracy, 2); 139 | 140 | Serial.println(); 141 | } 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /examples/SPI/Example_02_SPI_ResetCheck/Example_02_SPI_ResetCheck.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how check for a "Reset Complete" message from the sensor, 5 | which is helpful when used in tandem with requestResetReason() and 6 | getResetReason(). The sensor will be reset each time 100 readings are received 7 | to demonstrate. 8 | 9 | It outputs the x/y/z parts of the gyro. 10 | 11 | By: @mattbradford83 12 | Date: 1 August 2021 13 | 14 | By: Nathan Seidle 15 | SparkFun Electronics 16 | Date: December 21st, 2017 17 | SparkFun code, firmware, and software is released under the MIT License. 18 | Please see LICENSE.md for further details. 19 | 20 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 21 | 22 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 23 | CEVA Sensor Hub Driver, found here: 24 | https://github.com/ceva-dsp/sh2 25 | 26 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 27 | for Adafruit Industries. Found here: 28 | https://github.com/adafruit/Adafruit_BNO08x 29 | 30 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 31 | BusIO library found here: 32 | https://github.com/adafruit/Adafruit_BusIO 33 | 34 | Hardware Connections: 35 | IoT RedBoard --> BNO08x 36 | D5 --> CS 37 | PICO --> SI 38 | POCI --> SO 39 | SCK --> SCK 40 | A4 --> INT 41 | A5 --> RST 42 | 3V3 --> 3V3 43 | GND --> GND 44 | 45 | BNO08x "mode" pins set for SPI: 46 | PSO --> 3V3 47 | PS1 --> 3V3 48 | 49 | Serial.print it out at 115200 baud to serial monitor. 50 | 51 | Feel like supporting our work? Buy a board from SparkFun! 52 | https://www.sparkfun.com/products/22857 53 | */ 54 | 55 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 56 | BNO08x myIMU; 57 | 58 | // For SPI, we need some extra pins defined: 59 | // Note, these can be other GPIO if you like. 60 | #define BNO08X_CS 5 61 | #define BNO08X_INT A4 62 | #define BNO08X_RST A5 63 | 64 | // If using the MicroMod Machine Learning Carrier Board, use these pins: 65 | // for more info see https://github.com/sparkfun/SparkFun_BNO08x_Arduino_Library/issues/19 66 | //#define BNO08X_CS PWM0 67 | //#define BNO08X_INT D0 // Note, D0 is also the CS pin for the camera, so you'll need to change that if you're using both. 68 | // a good alternative for D0 is PWM1, (A0 and A1 are only inputs on the carrier board). 69 | //#define BNO08X_RST D1 70 | 71 | int cyclecount = 0; 72 | 73 | #define BNO08X_ADDR 0x4B // SparkFun BNO08x Breakout (Qwiic) defaults to 0x4B 74 | //#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed 75 | 76 | void setup() { 77 | Serial.begin(115200); 78 | 79 | while(!Serial) delay(10); // Wait for Serial to become available. 80 | // Necessary for boards with native USB (like the SAMD51 Thing+). 81 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 82 | // Comment out this while loop, or it will prevent the remaining code from running. 83 | 84 | Serial.println(); 85 | Serial.println("BNO08x Read Example"); 86 | 87 | Wire.begin(); 88 | 89 | if (myIMU.beginSPI(BNO08X_CS, BNO08X_INT, BNO08X_RST) == false) { 90 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 91 | while (1) 92 | ; 93 | } 94 | Serial.println("BNO08x found!"); 95 | 96 | Serial.print(F("Reset Reason: ")); 97 | printResetReasonName(myIMU.getResetReason()); 98 | Serial.println(); 99 | 100 | setReports(); 101 | 102 | Serial.println("Reading events"); 103 | delay(100); 104 | } 105 | 106 | // Here is where you define the sensor outputs you want to receive 107 | void setReports(void) { 108 | Serial.println("Setting desired reports"); 109 | if (myIMU.enableGyro() == true) { 110 | Serial.println(F("Gyro enabled")); 111 | Serial.println(F("Output in form x, y, z, in radians per second")); 112 | } else { 113 | Serial.println("Could not enable gyro"); 114 | } 115 | delay(100); // This delay allows enough time for the BNO086 to accept the new 116 | // configuration and clear its reset status 117 | } 118 | 119 | void loop() { 120 | delay(1); 121 | myIMU.serviceBus(); 122 | 123 | // One of these will appear at the very start because of the power on reset. 124 | // Use requestResetReason() and getResetReason() for the difference between 125 | // different resets. 126 | if (myIMU.wasReset()) { 127 | Serial.println(" ------------------ BNO08x has reset. ------------------ "); 128 | Serial.print(F("Reset Reason: ")); 129 | printResetReasonName(myIMU.getResetReason()); 130 | Serial.println(); 131 | 132 | setReports(); // We'll need to re-enable reports after any reset. 133 | } 134 | 135 | // Has a new event come in on the Sensor Hub Bus? 136 | if (myIMU.getSensorEvent() == true) { 137 | 138 | // is it the correct sensor data we want? 139 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_GYROSCOPE_CALIBRATED) { 140 | 141 | cyclecount++; 142 | 143 | Serial.print(F("[")); 144 | if (cyclecount < 10) Serial.print(F("0")); 145 | Serial.print(cyclecount); 146 | Serial.print(F("] ")); 147 | 148 | float x = myIMU.getGyroX(); 149 | float y = myIMU.getGyroY(); 150 | float z = myIMU.getGyroZ(); 151 | 152 | Serial.print(x, 2); 153 | Serial.print(F(",")); 154 | Serial.print(y, 2); 155 | Serial.print(F(",")); 156 | Serial.print(z, 2); 157 | 158 | Serial.println(); 159 | 160 | if (cyclecount == 100) { 161 | myIMU.softReset(); 162 | cyclecount = 0; 163 | } 164 | } 165 | } 166 | } 167 | 168 | 169 | //Given a number between 0 and 5, print the name of the reset reason 170 | //1 = POR, 2 = Internal reset, 3 = Watchdog, 4 = External reset, 5 = Other 171 | void printResetReasonName(byte resetReasonNumber) 172 | { 173 | if(resetReasonNumber == 1) Serial.print("POR"); 174 | else if(resetReasonNumber == 2) Serial.print("Internal reset"); 175 | else if(resetReasonNumber == 3) Serial.print("Watchdog"); 176 | else if(resetReasonNumber == 4) Serial.print("External reset"); 177 | else if(resetReasonNumber == 5) Serial.print("Other"); 178 | } 179 | -------------------------------------------------------------------------------- /examples/SPI/Example_03_SPI_Sleep/Example_03_SPI_Sleep.ino: -------------------------------------------------------------------------------- 1 | /* 2 | Using the BNO08x IMU 3 | 4 | This example shows how to use the sleep features of the sensor. 5 | 6 | It toggles the sleep mode on/off every 5 seconds. 7 | 8 | When awake, this example outputs the i/j/k/real parts of the rotation vector. 9 | https://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation 10 | 11 | By: Nathan Seidle 12 | SparkFun Electronics 13 | Date: December 21st, 2017 14 | SparkFun code, firmware, and software is released under the MIT License. 15 | Please see LICENSE.md for further details. 16 | 17 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 18 | 19 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 20 | CEVA Sensor Hub Driver, found here: 21 | https://github.com/ceva-dsp/sh2 22 | 23 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 24 | for Adafruit Industries. Found here: 25 | https://github.com/adafruit/Adafruit_BNO08x 26 | 27 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 28 | BusIO library found here: 29 | https://github.com/adafruit/Adafruit_BusIO 30 | 31 | Hardware Connections: 32 | IoT RedBoard --> BNO08x 33 | D5 --> CS 34 | PICO --> SI 35 | POCI --> SO 36 | SCK --> SCK 37 | A4 --> INT 38 | A5 --> RST 39 | 3V3 --> 3V3 40 | GND --> GND 41 | 42 | BNO08x "mode" pins set for SPI: 43 | PSO --> 3V3 44 | PS1 --> 3V3 45 | 46 | Serial.print it out at 115200 baud to serial monitor. 47 | 48 | Feel like supporting our work? Buy a board from SparkFun! 49 | https://www.sparkfun.com/products/22857 50 | */ 51 | 52 | #include "SparkFun_BNO08x_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BNO08x 53 | BNO08x myIMU; 54 | 55 | // For SPI, we need some extra pins defined: 56 | // Note, these can be other GPIO if you like. 57 | #define BNO08X_CS 5 58 | #define BNO08X_INT A4 59 | #define BNO08X_RST A5 60 | 61 | // If using the MicroMod Machine Learning Carrier Board, use these pins: 62 | // for more info see https://github.com/sparkfun/SparkFun_BNO08x_Arduino_Library/issues/19 63 | //#define BNO08X_CS PWM0 64 | //#define BNO08X_INT D0 // Note, D0 is also the CS pin for the camera, so you'll need to change that if you're using both. 65 | // a good alternative for D0 is PWM1, (A0 and A1 are only inputs on the carrier board). 66 | //#define BNO08X_RST D1 67 | 68 | unsigned long lastMillis = 0; // Keep track of time 69 | bool lastPowerState = true; // Toggle between "On" and "Sleep" 70 | 71 | void setup() { 72 | Serial.begin(115200); 73 | 74 | while(!Serial) delay(10); // Wait for Serial to become available. 75 | // Necessary for boards with native USB (like the SAMD51 Thing+). 76 | // For a final version of a project that does not need serial debug (or a USB cable plugged in), 77 | // Comment out this while loop, or it will prevent the remaining code from running. 78 | 79 | Serial.println(); 80 | Serial.println("BNO08x Sleep Example"); 81 | 82 | if (myIMU.beginSPI(BNO08X_CS, BNO08X_INT, BNO08X_RST) == false) { 83 | Serial.println("BNO08x not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); 84 | while (1) 85 | ; 86 | } 87 | Serial.println("BNO08x found!"); 88 | 89 | setReports(); 90 | 91 | Serial.println("Reading events"); 92 | delay(100); 93 | 94 | lastMillis = millis(); // Keep track of time 95 | } 96 | 97 | // Here is where you define the sensor outputs you want to receive 98 | void setReports(void) { 99 | Serial.println("Setting desired reports"); 100 | if (myIMU.enableRotationVector() == true) { 101 | Serial.println(F("Rotation vector enabled")); 102 | Serial.println(F("Output in form i, j, k, real, accuracy")); 103 | } else { 104 | Serial.println("Could not enable rotation vector"); 105 | } 106 | delay(100); // This delay allows enough time for the BNO086 to accept the new 107 | // configuration and clear its reset status 108 | } 109 | 110 | void loop() { 111 | delay(10); 112 | 113 | if (lastPowerState) // Are we "On"? 114 | { 115 | 116 | if (myIMU.wasReset()) { 117 | Serial.print("sensor was reset "); 118 | setReports(); 119 | } 120 | 121 | // Has a new event come in on the Sensor Hub Bus? 122 | if (myIMU.getSensorEvent() == true) { 123 | 124 | // is it the correct sensor data we want? 125 | if (myIMU.getSensorEventID() == SENSOR_REPORTID_ROTATION_VECTOR) { 126 | 127 | float quatI = myIMU.getQuatI(); 128 | float quatJ = myIMU.getQuatJ(); 129 | float quatK = myIMU.getQuatK(); 130 | float quatReal = myIMU.getQuatReal(); 131 | float quatRadianAccuracy = myIMU.getQuatRadianAccuracy(); 132 | 133 | Serial.print(quatI, 2); 134 | Serial.print(F(",")); 135 | Serial.print(quatJ, 2); 136 | Serial.print(F(",")); 137 | Serial.print(quatK, 2); 138 | Serial.print(F(",")); 139 | Serial.print(quatReal, 2); 140 | Serial.print(F(",")); 141 | Serial.print(quatRadianAccuracy, 2); 142 | Serial.print(F(",")); 143 | 144 | Serial.println(); 145 | } 146 | } 147 | } 148 | 149 | //Check if it is time to change the power state 150 | if (millis() > (lastMillis + 5000)) // Change state every 5 seconds 151 | { 152 | lastMillis = millis(); // Keep track of time 153 | 154 | if (lastPowerState) // Are we "On"? 155 | { 156 | Serial.println("Putting BNO08x to sleep..."); 157 | myIMU.modeSleep(); // Put BNO to sleep 158 | } else { 159 | Serial.println("Waking up BNO08x"); 160 | myIMU.modeOn(); // Turn BNO back on 161 | } 162 | 163 | lastPowerState ^= 1; // Invert lastPowerState (using ex-or) 164 | } 165 | } 166 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | BNO08x KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | begin KEYWORD2 16 | beginSPI KEYWORD2 17 | 18 | enableDebugging KEYWORD2 19 | 20 | softReset KEYWORD2 21 | resetReason KEYWORD2 22 | wasReset KEYWORD2 23 | modeOn KEYWORD2 24 | modeSleep KEYWORD2 25 | 26 | qToFloat KEYWORD2 27 | 28 | enableRotationVector KEYWORD2 29 | enableGeomagneticRotationVector KEYWORD2 30 | enableGameRotationVector KEYWORD2 31 | enableARVRStabilizedRotationVector KEYWORD2 32 | enableARVRStabilizedGameRotationVector KEYWORD2 33 | enableAccelerometer KEYWORD2 34 | enableGyro KEYWORD2 35 | enableUncalibratedGyro KEYWORD2 36 | enableGravity KEYWORD2 37 | enableMagnetometer KEYWORD2 38 | enableTapDetector KEYWORD2 39 | enableStepCounter KEYWORD2 40 | enableStabilityClassifier KEYWORD2 41 | enableActivityClassifier KEYWORD2 42 | enableLinearAccelerometer KEYWORD2 43 | enableRawAccelerometer KEYWORD2 44 | enableRawGyro KEYWORD2 45 | enableRawMagnetometer KEYWORD2 46 | enableGyroIntegratedRotationVector KEYWORD2 47 | 48 | getQuat KEYWORD2 49 | getQuatI KEYWORD2 50 | getQuatJ KEYWORD2 51 | getQuatK KEYWORD2 52 | getQuatReal KEYWORD2 53 | getQuatRadianAccuracy KEYWORD2 54 | getQuatAccuracy KEYWORD2 55 | 56 | getAccel KEYWORD2 57 | getAccelX KEYWORD2 58 | getAccelY KEYWORD2 59 | getAccelZ KEYWORD2 60 | getAccelAccuracy KEYWORD2 61 | 62 | getGyro KEYWORD2 63 | getGyroX KEYWORD2 64 | getGyroY KEYWORD2 65 | getGyroZ KEYWORD2 66 | getGyroAccuracy KEYWORD2 67 | 68 | getUncalibratedGyro KEYWORD2 69 | getUncalibratedGyroX KEYWORD2 70 | getUncalibratedGyroY KEYWORD2 71 | getUncalibratedGyroZ KEYWORD2 72 | getUncalibratedGyroAccuracy KEYWORD2 73 | getUncalibratedGyroBiasX KEYWORD2 74 | getUncalibratedGyroBiasY KEYWORD2 75 | getUncalibratedGyroBiasZ KEYWORD2 76 | 77 | getGravity KEYWORD2 78 | getGravityX KEYWORD2 79 | getGravityY KEYWORD2 80 | getGravityZ KEYWORD2 81 | getGravityAccuracy KEYWORD2 82 | 83 | getGyroIntegratedRVI KEYWORD2 84 | getGyroIntegratedRVJ KEYWORD2 85 | getGyroIntegratedRVK KEYWORD2 86 | getGyroIntegratedRVReal KEYWORD2 87 | getGyroIntegratedRVangVelX KEYWORD2 88 | getGyroIntegratedRVangVelY KEYWORD2 89 | getGyroIntegratedRVangVelZ KEYWORD2 90 | 91 | getMag KEYWORD2 92 | getMagX KEYWORD2 93 | getMagY KEYWORD2 94 | getMagZ KEYWORD2 95 | getMagAccuracy KEYWORD2 96 | 97 | getLinAccel KEYWORD2 98 | getLinAccelX KEYWORD2 99 | getLinAccelY KEYWORD2 100 | getLinAccelZ KEYWORD2 101 | getLinAccelAccuracy KEYWORD2 102 | 103 | setCalibrationConfig KEYWORD2 104 | saveCalibration KEYWORD2 105 | 106 | tareNow KEYWORD2 107 | saveTare KEYWORD2 108 | clearTare KEYWORD2 109 | sendTareCommand KEYWORD2 110 | 111 | getTapDetector KEYWORD2 112 | getTimeStamp KEYWORD2 113 | getStepCount KEYWORD2 114 | getStabilityClassifier KEYWORD2 115 | getActivityClassifier KEYWORD2 116 | 117 | sendCommand KEYWORD2 118 | sendCalibrateCommand KEYWORD2 119 | calibrationComplete KEYWORD2 120 | 121 | getQ1 KEYWORD2 122 | getQ2 KEYWORD2 123 | getQ3 KEYWORD2 124 | getResolution KEYWORD2 125 | getRange KEYWORD2 126 | readFRSword KEYWORD2 127 | frsReadRequest KEYWORD2 128 | readFRSdata KEYWORD2 129 | 130 | getRawAccelX KEYWORD2 131 | getRawAccelY KEYWORD2 132 | getRawAccelZ KEYWORD2 133 | 134 | getRawGyroX KEYWORD2 135 | getRawGyroY KEYWORD2 136 | getRawGyroZ KEYWORD2 137 | 138 | getRawMagX KEYWORD2 139 | getRawMagY KEYWORD2 140 | getRawMagZ KEYWORD2 141 | 142 | getRoll KEYWORD2 143 | getPitch KEYWORD2 144 | getYaw KEYWORD2 145 | 146 | ####################################### 147 | # Constants (LITERAL1) 148 | ####################################### 149 | -------------------------------------------------------------------------------- /library.properties: -------------------------------------------------------------------------------- 1 | name=SparkFun BNO08x Cortex Based IMU 2 | version=1.0.6 3 | author=SparkFun Electronics 4 | maintainer=SparkFun Electronics 5 | sentence=Library for the SparkFun Qwiic VR IMU - BNO080/BNO085/BNO086 6 | paragraph=An Arduino Library for the BNO08x IMU. The BNO08x IMU has a combination triple axis accelerometer/gyro/magnetometer packaged with an ARM Cortex M0+ running powerful algorithms. This enables the BNO08x Inertial Measurement Unit (IMU) to produce accurate rotation vector headings with an error of 5 degrees or less. It's what we've been waiting for: all the sensor data is combined into meaningful, accurate IMU information. Available at: https://www.sparkfun.com/products/22857 7 | category=Sensors 8 | url=https://github.com/sparkfun/SparkFun_BNO08x_Arduino_Library 9 | architectures=* 10 | -------------------------------------------------------------------------------- /src/NOTICE.txt: -------------------------------------------------------------------------------- 1 | This software is licensed from Hillcrest Laboratories, Inc. 2 | Copyright (c) Hillcrest Laboratories, Inc. and its licensors. 3 | All rights reserved. 4 | 5 | Hillcrest Laboratories and the Hillcrest logo are trademarks of 6 | Hillcrest Laboratories, Inc. 7 | 8 | You can contact Hillcrest Laboratories on the web at 9 | http://hillcrestlabs.com/company/contact-us/ or at Hillcrest Laboratories, 10 | 15245 Shady Grove Road, Suite 400, Rockville, MD 20850 USA 11 | 12 | /**********************************************************/ 13 | 14 | Some of this library was based off of the Adafruit BNO08x Arduino Library. 15 | More specifically, the code layers connecting to the HillCrest/Ceva Driver. 16 | Their original work can be found here: 17 | https://github.com/adafruit/Adafruit_BNO08x 18 | 19 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 20 | BusIO library found here: 21 | https://github.com/adafruit/Adafruit_BusIO 22 | 23 | Thank you Adafruit and your developers for all your hard work put into your Library! 24 | The following is the License text that they included on their code: 25 | 26 | Software License Agreement (BSD License) 27 | 28 | Copyright (c) 2019 Bryan Siepert for Adafruit Industries 29 | All rights reserved. 30 | 31 | Redistribution and use in source and binary forms, with or without 32 | modification, are permitted provided that the following conditions are met: 33 | 1. Redistributions of source code must retain the above copyright 34 | notice, this list of conditions and the following disclaimer. 35 | 2. Redistributions in binary form must reproduce the above copyright 36 | notice, this list of conditions and the following disclaimer in the 37 | documentation and/or other materials provided with the distribution. 38 | 3. Neither the name of the copyright holders nor the 39 | names of its contributors may be used to endorse or promote products 40 | derived from this software without specific prior written permission. 41 | 42 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY 43 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 44 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 45 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY 46 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 47 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 48 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 49 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 50 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 51 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 | 53 | /**********************************************************/ 54 | -------------------------------------------------------------------------------- /src/SparkFun_BNO08x_Arduino_Library.h: -------------------------------------------------------------------------------- 1 | /* 2 | This is a library written for the BNO08x 3 | SparkFun sells these at its website: www.sparkfun.com 4 | Do you like this library? Help support SparkFun. Buy a board! 5 | https://www.sparkfun.com/products/14686 6 | 7 | Originally written by Nathan Seidle @ SparkFun Electronics, December 28th, 2017 8 | 9 | Adjusted by Pete Lewis @ SparkFun Electronics, June 2023 to incorporate the 10 | CEVA Sensor Hub Driver, found here: 11 | https://github.com/ceva-dsp/sh2 12 | 13 | Also, utilizing code from the Adafruit BNO08x Arduino Library by Bryan Siepert 14 | for Adafruit Industries. Found here: 15 | https://github.com/adafruit/Adafruit_BNO08x 16 | 17 | Also, utilizing I2C and SPI read/write functions and code from the Adafruit 18 | BusIO library found here: 19 | https://github.com/adafruit/Adafruit_BusIO 20 | 21 | The BNO08x IMU is a powerful triple axis gyro/accel/magnetometer coupled with an ARM processor 22 | to maintain and complete all the complex calculations for various VR, inertial, step counting, 23 | and movement operations. 24 | 25 | This library handles the initialization of the BNO08x and is able to query the sensor 26 | for different readings. 27 | 28 | https://github.com/sparkfun/SparkFun_BNO08x_Arduino_Library 29 | 30 | Development environment specifics: 31 | Arduino IDE 2.1.1 32 | 33 | SparkFun code, firmware, and software is released under the MIT License. 34 | Please see LICENSE.md for further details. 35 | 36 | Some of this library was based off of the Adafruit BNO08x Arduino Library. 37 | More specifically, the code layers connecting to the HillCrest/Ceva Driver. 38 | Their original work can be found here: 39 | https://github.com/adafruit/Adafruit_BNO08x 40 | Thank you Adafruit and your developers for all your hard work put into your Library! 41 | */ 42 | 43 | #include "sh2.h" 44 | #include "sh2_SensorValue.h" 45 | #include "sh2_err.h" 46 | 47 | #pragma once 48 | 49 | #if (ARDUINO >= 100) 50 | #include "Arduino.h" 51 | #else 52 | #include "WProgram.h" 53 | #endif 54 | 55 | #include 56 | #include 57 | 58 | //The default I2C address for the BNO08x on the SparkFun breakout is 0x4B. 0x4A is also possible. 59 | #define BNO08x_DEFAULT_ADDRESS 0x4B 60 | 61 | //Platform specific configurations 62 | 63 | //Define the size of the I2C buffer based on the platform the user has 64 | //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 65 | #if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) 66 | 67 | //I2C_BUFFER_LENGTH is defined in Wire.H 68 | #define I2C_BUFFER_LENGTH 32 69 | 70 | //#else 71 | 72 | //The catch-all default is 32 73 | //#define I2C_BUFFER_LENGTH 32 74 | 75 | #endif 76 | //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 77 | 78 | 79 | //All the ways we can configure or talk to the BNO08x, figure 34, page 36 reference manual 80 | //These are used for low level communication with the sensor, on channel 2 81 | #define SHTP_REPORT_COMMAND_RESPONSE 0xF1 82 | #define SHTP_REPORT_COMMAND_REQUEST 0xF2 83 | #define SHTP_REPORT_FRS_READ_RESPONSE 0xF3 84 | #define SHTP_REPORT_FRS_READ_REQUEST 0xF4 85 | #define SHTP_REPORT_PRODUCT_ID_RESPONSE 0xF8 86 | #define SHTP_REPORT_PRODUCT_ID_REQUEST 0xF9 87 | #define SHTP_REPORT_BASE_TIMESTAMP 0xFB 88 | #define SHTP_REPORT_SET_FEATURE_COMMAND 0xFD 89 | 90 | //All the different sensors and features we can get reports from 91 | //These are used when enabling a given sensor 92 | #define SENSOR_REPORTID_ACCELEROMETER SH2_ACCELEROMETER 93 | #define SENSOR_REPORTID_GYROSCOPE_CALIBRATED SH2_GYROSCOPE_CALIBRATED 94 | #define SENSOR_REPORTID_MAGNETIC_FIELD SH2_MAGNETIC_FIELD_CALIBRATED 95 | #define SENSOR_REPORTID_LINEAR_ACCELERATION SH2_LINEAR_ACCELERATION 96 | #define SENSOR_REPORTID_ROTATION_VECTOR SH2_ROTATION_VECTOR 97 | #define SENSOR_REPORTID_GRAVITY SH2_GRAVITY 98 | #define SENSOR_REPORTID_UNCALIBRATED_GYRO SH2_GYROSCOPE_UNCALIBRATED 99 | #define SENSOR_REPORTID_GAME_ROTATION_VECTOR 0x08 100 | #define SENSOR_REPORTID_GEOMAGNETIC_ROTATION_VECTOR 0x09 101 | #define SENSOR_REPORTID_GYRO_INTEGRATED_ROTATION_VECTOR SH2_GYRO_INTEGRATED_RV 102 | #define SENSOR_REPORTID_TAP_DETECTOR 0x10 103 | #define SENSOR_REPORTID_STEP_COUNTER SH2_STEP_COUNTER 104 | #define SENSOR_REPORTID_STABILITY_CLASSIFIER SH2_STABILITY_CLASSIFIER 105 | #define SENSOR_REPORTID_RAW_ACCELEROMETER 0x14 106 | #define SENSOR_REPORTID_RAW_GYROSCOPE 0x15 107 | #define SENSOR_REPORTID_RAW_MAGNETOMETER 0x16 108 | #define SENSOR_REPORTID_PERSONAL_ACTIVITY_CLASSIFIER SH2_PERSONAL_ACTIVITY_CLASSIFIER 109 | #define SENSOR_REPORTID_AR_VR_STABILIZED_ROTATION_VECTOR 0x28 110 | #define SENSOR_REPORTID_AR_VR_STABILIZED_GAME_ROTATION_VECTOR 0x29 111 | 112 | // Reset complete packet (BNO08X Datasheet p.24 Figure 1-27) 113 | #define EXECUTABLE_RESET_COMPLETE 0x1 114 | 115 | //Command IDs from section 6.4, page 42 116 | //These are used to calibrate, initialize, set orientation, tare etc the sensor 117 | #define COMMAND_ERRORS 1 118 | #define COMMAND_COUNTER 2 119 | #define COMMAND_TARE 3 120 | #define COMMAND_INITIALIZE 4 121 | #define COMMAND_DCD 6 122 | #define COMMAND_ME_CALIBRATE 7 123 | #define COMMAND_DCD_PERIOD_SAVE 9 124 | #define COMMAND_OSCILLATOR 10 125 | #define COMMAND_CLEAR_DCD 11 126 | 127 | #define CALIBRATE_ACCEL 0 128 | #define CALIBRATE_GYRO 1 129 | #define CALIBRATE_MAG 2 130 | #define CALIBRATE_PLANAR_ACCEL 3 131 | #define CALIBRATE_ACCEL_GYRO_MAG 4 132 | #define CALIBRATE_STOP 5 133 | 134 | #define TARE_AXIS_ALL 0x07 135 | #define TARE_AXIS_Z 0x04 136 | 137 | #define TARE_ROTATION_VECTOR 0 138 | #define TARE_GAME_ROTATION_VECTOR 1 139 | #define TARE_GEOMAGNETIC_ROTATION_VECTOR 2 140 | #define TARE_GYRO_INTEGRATED_ROTATION_VECTOR 3 141 | #define TARE_AR_VR_STABILIZED_ROTATION_VECTOR 4 142 | #define TARE_AR_VR_STABILIZED_GAME_ROTATION_VECTOR 5 143 | 144 | class BNO08x 145 | { 146 | public: 147 | boolean begin(uint8_t deviceAddress = BNO08x_DEFAULT_ADDRESS, TwoWire &wirePort = Wire, int8_t user_INTPin = -1, int8_t user_RSTPin = -1); //By default use the default I2C addres, and use Wire port 148 | boolean beginSPI(uint8_t user_CSPin, uint8_t user_INTPin, uint8_t user_RSTPin, uint32_t spiPortSpeed = 1000000, SPIClass &spiPort = SPI); 149 | boolean isConnected(); 150 | 151 | sh2_ProductIds_t prodIds; ///< The product IDs returned by the sensor 152 | sh2_SensorValue_t sensorValue; 153 | 154 | void hardwareReset(void); 155 | bool wasReset(void); //Returns true if the sensor has reported a reset. Reading this will unflag the reset. 156 | 157 | uint8_t getResetReason(); // returns prodIds->resetCause 158 | 159 | bool enableReport(sh2_SensorId_t sensor, uint32_t interval_us = 10000, uint32_t sensorSpecific = 0); 160 | bool getSensorEvent(); 161 | uint8_t getSensorEventID(); 162 | 163 | void enableDebugging(Stream &debugPort = Serial); //Turn on debug printing. If user doesn't specify then Serial will be used. 164 | 165 | bool softReset(); //Try to reset the IMU via software 166 | bool serviceBus(void); 167 | uint8_t resetReason(); //Query the IMU for the reason it last reset 168 | bool modeOn(); //Use the executable channel to turn the BNO on 169 | bool modeSleep(); //Use the executable channel to put the BNO to sleep 170 | 171 | float qToFloat(int16_t fixedPointValue, uint8_t qPoint); //Given a Q value, converts fixed point floating to regular floating point number 172 | 173 | bool enableRotationVector(uint16_t timeBetweenReports = 10); 174 | bool enableGeomagneticRotationVector(uint16_t timeBetweenReports = 10); 175 | bool enableGameRotationVector(uint16_t timeBetweenReports = 10); 176 | bool enableARVRStabilizedRotationVector(uint16_t timeBetweenReports); 177 | bool enableARVRStabilizedGameRotationVector(uint16_t timeBetweenReports); 178 | bool enableAccelerometer(uint16_t timeBetweenReports = 10); 179 | bool enableLinearAccelerometer(uint16_t timeBetweenReports = 10); 180 | bool enableGravity(uint16_t timeBetweenReports = 10); 181 | bool enableGyro(uint16_t timeBetweenReports = 10); 182 | bool enableUncalibratedGyro(uint16_t timeBetweenReports = 10); 183 | bool enableMagnetometer(uint16_t timeBetweenReports = 10); 184 | bool enableTapDetector(uint16_t timeBetweenReports); 185 | bool enableStepCounter(uint16_t timeBetweenReports = 10); 186 | bool enableStabilityClassifier(uint16_t timeBetweenReports = 10); 187 | bool enableActivityClassifier(uint16_t timeBetweenReports, uint32_t activitiesToEnable); 188 | bool enableRawAccelerometer(uint16_t timeBetweenReports = 10); 189 | bool enableRawGyro(uint16_t timeBetweenReports = 10); 190 | bool enableRawMagnetometer(uint16_t timeBetweenReports = 10); 191 | bool enableGyroIntegratedRotationVector(uint16_t timeBetweenReports = 10); 192 | 193 | void getQuat(float &i, float &j, float &k, float &real, float &radAccuracy, uint8_t &accuracy); 194 | float getQuatI(); 195 | float getQuatJ(); 196 | float getQuatK(); 197 | float getQuatReal(); 198 | float getQuatRadianAccuracy(); 199 | uint8_t getQuatAccuracy(); 200 | 201 | float getGameQuatI(); 202 | float getGameQuatJ(); 203 | float getGameQuatK(); 204 | float getGameQuatReal(); 205 | 206 | void getAccel(float &x, float &y, float &z, uint8_t &accuracy); 207 | float getAccelX(); 208 | float getAccelY(); 209 | float getAccelZ(); 210 | uint8_t getAccelAccuracy(); 211 | 212 | void getLinAccel(float &x, float &y, float &z, uint8_t &accuracy); 213 | float getLinAccelX(); 214 | float getLinAccelY(); 215 | float getLinAccelZ(); 216 | uint8_t getLinAccelAccuracy(); 217 | 218 | void getGyro(float &x, float &y, float &z, uint8_t &accuracy); 219 | float getGyroX(); 220 | float getGyroY(); 221 | float getGyroZ(); 222 | uint8_t getGyroAccuracy(); 223 | 224 | void getUncalibratedGyro(float &x, float &y, float &z, float &bx, float &by, float &bz, uint8_t &accuracy); 225 | float getUncalibratedGyroX(); 226 | float getUncalibratedGyroY(); 227 | float getUncalibratedGyroZ(); 228 | float getUncalibratedGyroBiasX(); 229 | float getUncalibratedGyroBiasY(); 230 | float getUncalibratedGyroBiasZ(); 231 | uint8_t getUncalibratedGyroAccuracy(); 232 | 233 | float getGyroIntegratedRVI(); 234 | float getGyroIntegratedRVJ(); 235 | float getGyroIntegratedRVK(); 236 | float getGyroIntegratedRVReal(); 237 | float getGyroIntegratedRVangVelX(); 238 | float getGyroIntegratedRVangVelY(); 239 | float getGyroIntegratedRVangVelZ(); 240 | 241 | void getMag(float &x, float &y, float &z, uint8_t &accuracy); 242 | float getMagX(); 243 | float getMagY(); 244 | float getMagZ(); 245 | uint8_t getMagAccuracy(); 246 | 247 | void getGravity(float &x, float &y, float &z, uint8_t &accuracy); 248 | float getGravityX(); 249 | float getGravityY(); 250 | float getGravityZ(); 251 | uint8_t getGravityAccuracy(); 252 | 253 | bool setCalibrationConfig(uint8_t sensors); 254 | bool saveCalibration(); 255 | 256 | bool tareNow(bool zAxis=false, sh2_TareBasis_t basis=SH2_TARE_BASIS_ROTATION_VECTOR); 257 | bool saveTare(); 258 | bool clearTare(); 259 | 260 | uint8_t getTapDetector(); 261 | uint64_t getTimeStamp(); 262 | uint16_t getStepCount(); 263 | uint8_t getStabilityClassifier(); 264 | uint8_t getActivityClassifier(); 265 | uint8_t getActivityConfidence(uint8_t activity); 266 | 267 | int16_t getRawAccelX(); 268 | int16_t getRawAccelY(); 269 | int16_t getRawAccelZ(); 270 | 271 | int16_t getRawGyroX(); 272 | int16_t getRawGyroY(); 273 | int16_t getRawGyroZ(); 274 | 275 | int16_t getRawMagX(); 276 | int16_t getRawMagY(); 277 | int16_t getRawMagZ(); 278 | 279 | float getRoll(); 280 | float getPitch(); 281 | float getYaw(); 282 | 283 | // void sendCommand(uint8_t command); 284 | // void sendCalibrateCommand(uint8_t thingToCalibrate); 285 | 286 | //Metadata functions 287 | // int16_t getQ1(uint16_t recordID); 288 | // int16_t getQ2(uint16_t recordID); 289 | // int16_t getQ3(uint16_t recordID); 290 | // float getResolution(uint16_t recordID); 291 | // float getRange(uint16_t recordID); 292 | // uint32_t readFRSword(uint16_t recordID, uint8_t wordNumber); 293 | // void frsReadRequest(uint16_t recordID, uint16_t readOffset, uint16_t blockSize); 294 | // bool readFRSdata(uint16_t recordID, uint8_t startLocation, uint8_t wordsToRead); 295 | 296 | //Global Variables 297 | // uint8_t shtpHeader[4]; //Each packet has a header of 4 bytes 298 | // uint8_t shtpData[MAX_PACKET_SIZE]; 299 | // uint8_t sequenceNumber[6] = {0, 0, 0, 0, 0, 0}; //There are 6 com channels. Each channel has its own seqnum 300 | // uint8_t commandSequenceNumber = 0; //Commands have a seqNum as well. These are inside command packet, the header uses its own seqNum per channel 301 | // uint32_t metaData[MAX_METADATA_SIZE]; //There is more than 10 words in a metadata record but we'll stop at Q point 3 302 | 303 | // unsigned long _spiPortSpeed; //Optional user defined port speed 304 | // uint8_t _cs; //Pins needed for SPI 305 | 306 | private: 307 | 308 | Stream *_debugPort; //The stream to send debug messages to if enabled. Usually Serial. 309 | boolean _printDebug = false; //Flag to print debugging variables 310 | 311 | //These are the raw sensor values (without Q applied) pulled from the user requested Input Report 312 | uint16_t rawAccelX, rawAccelY, rawAccelZ, accelAccuracy; 313 | uint16_t rawLinAccelX, rawLinAccelY, rawLinAccelZ, accelLinAccuracy; 314 | uint16_t rawGyroX, rawGyroY, rawGyroZ, gyroAccuracy; 315 | uint16_t rawUncalibGyroX, rawUncalibGyroY, rawUncalibGyroZ, rawBiasX, rawBiasY, rawBiasZ, UncalibGyroAccuracy; 316 | uint16_t rawMagX, rawMagY, rawMagZ, magAccuracy; 317 | uint16_t rawQuatI, rawQuatJ, rawQuatK, rawQuatReal, rawQuatRadianAccuracy, quatAccuracy; 318 | uint16_t rawFastGyroX, rawFastGyroY, rawFastGyroZ; 319 | uint16_t gravityX, gravityY, gravityZ, gravityAccuracy; 320 | uint8_t tapDetector; 321 | uint16_t stepCount; 322 | uint32_t timeStamp; 323 | uint8_t stabilityClassifier; 324 | uint8_t activityClassifier; 325 | uint8_t calibrationStatus; //Byte R0 of ME Calibration Response 326 | uint16_t memsRawAccelX, memsRawAccelY, memsRawAccelZ; //Raw readings from MEMS sensor 327 | uint16_t memsRawGyroX, memsRawGyroY, memsRawGyroZ; //Raw readings from MEMS sensor 328 | uint16_t memsRawMagX, memsRawMagY, memsRawMagZ; //Raw readings from MEMS sensor 329 | 330 | //These Q values are defined in the datasheet but can also be obtained by querying the meta data records 331 | //See the read metadata example for more info 332 | int16_t rotationVector_Q1 = 14; 333 | int16_t rotationVectorAccuracy_Q1 = 12; //Heading accuracy estimate in radians. The Q point is 12. 334 | int16_t accelerometer_Q1 = 8; 335 | int16_t linear_accelerometer_Q1 = 8; 336 | int16_t gyro_Q1 = 9; 337 | int16_t magnetometer_Q1 = 4; 338 | int16_t angular_velocity_Q1 = 10; 339 | int16_t gravity_Q1 = 8; 340 | 341 | protected: 342 | virtual bool _init(int32_t sensor_id = 0); 343 | sh2_Hal_t _HAL; ///< The struct representing the SH2 Hardware Abstraction Layer 344 | }; -------------------------------------------------------------------------------- /src/sh2_SensorValue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-16 Hillcrest Laboratories, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License and 6 | * any applicable agreements you may have with Hillcrest Laboratories, Inc. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* 19 | * BNO08x Sensor Event decoding 20 | */ 21 | 22 | #include "sh2_SensorValue.h" 23 | #include "sh2_err.h" 24 | #include "sh2_util.h" 25 | 26 | #define SCALE_Q(n) (1.0f / (1 << n)) 27 | 28 | const float scaleRadToDeg = 180.0 / 3.14159265358; 29 | 30 | // ------------------------------------------------------------------------ 31 | // Forward declarations 32 | 33 | static int decodeRawAccelerometer(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 34 | static int decodeAccelerometer(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 35 | static int decodeLinearAcceleration(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 36 | static int decodeGravity(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 37 | static int decodeRawGyroscope(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 38 | static int decodeGyroscopeCalibrated(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 39 | static int decodeGyroscopeUncal(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 40 | static int decodeRawMagnetometer(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 41 | static int decodeMagneticFieldCalibrated(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 42 | static int decodeMagneticFieldUncal(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 43 | static int decodeRotationVector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 44 | static int decodeGameRotationVector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 45 | static int decodeGeomagneticRotationVector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 46 | static int decodePressure(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 47 | static int decodeAmbientLight(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 48 | static int decodeHumidity(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 49 | static int decodeProximity(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 50 | static int decodeTemperature(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 51 | static int decodeReserved(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 52 | static int decodeTapDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 53 | static int decodeStepDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 54 | static int decodeStepCounter(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 55 | static int decodeSignificantMotion(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 56 | static int decodeStabilityClassifier(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 57 | static int decodeShakeDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 58 | static int decodeFlipDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 59 | static int decodePickupDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 60 | static int decodeStabilityDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 61 | static int decodePersonalActivityClassifier(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 62 | static int decodeSleepDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 63 | static int decodeTiltDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 64 | static int decodePocketDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 65 | static int decodeCircleDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 66 | static int decodeHeartRateMonitor(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 67 | static int decodeArvrStabilizedRV(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 68 | static int decodeArvrStabilizedGRV(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 69 | static int decodeGyroIntegratedRV(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 70 | static int decodeIZroRequest(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 71 | 72 | // ------------------------------------------------------------------------ 73 | // Public API 74 | 75 | int sh2_decodeSensorEvent(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 76 | { 77 | // Fill out fields of *value based on *event, converting data from message representation 78 | // to natural representation. 79 | 80 | int rc = SH2_OK; 81 | 82 | value->sensorId = event->reportId; 83 | value->timestamp = event->timestamp_uS; 84 | 85 | if (value->sensorId != SH2_GYRO_INTEGRATED_RV) { 86 | value->sequence = event->report[1]; 87 | value->status = event->report[2] & 0x03; 88 | } 89 | else { 90 | value->sequence = 0; 91 | value->status = 0; 92 | } 93 | 94 | // extract delay field (100uS units) 95 | 96 | 97 | switch (value->sensorId) { 98 | case SH2_RAW_ACCELEROMETER: 99 | rc = decodeRawAccelerometer(value, event); 100 | break; 101 | case SH2_ACCELEROMETER: 102 | rc = decodeAccelerometer(value, event); 103 | break; 104 | case SH2_LINEAR_ACCELERATION: 105 | rc = decodeLinearAcceleration(value, event); 106 | break; 107 | case SH2_GRAVITY: 108 | rc = decodeGravity(value, event); 109 | break; 110 | case SH2_RAW_GYROSCOPE: 111 | rc = decodeRawGyroscope(value, event); 112 | break; 113 | case SH2_GYROSCOPE_CALIBRATED: 114 | rc = decodeGyroscopeCalibrated(value, event); 115 | break; 116 | case SH2_GYROSCOPE_UNCALIBRATED: 117 | rc = decodeGyroscopeUncal(value, event); 118 | break; 119 | case SH2_RAW_MAGNETOMETER: 120 | rc = decodeRawMagnetometer(value, event); 121 | break; 122 | case SH2_MAGNETIC_FIELD_CALIBRATED: 123 | rc = decodeMagneticFieldCalibrated(value, event); 124 | break; 125 | case SH2_MAGNETIC_FIELD_UNCALIBRATED: 126 | rc = decodeMagneticFieldUncal(value, event); 127 | break; 128 | case SH2_ROTATION_VECTOR: 129 | rc = decodeRotationVector(value, event); 130 | break; 131 | case SH2_GAME_ROTATION_VECTOR: 132 | rc = decodeGameRotationVector(value, event); 133 | break; 134 | case SH2_GEOMAGNETIC_ROTATION_VECTOR: 135 | rc = decodeGeomagneticRotationVector(value, event); 136 | break; 137 | case SH2_PRESSURE: 138 | rc = decodePressure(value, event); 139 | break; 140 | case SH2_AMBIENT_LIGHT: 141 | rc = decodeAmbientLight(value, event); 142 | break; 143 | case SH2_HUMIDITY: 144 | rc = decodeHumidity(value, event); 145 | break; 146 | case SH2_PROXIMITY: 147 | rc = decodeProximity(value, event); 148 | break; 149 | case SH2_TEMPERATURE: 150 | rc = decodeTemperature(value, event); 151 | break; 152 | case SH2_RESERVED: 153 | rc = decodeReserved(value, event); 154 | break; 155 | case SH2_TAP_DETECTOR: 156 | rc = decodeTapDetector(value, event); 157 | break; 158 | case SH2_STEP_DETECTOR: 159 | rc = decodeStepDetector(value, event); 160 | break; 161 | case SH2_STEP_COUNTER: 162 | rc = decodeStepCounter(value, event); 163 | break; 164 | case SH2_SIGNIFICANT_MOTION: 165 | rc = decodeSignificantMotion(value, event); 166 | break; 167 | case SH2_STABILITY_CLASSIFIER: 168 | rc = decodeStabilityClassifier(value, event); 169 | break; 170 | case SH2_SHAKE_DETECTOR: 171 | rc = decodeShakeDetector(value, event); 172 | break; 173 | case SH2_FLIP_DETECTOR: 174 | rc = decodeFlipDetector(value, event); 175 | break; 176 | case SH2_PICKUP_DETECTOR: 177 | rc = decodePickupDetector(value, event); 178 | break; 179 | case SH2_STABILITY_DETECTOR: 180 | rc = decodeStabilityDetector(value, event); 181 | break; 182 | case SH2_PERSONAL_ACTIVITY_CLASSIFIER: 183 | rc = decodePersonalActivityClassifier(value, event); 184 | break; 185 | case SH2_SLEEP_DETECTOR: 186 | rc = decodeSleepDetector(value, event); 187 | break; 188 | case SH2_TILT_DETECTOR: 189 | rc = decodeTiltDetector(value, event); 190 | break; 191 | case SH2_POCKET_DETECTOR: 192 | rc = decodePocketDetector(value, event); 193 | break; 194 | case SH2_CIRCLE_DETECTOR: 195 | rc = decodeCircleDetector(value, event); 196 | break; 197 | case SH2_HEART_RATE_MONITOR: 198 | rc = decodeHeartRateMonitor(value, event); 199 | break; 200 | case SH2_ARVR_STABILIZED_RV: 201 | rc = decodeArvrStabilizedRV(value, event); 202 | break; 203 | case SH2_ARVR_STABILIZED_GRV: 204 | rc = decodeArvrStabilizedGRV(value, event); 205 | break; 206 | case SH2_GYRO_INTEGRATED_RV: 207 | rc = decodeGyroIntegratedRV(value, event); 208 | break; 209 | case SH2_IZRO_MOTION_REQUEST: 210 | rc = decodeIZroRequest(value, event); 211 | break; 212 | default: 213 | // Unknown report id 214 | rc = SH2_ERR; 215 | break; 216 | } 217 | 218 | return rc; 219 | } 220 | 221 | // ------------------------------------------------------------------------ 222 | // Private utility functions 223 | 224 | static int decodeRawAccelerometer(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 225 | { 226 | value->un.rawAccelerometer.x = read16(&event->report[4]); 227 | value->un.rawAccelerometer.y = read16(&event->report[6]); 228 | value->un.rawAccelerometer.z = read16(&event->report[8]); 229 | value->un.rawAccelerometer.timestamp = read32(&event->report[12]); 230 | 231 | return SH2_OK; 232 | } 233 | 234 | static int decodeAccelerometer(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 235 | { 236 | value->un.accelerometer.x = read16(&event->report[4]) * SCALE_Q(8); 237 | value->un.accelerometer.y = read16(&event->report[6]) * SCALE_Q(8); 238 | value->un.accelerometer.z = read16(&event->report[8]) * SCALE_Q(8); 239 | 240 | return SH2_OK; 241 | } 242 | 243 | static int decodeLinearAcceleration(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 244 | { 245 | value->un.linearAcceleration.x = read16(&event->report[4]) * SCALE_Q(8); 246 | value->un.linearAcceleration.y = read16(&event->report[6]) * SCALE_Q(8); 247 | value->un.linearAcceleration.z = read16(&event->report[8]) * SCALE_Q(8); 248 | 249 | return SH2_OK; 250 | } 251 | 252 | static int decodeGravity(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 253 | { 254 | value->un.gravity.x = read16(&event->report[4]) * SCALE_Q(8); 255 | value->un.gravity.y = read16(&event->report[6]) * SCALE_Q(8); 256 | value->un.gravity.z = read16(&event->report[8]) * SCALE_Q(8); 257 | 258 | return SH2_OK; 259 | } 260 | 261 | static int decodeRawGyroscope(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 262 | { 263 | value->un.rawGyroscope.x = read16(&event->report[4]); 264 | value->un.rawGyroscope.y = read16(&event->report[6]); 265 | value->un.rawGyroscope.z = read16(&event->report[8]); 266 | value->un.rawGyroscope.temperature = read16(&event->report[10]); 267 | value->un.rawGyroscope.timestamp = read32(&event->report[12]); 268 | 269 | return SH2_OK; 270 | } 271 | 272 | static int decodeGyroscopeCalibrated(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 273 | { 274 | value->un.gyroscope.x = read16(&event->report[4]) * SCALE_Q(9); 275 | value->un.gyroscope.y = read16(&event->report[6]) * SCALE_Q(9); 276 | value->un.gyroscope.z = read16(&event->report[8]) * SCALE_Q(9); 277 | 278 | return SH2_OK; 279 | } 280 | 281 | static int decodeGyroscopeUncal(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 282 | { 283 | value->un.gyroscopeUncal.x = read16(&event->report[4]) * SCALE_Q(9); 284 | value->un.gyroscopeUncal.y = read16(&event->report[6]) * SCALE_Q(9); 285 | value->un.gyroscopeUncal.z = read16(&event->report[8]) * SCALE_Q(9); 286 | 287 | value->un.gyroscopeUncal.biasX = read16(&event->report[10]) * SCALE_Q(9); 288 | value->un.gyroscopeUncal.biasY = read16(&event->report[12]) * SCALE_Q(9); 289 | value->un.gyroscopeUncal.biasZ = read16(&event->report[14]) * SCALE_Q(9); 290 | 291 | return SH2_OK; 292 | } 293 | 294 | static int decodeRawMagnetometer(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 295 | { 296 | value->un.rawMagnetometer.x = read16(&event->report[4]); 297 | value->un.rawMagnetometer.y = read16(&event->report[6]); 298 | value->un.rawMagnetometer.z = read16(&event->report[8]); 299 | value->un.rawMagnetometer.timestamp = read32(&event->report[12]); 300 | 301 | return SH2_OK; 302 | } 303 | 304 | static int decodeMagneticFieldCalibrated(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 305 | { 306 | value->un.magneticField.x = read16(&event->report[4]) * SCALE_Q(4); 307 | value->un.magneticField.y = read16(&event->report[6]) * SCALE_Q(4); 308 | value->un.magneticField.z = read16(&event->report[8]) * SCALE_Q(4); 309 | 310 | return SH2_OK; 311 | } 312 | 313 | static int decodeMagneticFieldUncal(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 314 | { 315 | value->un.magneticFieldUncal.x = read16(&event->report[4]) * SCALE_Q(4); 316 | value->un.magneticFieldUncal.y = read16(&event->report[6]) * SCALE_Q(4); 317 | value->un.magneticFieldUncal.z = read16(&event->report[8]) * SCALE_Q(4); 318 | 319 | value->un.magneticFieldUncal.biasX = read16(&event->report[10]) * SCALE_Q(4); 320 | value->un.magneticFieldUncal.biasY = read16(&event->report[12]) * SCALE_Q(4); 321 | value->un.magneticFieldUncal.biasZ = read16(&event->report[14]) * SCALE_Q(4); 322 | 323 | return SH2_OK; 324 | } 325 | 326 | static int decodeRotationVector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 327 | { 328 | value->un.rotationVector.i = read16(&event->report[4]) * SCALE_Q(14); 329 | value->un.rotationVector.j = read16(&event->report[6]) * SCALE_Q(14); 330 | value->un.rotationVector.k = read16(&event->report[8]) * SCALE_Q(14); 331 | value->un.rotationVector.real = read16(&event->report[10]) * SCALE_Q(14); 332 | value->un.rotationVector.accuracy = read16(&event->report[12]) * SCALE_Q(12); 333 | 334 | return SH2_OK; 335 | } 336 | 337 | static int decodeGameRotationVector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 338 | { 339 | value->un.gameRotationVector.i = read16(&event->report[4]) * SCALE_Q(14); 340 | value->un.gameRotationVector.j = read16(&event->report[6]) * SCALE_Q(14); 341 | value->un.gameRotationVector.k = read16(&event->report[8]) * SCALE_Q(14); 342 | value->un.gameRotationVector.real = read16(&event->report[10]) * SCALE_Q(14); 343 | 344 | return SH2_OK; 345 | } 346 | 347 | static int decodeGeomagneticRotationVector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 348 | { 349 | value->un.geoMagRotationVector.i = read16(&event->report[4]) * SCALE_Q(14); 350 | value->un.geoMagRotationVector.j = read16(&event->report[6]) * SCALE_Q(14); 351 | value->un.geoMagRotationVector.k = read16(&event->report[8]) * SCALE_Q(14); 352 | value->un.geoMagRotationVector.real = read16(&event->report[10]) * SCALE_Q(14); 353 | value->un.geoMagRotationVector.accuracy = read16(&event->report[12]) * SCALE_Q(12); 354 | 355 | return SH2_OK; 356 | } 357 | 358 | static int decodePressure(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 359 | { 360 | value->un.pressure.value = read32(&event->report[4]) * SCALE_Q(20); 361 | 362 | return SH2_OK; 363 | } 364 | 365 | static int decodeAmbientLight(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 366 | { 367 | value->un.ambientLight.value = read32(&event->report[4]) * SCALE_Q(8); 368 | 369 | return SH2_OK; 370 | } 371 | 372 | static int decodeHumidity(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 373 | { 374 | value->un.humidity.value = read16(&event->report[4]) * SCALE_Q(8); 375 | 376 | return SH2_OK; 377 | } 378 | 379 | static int decodeProximity(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 380 | { 381 | value->un.proximity.value = read16(&event->report[4]) * SCALE_Q(4); 382 | 383 | return SH2_OK; 384 | } 385 | 386 | static int decodeTemperature(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 387 | { 388 | value->un.temperature.value = read16(&event->report[4]) * SCALE_Q(7); 389 | 390 | return SH2_OK; 391 | } 392 | 393 | static int decodeReserved(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 394 | { 395 | value->un.reserved.tbd = read16(&event->report[4]) * SCALE_Q(7); 396 | 397 | return SH2_OK; 398 | } 399 | 400 | static int decodeTapDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 401 | { 402 | value->un.tapDetector.flags = event->report[4]; 403 | 404 | return SH2_OK; 405 | } 406 | 407 | static int decodeStepDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 408 | { 409 | value->un.stepDetector.latency = readu32(&event->report[4]); 410 | 411 | return SH2_OK; 412 | } 413 | 414 | static int decodeStepCounter(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 415 | { 416 | value->un.stepCounter.latency = readu32(&event->report[4]); 417 | value->un.stepCounter.steps = readu32(&event->report[8]); 418 | 419 | return SH2_OK; 420 | } 421 | 422 | static int decodeSignificantMotion(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 423 | { 424 | value->un.sigMotion.motion = readu16(&event->report[4]); 425 | 426 | return SH2_OK; 427 | } 428 | 429 | static int decodeStabilityClassifier(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 430 | { 431 | value->un.stabilityClassifier.classification = event->report[4]; 432 | 433 | return SH2_OK; 434 | } 435 | 436 | static int decodeShakeDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 437 | { 438 | value->un.shakeDetector.shake = readu16(&event->report[4]); 439 | 440 | return SH2_OK; 441 | } 442 | 443 | static int decodeFlipDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 444 | { 445 | value->un.flipDetector.flip = readu16(&event->report[4]); 446 | 447 | return SH2_OK; 448 | } 449 | 450 | static int decodePickupDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 451 | { 452 | value->un.pickupDetector.pickup = readu16(&event->report[4]); 453 | 454 | return SH2_OK; 455 | } 456 | 457 | static int decodeStabilityDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 458 | { 459 | value->un.stabilityDetector.stability = readu16(&event->report[4]); 460 | 461 | return SH2_OK; 462 | } 463 | 464 | static int decodePersonalActivityClassifier(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 465 | { 466 | value->un.personalActivityClassifier.page = event->report[4] & 0x7F; 467 | value->un.personalActivityClassifier.lastPage = ((event->report[4] & 0x80) != 0); 468 | value->un.personalActivityClassifier.mostLikelyState = event->report[5]; 469 | for (int n = 0; n < 10; n++) { 470 | value->un.personalActivityClassifier.confidence[n] = event->report[6+n]; 471 | } 472 | 473 | return SH2_OK; 474 | } 475 | 476 | static int decodeSleepDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 477 | { 478 | value->un.sleepDetector.sleepState = event->report[4]; 479 | 480 | return SH2_OK; 481 | } 482 | 483 | static int decodeTiltDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 484 | { 485 | value->un.tiltDetector.tilt = readu16(&event->report[4]); 486 | 487 | return SH2_OK; 488 | } 489 | 490 | static int decodePocketDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 491 | { 492 | value->un.pocketDetector.pocket = readu16(&event->report[4]); 493 | 494 | return SH2_OK; 495 | } 496 | 497 | static int decodeCircleDetector(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 498 | { 499 | value->un.circleDetector.circle = readu16(&event->report[4]); 500 | 501 | return SH2_OK; 502 | } 503 | 504 | static int decodeHeartRateMonitor(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 505 | { 506 | value->un.heartRateMonitor.heartRate = readu16(&event->report[4]); 507 | 508 | return SH2_OK; 509 | } 510 | 511 | static int decodeArvrStabilizedRV(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 512 | { 513 | value->un.arvrStabilizedRV.i = read16(&event->report[4]) * SCALE_Q(14); 514 | value->un.arvrStabilizedRV.j = read16(&event->report[6]) * SCALE_Q(14); 515 | value->un.arvrStabilizedRV.k = read16(&event->report[8]) * SCALE_Q(14); 516 | value->un.arvrStabilizedRV.real = read16(&event->report[10]) * SCALE_Q(14); 517 | value->un.arvrStabilizedRV.accuracy = read16(&event->report[12]) * SCALE_Q(12); 518 | 519 | return SH2_OK; 520 | } 521 | 522 | static int decodeArvrStabilizedGRV(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 523 | { 524 | value->un.arvrStabilizedGRV.i = read16(&event->report[4]) * SCALE_Q(14); 525 | value->un.arvrStabilizedGRV.j = read16(&event->report[6]) * SCALE_Q(14); 526 | value->un.arvrStabilizedGRV.k = read16(&event->report[8]) * SCALE_Q(14); 527 | value->un.arvrStabilizedGRV.real = read16(&event->report[10]) * SCALE_Q(14); 528 | 529 | return SH2_OK; 530 | } 531 | 532 | static int decodeGyroIntegratedRV(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 533 | { 534 | value->un.gyroIntegratedRV.i = read16(&event->report[0]) * SCALE_Q(14); 535 | value->un.gyroIntegratedRV.j = read16(&event->report[2]) * SCALE_Q(14); 536 | value->un.gyroIntegratedRV.k = read16(&event->report[4]) * SCALE_Q(14); 537 | value->un.gyroIntegratedRV.real = read16(&event->report[6]) * SCALE_Q(14); 538 | value->un.gyroIntegratedRV.angVelX = read16(&event->report[8]) * SCALE_Q(10); 539 | value->un.gyroIntegratedRV.angVelY = read16(&event->report[10]) * SCALE_Q(10); 540 | value->un.gyroIntegratedRV.angVelZ = read16(&event->report[12]) * SCALE_Q(10); 541 | 542 | return SH2_OK; 543 | } 544 | 545 | static int decodeIZroRequest(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event) 546 | { 547 | value->un.izroRequest.intent = (sh2_IZroMotionIntent_t)event->report[4]; 548 | value->un.izroRequest.request = (sh2_IZroMotionRequest_t)event->report[5]; 549 | 550 | return SH2_OK; 551 | } 552 | -------------------------------------------------------------------------------- /src/sh2_SensorValue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-16 Hillcrest Laboratories, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License and 6 | * any applicable agreements you may have with Hillcrest Laboratories, Inc. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /** 19 | * @file sh2_SensorValue.h 20 | * @author David Wheeler 21 | * @date 10 Nov 2015 22 | * @brief Support for converting sensor events (messages) into natural data structures. 23 | * 24 | */ 25 | 26 | #ifndef SH2_SENSORVALUE_H 27 | #define SH2_SENSORVALUE_H 28 | 29 | #ifdef __cplusplus 30 | extern "C" { 31 | #endif 32 | 33 | #include 34 | 35 | #include "sh2.h" 36 | 37 | /* Note on quaternion naming conventions: 38 | * Quaternions are values with four real components that are usually 39 | * interpreted as coefficients in the complex quantity, Q. 40 | * 41 | * As in, Q = W + Xi + Yj + Zk 42 | * 43 | * Where i, j and k represent the three imaginary dimensions. 44 | * 45 | * So W represents the Real components and X, Y and Z the Imaginary ones. 46 | * 47 | * In the Hillcrest datasheets and in this code, however, the four components 48 | * are named real, i, j and k, to make it explicit which is which. If you 49 | * need to translate these names into the "wxyz" or "xyzw" convention, then, the 50 | * appropriate mapping is this: 51 | * w = real 52 | * x = i 53 | * y = j 54 | * z = k 55 | */ 56 | 57 | /** 58 | * @brief Raw Accelerometer 59 | * 60 | * See the SH-2 Reference Manual for more detail. 61 | */ 62 | typedef struct sh2_RawAccelerometer { 63 | /* Units are ADC counts */ 64 | int16_t x; /**< @brief [ADC counts] */ 65 | int16_t y; /**< @brief [ADC counts] */ 66 | int16_t z; /**< @brief [ADC counts] */ 67 | 68 | /* Microseconds */ 69 | uint32_t timestamp; /**< @brief [uS] */ 70 | } sh2_RawAccelerometer_t; 71 | 72 | /** 73 | * @brief Accelerometer 74 | * 75 | * See the SH-2 Reference Manual for more detail. 76 | */ 77 | typedef struct sh2_Accelerometer { 78 | float x; 79 | float y; 80 | float z; 81 | } sh2_Accelerometer_t; 82 | 83 | /** 84 | * @brief Raw gyroscope 85 | * 86 | * See the SH-2 Reference Manual for more detail. 87 | */ 88 | typedef struct sh2_RawGyroscope { 89 | /* Units are ADC counts */ 90 | int16_t x; /**< @brief [ADC Counts] */ 91 | int16_t y; /**< @brief [ADC Counts] */ 92 | int16_t z; /**< @brief [ADC Counts] */ 93 | int16_t temperature; /**< @brief [ADC Counts] */ 94 | 95 | /* Microseconds */ 96 | uint32_t timestamp; /**< @brief [uS] */ 97 | } sh2_RawGyroscope_t; 98 | 99 | /** 100 | * @brief Gyroscope 101 | * 102 | * See the SH-2 Reference Manual for more detail. 103 | */ 104 | typedef struct sh2_Gyroscope { 105 | /* Units are rad/s */ 106 | float x; 107 | float y; 108 | float z; 109 | } sh2_Gyroscope_t; 110 | 111 | /** 112 | * @brief Uncalibrated gyroscope 113 | * 114 | * See the SH-2 Reference Manual for more detail. 115 | */ 116 | typedef struct sh2_GyroscopeUncalibrated { 117 | /* Units are rad/s */ 118 | float x; /**< @brief [rad/s] */ 119 | float y; /**< @brief [rad/s] */ 120 | float z; /**< @brief [rad/s] */ 121 | float biasX; /**< @brief [rad/s] */ 122 | float biasY; /**< @brief [rad/s] */ 123 | float biasZ; /**< @brief [rad/s] */ 124 | } sh2_GyroscopeUncalibrated_t; 125 | 126 | /** 127 | * @brief Raw Magnetometer 128 | * 129 | * See the SH-2 Reference Manual for more detail. 130 | */ 131 | typedef struct sh2_RawMagnetometer { 132 | /* Units are ADC counts */ 133 | int16_t x; /**< @brief [ADC Counts] */ 134 | int16_t y; /**< @brief [ADC Counts] */ 135 | int16_t z; /**< @brief [ADC Counts] */ 136 | 137 | /* Microseconds */ 138 | uint32_t timestamp; /**< @brief [uS] */ 139 | } sh2_RawMagnetometer_t; 140 | 141 | /** 142 | * @brief Magnetic field 143 | * 144 | * See the SH-2 Reference Manual for more detail. 145 | */ 146 | typedef struct sh2_MagneticField { 147 | /* Units are uTesla */ 148 | float x; /**< @brief [uTesla] */ 149 | float y; /**< @brief [uTesla] */ 150 | float z; /**< @brief [uTesla] */ 151 | } sh2_MagneticField_t; 152 | 153 | /** 154 | * @brief Uncalibrated magnetic field 155 | * 156 | * See the SH-2 Reference Manual for more detail. 157 | */ 158 | typedef struct sh2_MagneticFieldUncalibrated { 159 | /* Units are uTesla */ 160 | float x; /**< @brief [uTesla] */ 161 | float y; /**< @brief [uTesla] */ 162 | float z; /**< @brief [uTesla] */ 163 | float biasX; /**< @brief [uTesla] */ 164 | float biasY; /**< @brief [uTesla] */ 165 | float biasZ; /**< @brief [uTesla] */ 166 | } sh2_MagneticFieldUncalibrated_t; 167 | 168 | /** 169 | * @brief Rotation Vector with Accuracy 170 | * 171 | * See the SH-2 Reference Manual for more detail. 172 | */ 173 | typedef struct sh2_RotationVectorWAcc { 174 | float i; /**< @brief Quaternion component i */ 175 | float j; /**< @brief Quaternion component j */ 176 | float k; /**< @brief Quaternion component k */ 177 | float real; /**< @brief Quaternion component, real */ 178 | float accuracy; /**< @brief Accuracy estimate [radians] */ 179 | } sh2_RotationVectorWAcc_t; 180 | 181 | /** 182 | * @brief Rotation Vector 183 | * 184 | * See the SH-2 Reference Manual for more detail. 185 | */ 186 | typedef struct sh2_RotationVector { 187 | float i; /**< @brief Quaternion component i */ 188 | float j; /**< @brief Quaternion component j */ 189 | float k; /**< @brief Quaternion component k */ 190 | float real; /**< @brief Quaternion component real */ 191 | } sh2_RotationVector_t; 192 | 193 | /** 194 | * @brief Atmospheric Pressure 195 | * 196 | * See the SH-2 Reference Manual for more detail. 197 | */ 198 | typedef struct sh2_Pressure { 199 | float value; /**< @brief Atmospheric Pressure. [hectopascals] */ 200 | } sh2_Pressure_t; 201 | 202 | /** 203 | * @brief Ambient Light 204 | * 205 | * See the SH-2 Reference Manual for more detail. 206 | */ 207 | typedef struct sh2_AmbientLight { 208 | float value; /**< @brief Ambient Light. [lux] */ 209 | } sh2_AmbientLight_t; 210 | 211 | /** 212 | * @brief Humidity 213 | * 214 | * See the SH-2 Reference Manual for more detail. 215 | */ 216 | typedef struct sh2_Humidity { 217 | float value; /**< @brief Relative Humidity. [percent] */ 218 | } sh2_Humidity_t; 219 | 220 | /** 221 | * @brief Proximity 222 | * 223 | * See the SH-2 Reference Manual for more detail. 224 | */ 225 | typedef struct sh2_Proximity { 226 | float value; /**< @brief Proximity. [cm] */ 227 | } sh2_Proximity_t; 228 | 229 | /** 230 | * @brief Temperature 231 | * 232 | * See the SH-2 Reference Manual for more detail. 233 | */ 234 | typedef struct sh2_Temperature { 235 | float value; /**< @brief Temperature. [C] */ 236 | } sh2_Temperature_t; 237 | 238 | /** 239 | * @brief Reserved 240 | * 241 | * See the SH-2 Reference Manual for more detail. 242 | */ 243 | typedef struct sh2_Reserved { 244 | float tbd; /**< @brief Reserved */ 245 | } sh2_Reserved_t; 246 | 247 | /** 248 | * @brief TapDetector 249 | * 250 | * See the SH-2 Reference Manual for more detail. 251 | */ 252 | #define TAPDET_X (1) 253 | #define TAPDET_X_POS (2) 254 | #define TAPDET_Y (4) 255 | #define TAPDET_Y_POS (8) 256 | #define TAPDET_Z (16) 257 | #define TAPDET_Z_POS (32) 258 | #define TAPDET_DOUBLE (64) 259 | typedef struct sh2_TapDetector { 260 | uint8_t flags; /**< @brief TapDetector. */ 261 | } sh2_TapDetector_t; 262 | 263 | /** 264 | * @brief StepDetector 265 | * 266 | * See the SH-2 Reference Manual for more detail. 267 | */ 268 | typedef struct sh2_StepDetector { 269 | uint32_t latency; /**< @brief Step detect latency [uS]. */ 270 | } sh2_StepDetector_t; 271 | 272 | /** 273 | * @brief StepCounter 274 | * 275 | * See the SH-2 Reference Manual for more detail. 276 | */ 277 | typedef struct sh2_StepCounter { 278 | uint32_t latency; /**< @brief Step counter latency [uS]. */ 279 | uint16_t steps; /**< @brief Steps counted. */ 280 | } sh2_StepCounter_t; 281 | 282 | /** 283 | * @brief SigMotion 284 | * 285 | * See the SH-2 Reference Manual for more detail. 286 | */ 287 | typedef struct sh2_SigMotion { 288 | uint16_t motion; 289 | } sh2_SigMotion_t; 290 | 291 | /** 292 | * @brief StabilityClassifier 293 | * 294 | * See the SH-2 Reference Manual for more detail. 295 | */ 296 | #define STABILITY_CLASSIFIER_UNKNOWN (0) 297 | #define STABILITY_CLASSIFIER_ON_TABLE (1) 298 | #define STABILITY_CLASSIFIER_STATIONARY (2) 299 | #define STABILITY_CLASSIFIER_STABLE (3) 300 | #define STABILITY_CLASSIFIER_MOTION (4) 301 | #define STABILITY_CLASSIFIER_RESERVED (5) 302 | typedef struct sh2_StabilityClassifier { 303 | uint8_t classification; 304 | } sh2_StabilityClassifier_t; 305 | 306 | /** 307 | * @brief ShakeDetector 308 | * 309 | * See the SH-2 Reference Manual for more detail. 310 | */ 311 | #define SHAKE_X (1) 312 | #define SHAKE_Y (2) 313 | #define SHAKE_Z (4) 314 | typedef struct sh2_ShakeDetector { 315 | uint16_t shake; 316 | } sh2_ShakeDetector_t; 317 | 318 | /** 319 | * @brief flipDetector 320 | * 321 | * See the SH-2 Reference Manual for more detail. 322 | */ 323 | typedef struct sh2_FlipDetector { 324 | uint16_t flip; 325 | } sh2_FlipDetector_t; 326 | 327 | /** 328 | * @brief pickupDetector 329 | * 330 | * See the SH-2 Reference Manual for more detail. 331 | */ 332 | #define PICKUP_LEVEL_TO_NOT_LEVEL (1) 333 | #define PICKUP_STOP_WITHIN_REGION (2) 334 | typedef struct sh2_PickupDetector { 335 | uint16_t pickup; /**< flag field with bits defined above. */ 336 | } sh2_PickupDetector_t; 337 | 338 | /** 339 | * @brief stabilityDetector 340 | * 341 | * See the SH-2 Reference Manual for more detail. 342 | */ 343 | #define STABILITY_ENTERED (1) 344 | #define STABILITY_EXITED (2) 345 | typedef struct sh2_StabilityDetector { 346 | uint16_t stability; /**< flag field with bits defined above. */ 347 | } sh2_StabilityDetector_t; 348 | 349 | /** 350 | * @brief Personal Activity Classifier 351 | * 352 | * See the SH-2 Reference Manual for more detail. 353 | */ 354 | #define PAC_UNKNOWN (0) 355 | #define PAC_IN_VEHICLE (1) 356 | #define PAC_ON_BICYCLE (2) 357 | #define PAC_ON_FOOT (3) 358 | #define PAC_STILL (4) 359 | #define PAC_TILTING (5) 360 | #define PAC_WALKING (6) 361 | #define PAC_RUNNING (7) 362 | typedef struct sh2_PersonalActivityClassifier { 363 | uint8_t page; 364 | bool lastPage; 365 | uint8_t mostLikelyState; 366 | uint8_t confidence[10]; 367 | } sh2_PersonalActivityClassifier_t; 368 | 369 | /** 370 | * @brief sleepDetector 371 | * 372 | * See the SH-2 Reference Manual for more detail. 373 | */ 374 | typedef struct sh2_SleepDetector { 375 | uint8_t sleepState; 376 | } sh2_SleepDetector_t; 377 | 378 | /** 379 | * @brief tiltDetector 380 | * 381 | * See the SH-2 Reference Manual for more detail. 382 | */ 383 | typedef struct sh2_TiltDetector { 384 | uint16_t tilt; 385 | } sh2_TiltDetector_t; 386 | 387 | /** 388 | * @brief pocketDetector 389 | * 390 | * See the SH-2 Reference Manual for more detail. 391 | */ 392 | typedef struct sh2_PocketDetector { 393 | uint16_t pocket; 394 | } sh2_PocketDetector_t; 395 | 396 | /** 397 | * @brief circleDetector 398 | * 399 | * See the SH-2 Reference Manual for more detail. 400 | */ 401 | typedef struct sh2_CircleDetector { 402 | uint16_t circle; 403 | } sh2_CircleDetector_t; 404 | 405 | /** 406 | * @brief heartRateMonitor 407 | * 408 | * See SH-2 Reference Manual for details. 409 | */ 410 | typedef struct sh2_HeartRateMonitor { 411 | uint16_t heartRate; /**< heart rate in beats per minute. */ 412 | } sh2_HeartRateMonitor_t; 413 | 414 | /** 415 | * @brief Gyro Integrated Rotation Vector 416 | * 417 | * See SH-2 Reference Manual for details. 418 | */ 419 | typedef struct sh2_GyroIntegratedRV { 420 | float i; /**< @brief Quaternion component i */ 421 | float j; /**< @brief Quaternion component j */ 422 | float k; /**< @brief Quaternion component k */ 423 | float real; /**< @brief Quaternion component real */ 424 | float angVelX; /**< @brief Angular velocity about x [rad/s] */ 425 | float angVelY; /**< @brief Angular velocity about y [rad/s] */ 426 | float angVelZ; /**< @brief Angular velocity about z [rad/s] */ 427 | } sh2_GyroIntegratedRV_t; 428 | 429 | typedef struct sh2_IZroRequest { 430 | sh2_IZroMotionIntent_t intent; 431 | sh2_IZroMotionRequest_t request; 432 | } sh2_IZroRequest_t; 433 | 434 | typedef struct sh2_SensorValue { 435 | 436 | /** Which sensor produced this event. */ 437 | uint8_t sensorId; 438 | 439 | /** @brief 8-bit unsigned integer used to track reports. 440 | * 441 | * The sequence number increments once for each report sent. Gaps 442 | * in the sequence numbers indicate missing or dropped reports. 443 | */ 444 | uint8_t sequence; 445 | 446 | /* Status of a sensor 447 | * 0 - Unreliable 448 | * 1 - Accuracy low 449 | * 2 - Accuracy medium 450 | * 3 - Accuracy high 451 | */ 452 | uint8_t status; /**< @brief bits 7-5: reserved, 4-2: exponent delay, 1-0: Accuracy */ 453 | 454 | uint64_t timestamp; /**< [uS] */ 455 | 456 | uint32_t delay; /**< @brief [uS] value is delay * 2^exponent (see status) */ 457 | 458 | /** @brief Sensor Data 459 | * 460 | * Use the structure based on the value of the sensor 461 | * field. 462 | */ 463 | union { 464 | sh2_RawAccelerometer_t rawAccelerometer; 465 | sh2_Accelerometer_t accelerometer; 466 | sh2_Accelerometer_t linearAcceleration; 467 | sh2_Accelerometer_t gravity; 468 | sh2_RawGyroscope_t rawGyroscope; 469 | sh2_Gyroscope_t gyroscope; 470 | sh2_GyroscopeUncalibrated_t gyroscopeUncal; 471 | sh2_RawMagnetometer_t rawMagnetometer; 472 | sh2_MagneticField_t magneticField; 473 | sh2_MagneticFieldUncalibrated_t magneticFieldUncal; 474 | sh2_RotationVectorWAcc_t rotationVector; 475 | sh2_RotationVector_t gameRotationVector; 476 | sh2_RotationVectorWAcc_t geoMagRotationVector; 477 | sh2_Pressure_t pressure; 478 | sh2_AmbientLight_t ambientLight; 479 | sh2_Humidity_t humidity; 480 | sh2_Proximity_t proximity; 481 | sh2_Temperature_t temperature; 482 | sh2_Reserved_t reserved; 483 | sh2_TapDetector_t tapDetector; 484 | sh2_StepDetector_t stepDetector; 485 | sh2_StepCounter_t stepCounter; 486 | sh2_SigMotion_t sigMotion; 487 | sh2_StabilityClassifier_t stabilityClassifier; 488 | sh2_ShakeDetector_t shakeDetector; 489 | sh2_FlipDetector_t flipDetector; 490 | sh2_PickupDetector_t pickupDetector; 491 | sh2_StabilityDetector_t stabilityDetector; 492 | sh2_PersonalActivityClassifier_t personalActivityClassifier; 493 | sh2_SleepDetector_t sleepDetector; 494 | sh2_TiltDetector_t tiltDetector; 495 | sh2_PocketDetector_t pocketDetector; 496 | sh2_CircleDetector_t circleDetector; 497 | sh2_HeartRateMonitor_t heartRateMonitor; 498 | sh2_RotationVectorWAcc_t arvrStabilizedRV; 499 | sh2_RotationVector_t arvrStabilizedGRV; 500 | sh2_GyroIntegratedRV_t gyroIntegratedRV; 501 | sh2_IZroRequest_t izroRequest; 502 | } un; 503 | } sh2_SensorValue_t; 504 | 505 | int sh2_decodeSensorEvent(sh2_SensorValue_t *value, const sh2_SensorEvent_t *event); 506 | 507 | 508 | #ifdef __cplusplus 509 | } // extern "C" 510 | #endif 511 | 512 | #endif 513 | -------------------------------------------------------------------------------- /src/sh2_err.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-16 Hillcrest Laboratories, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License and 6 | * any applicable agreements you may have with Hillcrest Laboratories, Inc. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /** 19 | * @file sh2_err.h 20 | * @author David Wheeler 21 | * @date 22 May 2015 22 | * @brief Type definitions for Hillcrest SH-2 API. 23 | * 24 | * Struct and type definitions supporting the Hillcrest SH-2 SensorHub API. 25 | * 26 | */ 27 | 28 | 29 | #ifndef SH2_ERR_H 30 | #define SH2_ERR_H 31 | 32 | 33 | #define SH2_OK (0) /**< Success */ 34 | #define SH2_ERR (-1) /**< General Error */ 35 | #define SH2_ERR_BAD_PARAM (-2) /**< Bad parameter to an API call */ 36 | #define SH2_ERR_OP_IN_PROGRESS (-3) /**< Operation in progress */ 37 | #define SH2_ERR_IO (-4) /**< Error communicating with hub */ 38 | #define SH2_ERR_HUB (-5) /**< Error reported by hub */ 39 | #define SH2_ERR_TIMEOUT (-6) /**< Operation timed out */ 40 | 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/sh2_hal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 Hillcrest Laboratories, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License and 6 | * any applicable agreements you may have with Hillcrest Laboratories, Inc. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* 19 | * SH2 HAL Interface for Non-RTOS Applications. 20 | */ 21 | 22 | // Include guard 23 | #ifndef SH2_HAL_H 24 | #define SH2_HAL_H 25 | 26 | #include 27 | 28 | // SH2 Implementations generally have a max out transfer len of 256 29 | #define SH2_HAL_MAX_TRANSFER_OUT (256) 30 | #define SH2_HAL_MAX_PAYLOAD_OUT (256) 31 | 32 | // Although some implementations adversize a max in transfer of 32K, 33 | // in practice, the largest transfer performed is the advertisements 34 | // which is 272 bytes at time of writing. 35 | #define SH2_HAL_MAX_TRANSFER_IN (384) 36 | #define SH2_HAL_MAX_PAYLOAD_IN (384) 37 | 38 | // This needs to be a power of 2, greater than max of the above. 39 | #define SH2_HAL_DMA_SIZE (512) 40 | 41 | typedef struct sh2_Hal_s sh2_Hal_t; 42 | 43 | // The SH2 interface uses these functions to access the underlying 44 | // communications device, so the system integrator will need to 45 | // implement these. At system intialization time, an sh2_Hal_t 46 | // structure should be initialized with pointers to all the hardware 47 | // access layer functions. A pointer to this structure must then be 48 | // passed to sh2_open() to initialize the SH2 interface. 49 | // 50 | // If the DFU (download firmware update) capability is needed, the 51 | // example DFU code also uses this interface but each function has 52 | // somewhat different requirements. So a separate instance of an 53 | // sh2_Hal_t structure, pointing to different functions, is 54 | // recommended for supporting DFU. 55 | 56 | struct sh2_Hal_s { 57 | // This function initializes communications with the device. It 58 | // can initialize any GPIO pins and peripheral devices used to 59 | // interface with the sensor hub. 60 | // It should also perform a reset cycle on the sensor hub to 61 | // ensure communications start from a known state. 62 | int (*open)(sh2_Hal_t *self); 63 | 64 | // This function completes communications with the sensor hub. 65 | // It should put the device in reset then de-initialize any 66 | // peripherals or hardware resources that were used. 67 | void (*close)(sh2_Hal_t *self); 68 | 69 | // This function supports reading data from the sensor hub. 70 | // It will be called frequently to sevice the device. 71 | // 72 | // If the HAL has received a full SHTP transfer, this function 73 | // should load the data into pBuffer, set the timestamp to the 74 | // time the interrupt was detected and return the non-zero length 75 | // of data in this transfer. 76 | // 77 | // If the HAL has not recevied a full SHTP transfer, this function 78 | // should return 0. 79 | // 80 | // Because this function is called regularly, it can be used to 81 | // perform other housekeeping operations. (In the case of UART 82 | // interfacing, bytes transmitted are staggered in time and this 83 | // function can be used to keep the transmission flowing.) 84 | int (*read)(sh2_Hal_t *self, uint8_t *pBuffer, unsigned len, uint32_t *t_us); 85 | 86 | // This function supports writing data to the sensor hub. 87 | // It is called each time the application has a block of data to 88 | // transfer to the device. 89 | // 90 | // If the device isn't ready to receive data this function can 91 | // return 0 without performing the transmit function. 92 | // 93 | // If the transmission can be started, this function needs to 94 | // copy the data from pBuffer and return the number of bytes 95 | // accepted. It need not block. The actual transmission of 96 | // the data can continue after this function returns. 97 | int (*write)(sh2_Hal_t *self, uint8_t *pBuffer, unsigned len); 98 | 99 | // This function should return a 32-bit value representing a 100 | // microsecond counter. The count may roll over after 2^32 101 | // microseconds. 102 | uint32_t (*getTimeUs)(sh2_Hal_t *self); 103 | }; 104 | 105 | // End of include guard 106 | #endif 107 | -------------------------------------------------------------------------------- /src/sh2_util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-16 Hillcrest Laboratories, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License and 6 | * any applicable agreements you may have with Hillcrest Laboratories, Inc. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* 19 | * Simple Utility functions common to several SH2 files. 20 | */ 21 | 22 | #include "sh2_util.h" 23 | 24 | uint8_t readu8(const uint8_t *p) 25 | { 26 | uint8_t retval = p[0]; 27 | return retval; 28 | } 29 | 30 | void writeu8(uint8_t * p, uint8_t value) 31 | { 32 | *p = (uint8_t)(value & 0xFF); 33 | } 34 | 35 | uint16_t readu16(const uint8_t *p) 36 | { 37 | uint16_t retval = p[0] | (p[1] << 8); 38 | return retval; 39 | } 40 | 41 | void writeu16(uint8_t * p, uint16_t value) 42 | { 43 | *p++ = (uint8_t)(value & 0xFF); 44 | value >>= 8; 45 | *p = (uint8_t)(value & 0xFF); 46 | } 47 | 48 | uint32_t readu32(const uint8_t *p) 49 | { 50 | uint32_t retval = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 51 | return retval; 52 | } 53 | 54 | void writeu32(uint8_t * p, uint32_t value) 55 | { 56 | *p++ = (uint8_t)(value & 0xFF); 57 | value >>= 8; 58 | *p++ = (uint8_t)(value & 0xFF); 59 | value >>= 8; 60 | *p++ = (uint8_t)(value & 0xFF); 61 | value >>= 8; 62 | *p = (uint8_t)(value & 0xFF); 63 | } 64 | 65 | int8_t read8(const uint8_t *p) 66 | { 67 | int8_t retval = p[0]; 68 | return retval; 69 | } 70 | 71 | void write8(uint8_t * p, int8_t value) 72 | { 73 | *p = (uint8_t)(value & 0xFF); 74 | } 75 | 76 | int16_t read16(const uint8_t *p) 77 | { 78 | int16_t retval = p[0] | (p[1] << 8); 79 | return retval; 80 | } 81 | 82 | void write16(uint8_t * p, int16_t value) 83 | { 84 | *p++ = (uint8_t)(value & 0xFF); 85 | value >>= 8; 86 | *p = (uint8_t)(value & 0xFF); 87 | } 88 | 89 | int32_t read32(const uint8_t *p) 90 | { 91 | int32_t retval = p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24); 92 | return retval; 93 | } 94 | 95 | void write32(uint8_t * p, int32_t value) 96 | { 97 | *p++ = (uint8_t)(value & 0xFF); 98 | value >>= 8; 99 | *p++ = (uint8_t)(value & 0xFF); 100 | value >>= 8; 101 | *p++ = (uint8_t)(value & 0xFF); 102 | value >>= 8; 103 | *p = (uint8_t)(value & 0xFF); 104 | } 105 | -------------------------------------------------------------------------------- /src/sh2_util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-16 Hillcrest Laboratories, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License and 6 | * any applicable agreements you may have with Hillcrest Laboratories, Inc. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* 19 | * Simple Utility functions common to several SH2 files. 20 | */ 21 | 22 | #ifndef SH2_UTIL_H 23 | #define SH2_UTIL_H 24 | 25 | #include 26 | 27 | #ifndef ARRAY_LEN 28 | #define ARRAY_LEN(a) (sizeof(a)/sizeof(a[0])) 29 | #endif 30 | 31 | uint8_t readu8(const uint8_t * buffer); 32 | void writeu8(uint8_t * buffer, uint8_t value); 33 | uint16_t readu16(const uint8_t * buffer); 34 | void writeu16(uint8_t * buffer, uint16_t value); 35 | uint32_t readu32(const uint8_t * buffer); 36 | void writeu32(uint8_t * buffer, uint32_t value); 37 | 38 | int8_t read8(const uint8_t * buffer); 39 | void write8(uint8_t * buffer, int8_t value); 40 | int16_t read16(const uint8_t * buffer); 41 | void write16(uint8_t * buffer, int16_t value); 42 | int32_t read32(const uint8_t * buffer); 43 | void write32(uint8_t * buffer, int32_t value); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/shtp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2015-18 Hillcrest Laboratories, Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License and 6 | * any applicable agreements you may have with Hillcrest Laboratories, Inc. 7 | * You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | /* 19 | * Hillcrest Sensor Hub Transport Protocol (SHTP) API 20 | */ 21 | 22 | #ifndef SHTP_H 23 | #define SHTP_H 24 | 25 | #include 26 | #include 27 | 28 | #include "sh2_hal.h" 29 | 30 | // Advertisement TLV tags 31 | #define TAG_NULL 0 32 | #define TAG_GUID 1 33 | #define TAG_MAX_CARGO_PLUS_HEADER_WRITE 2 34 | #define TAG_MAX_CARGO_PLUS_HEADER_READ 3 35 | #define TAG_MAX_TRANSFER_WRITE 4 36 | #define TAG_MAX_TRANSFER_READ 5 37 | #define TAG_NORMAL_CHANNEL 6 38 | #define TAG_WAKE_CHANNEL 7 39 | #define TAG_APP_NAME 8 40 | #define TAG_CHANNEL_NAME 9 41 | #define TAG_ADV_COUNT 10 42 | #define TAG_APP_SPECIFIC 0x80 43 | 44 | typedef enum shtp_Event_e { 45 | SHTP_TX_DISCARD = 0, 46 | SHTP_SHORT_FRAGMENT = 1, 47 | SHTP_TOO_LARGE_PAYLOADS = 2, 48 | SHTP_BAD_RX_CHAN = 3, 49 | SHTP_BAD_TX_CHAN = 4, 50 | } shtp_Event_t; 51 | 52 | typedef void shtp_Callback_t(void * cookie, uint8_t *payload, uint16_t len, uint32_t timestamp); 53 | typedef void shtp_AdvertCallback_t(void * cookie, uint8_t tag, uint8_t len, uint8_t *value); 54 | typedef void shtp_SendCallback_t(void *cookie); 55 | typedef void shtp_EventCallback_t(void *cookie, shtp_Event_t shtpEvent); 56 | 57 | // Takes HAL pointer, returns shtp ID for use in future calls. 58 | // HAL will be opened by this call. 59 | void * shtp_open(sh2_Hal_t *pHal); 60 | 61 | // Releases resources associated with this SHTP instance. 62 | // HAL will not be closed. 63 | void shtp_close(void *pShtp); 64 | 65 | // Provide the point of the callback function for reporting SHTP asynchronous events 66 | void shtp_setEventCallback(void *pInstance, 67 | shtp_EventCallback_t * eventCallback, 68 | void *eventCookie); 69 | 70 | // Register a listener for an SHTP channel 71 | int shtp_listenChan(void *pShtp, 72 | uint16_t guid, const char * chan, 73 | shtp_Callback_t *callback, void * cookie); 74 | 75 | // Register a listener for SHTP advertisements 76 | int shtp_listenAdvert(void *pShtp, 77 | uint16_t guid, 78 | shtp_AdvertCallback_t *advertCallback, void * cookie); 79 | 80 | // Look up the channel number for a particular app, channel. 81 | uint8_t shtp_chanNo(void *pShtp, 82 | const char * appName, const char * chanName); 83 | 84 | // Send an SHTP payload on a particular channel 85 | int shtp_send(void *pShtp, 86 | uint8_t channel, const uint8_t *payload, uint16_t len); 87 | 88 | // Check for received data and process it. 89 | void shtp_service(void *pShtp); 90 | 91 | // #ifdef SHTP_H 92 | #endif 93 | --------------------------------------------------------------------------------