From 467286cd743f20251c693b786ee1e33bd45253d2 Mon Sep 17 00:00:00 2001 From: Matt Bradford Date: Sun, 1 Aug 2021 12:48:32 +1000 Subject: [PATCH 1/5] Implement hasReset() to track Reset Complete response. --- .../Example21-ResetCheck.ino | 85 +++++++++++++++++++ keywords.txt | 1 + src/SparkFun_BNO080_Arduino_Library.cpp | 19 +++++ src/SparkFun_BNO080_Arduino_Library.h | 6 ++ 4 files changed, 111 insertions(+) create mode 100644 examples/Example21-ResetCheck/Example21-ResetCheck.ino diff --git a/examples/Example21-ResetCheck/Example21-ResetCheck.ino b/examples/Example21-ResetCheck/Example21-ResetCheck.ino new file mode 100644 index 0000000..a2c76b0 --- /dev/null +++ b/examples/Example21-ResetCheck/Example21-ResetCheck.ino @@ -0,0 +1,85 @@ +/* + Using the BNO080 IMU hasReset() function + By: @mattbradford83 + Date: 1 August 2021 + SparkFun code, firmware, and software is released under the MIT License. + Please see LICENSE.md for further details. + + This example shows how check for a "Reset Complete" packet from the sensor, + which is helpful when used in tandem with resetReason(). The sensor will be + reset each time 25 readings are received to demonstrate. + +*/ + +#include + +#include "SparkFun_BNO080_Arduino_Library.h" // Click here to get the library: http://librarymanager/All#SparkFun_BNO080 + +#define BNO08X_ADDR 0x4A +//#define BNO08X_ADDR 0x4B + +BNO080 myIMU; + +int cyclecount = 0; + + +// After a reset, reports need to be re-enabled. +void enableReports() { + myIMU.enableGyro(50); //Send data update every 50ms +} + +void setup() +{ + Serial.begin(115200); + Serial.println(); + Serial.println("BNO080 Read Example"); + + Wire.begin(); + Wire.flush(); + if (!myIMU.begin(BNO08X_ADDR)) { + Serial.println("Could Not Enable BNO Sensor! Check your I2C Address."); + return; + } + + enableReports(); + + Serial.println(F("Gyro enabled")); + Serial.println(F("Output in form x, y, z, in radians per second")); +} + +void loop() +{ + // One of these will appear at the very start because of the power on reset. + // Check resetReason() for the difference between different resets. + if (myIMU.hasReset()) { + Serial.println(" ------------------ BNO085 has reset. ------------------ "); + Serial.printf(" Reason: %i\n",myIMU.resetReason()); + enableReports(); // We'll need to re-enable reports after any reset. + } + + //Look for reports from the IMU + if (myIMU.dataAvailable()) + { + cyclecount++; + Serial.printf("[%2i] ",cyclecount); + + float x = myIMU.getGyroX(); + float y = myIMU.getGyroY(); + float z = myIMU.getGyroZ(); + + Serial.print(x, 2); + Serial.print(F(",")); + Serial.print(y, 2); + Serial.print(F(",")); + Serial.print(z, 2); + Serial.print(F(",")); + + Serial.println(); + + if (cyclecount == 25) { + myIMU.softReset(); + cyclecount=0; + } + + } +} diff --git a/keywords.txt b/keywords.txt index 89dc28e..318ed33 100644 --- a/keywords.txt +++ b/keywords.txt @@ -19,6 +19,7 @@ enableDebugging KEYWORD2 softReset KEYWORD2 resetReason KEYWORD2 +hasReset KEYWORD2 modeOn KEYWORD2 modeSleep KEYWORD2 diff --git a/src/SparkFun_BNO080_Arduino_Library.cpp b/src/SparkFun_BNO080_Arduino_Library.cpp index 179f624..6c84081 100644 --- a/src/SparkFun_BNO080_Arduino_Library.cpp +++ b/src/SparkFun_BNO080_Arduino_Library.cpp @@ -999,6 +999,16 @@ void BNO080::modeSleep(void) ; //delay(1); } +// Indicates if we've received a Reset Complete packet. Once it's been read, +// the state will reset to false until another Reset Complete packet is found. +bool BNO080::hasReset() { + if (_hasReset) { + _hasReset = false; + return true; + } + return false; +} + //Get the reason for the last reset //1 = POR, 2 = Internal reset, 3 = Watchdog, 4 = External reset, 5 = Other uint8_t BNO080::resetReason() @@ -1447,6 +1457,15 @@ boolean BNO080::receivePacket(void) getData(dataLength); } + // Quickly check for reset complete packet. No need for a seperate parser. + // This function is also called after soft reset, so we need to catch this + // packet here otherwise we need to check for the reset packet in multiple + // places. + if (shtpHeader[2] == CHANNEL_EXECUTABLE && shtpData[0] == EXECUTABLE_RESET_COMPLETE) + { + _hasReset = true; + } + return (true); //We're done! } diff --git a/src/SparkFun_BNO080_Arduino_Library.h b/src/SparkFun_BNO080_Arduino_Library.h index 025f9c8..0b1c811 100644 --- a/src/SparkFun_BNO080_Arduino_Library.h +++ b/src/SparkFun_BNO080_Arduino_Library.h @@ -100,6 +100,9 @@ const byte CHANNEL_GYRO = 5; #define FRS_RECORDID_MAGNETIC_FIELD_CALIBRATED 0xE309 #define FRS_RECORDID_ROTATION_VECTOR 0xE30B +// Reset complete packet (BNO08X Datasheet p.24 Figure 1-27) +#define EXECUTABLE_RESET_COMPLETE 0x1 + //Command IDs from section 6.4, page 42 //These are used to calibrate, initialize, set orientation, tare etc the sensor #define COMMAND_ERRORS 1 @@ -131,6 +134,7 @@ class BNO080 void enableDebugging(Stream &debugPort = Serial); //Turn on debug printing. If user doesn't specify then Serial will be used. void softReset(); //Try to reset the IMU via software + bool hasReset(); //Returns true if the sensor has reported a reset. Reading this will unflag the reset. uint8_t resetReason(); //Query the IMU for the reason it last reset void modeOn(); //Use the executable channel to turn the BNO on void modeSleep(); //Use the executable channel to put the BNO to sleep @@ -273,6 +277,8 @@ class BNO080 uint8_t _int; uint8_t _rst; + bool _hasReset = false; // Keeps track of any Reset Complete packets we receive. + //These are the raw sensor values (without Q applied) pulled from the user requested Input Report uint16_t rawAccelX, rawAccelY, rawAccelZ, accelAccuracy; uint16_t rawLinAccelX, rawLinAccelY, rawLinAccelZ, accelLinAccuracy; From f4cb60104f6312976389872d3aa3ce24e5dcfd2a Mon Sep 17 00:00:00 2001 From: PaulZC Date: Mon, 8 Mar 2021 18:36:59 +0000 Subject: [PATCH 2/5] Update Example20-Sleep. Add non-unitary Quat debug messages. This commit updates Example20: The I2C clock speed is only increased to 400kHz _after_ enabling the Rotation Vector. I think bus errors sometimes cause the setFeatureCommand to fail at 400kHz. Also, we only communicate with the BNO while it is awake. Talking to it continuously while it is asleep raises the current draw significantly This commit also adds extra debug messages to help trap those rare occasions when QuatI/J/K is >|1|. My theory is these are bus errors on the MS (sign) bit of the int16_t data when running at 400kHz. --- examples/Example20-Sleep/Example20-Sleep.ino | 60 ++++++++++++-------- src/SparkFun_BNO080_Arduino_Library.cpp | 36 ++++++++++++ 2 files changed, 71 insertions(+), 25 deletions(-) diff --git a/examples/Example20-Sleep/Example20-Sleep.ino b/examples/Example20-Sleep/Example20-Sleep.ino index ca93525..bdf1b0a 100644 --- a/examples/Example20-Sleep/Example20-Sleep.ino +++ b/examples/Example20-Sleep/Example20-Sleep.ino @@ -26,6 +26,9 @@ #include "SparkFun_BNO080_Arduino_Library.h" // Click here to get the library: http://librarymanager/All#SparkFun_BNO080 BNO080 myIMU; +unsigned long lastMillis = 0; // Keep track of time +bool lastPowerState = true; // Toggle between "On" and "Sleep" + void setup() { Serial.begin(115200); @@ -44,46 +47,51 @@ void setup() // Wire.setClockStretchLimit(4000); // //================================= + //myIMU.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + if (myIMU.begin() == false) { Serial.println("BNO080 not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); while (1); } - Wire.setClock(400000); //Increase I2C data rate to 400kHz + // Enable the Rotation Vector packet ** while the I2C bus is set to 100kHz ** + myIMU.enableRotationVector(50); //Send RV data update every 50ms - myIMU.enableRotationVector(50); //Send data update every 50ms + Wire.setClock(400000); //Now increase I2C data rate to 400kHz Serial.println(F("Rotation vector enabled")); Serial.println(F("Output in form i, j, k, real, accuracy")); -} -unsigned long lastMillis = 0; // Keep track of time -bool lastPowerState = true; // Toggle between "On" and "Sleep" + lastMillis = millis(); // Keep track of time +} void loop() { - //Look for reports from the IMU - if (myIMU.dataAvailable() == true) + //Look for reports from the IMU - ** but only when not asleep ** + if (lastPowerState) // Are we "On"? (Comment this if you are interested in how it effects the sleep current) { - float quatI = myIMU.getQuatI(); - float quatJ = myIMU.getQuatJ(); - float quatK = myIMU.getQuatK(); - float quatReal = myIMU.getQuatReal(); - float quatRadianAccuracy = myIMU.getQuatRadianAccuracy(); - - Serial.print(quatI, 2); - Serial.print(F(",")); - Serial.print(quatJ, 2); - Serial.print(F(",")); - Serial.print(quatK, 2); - Serial.print(F(",")); - Serial.print(quatReal, 2); - Serial.print(F(",")); - Serial.print(quatRadianAccuracy, 2); - Serial.print(F(",")); - - Serial.println(); + if (myIMU.dataAvailable() == true) // Is fresh data available? + { + float quatI = myIMU.getQuatI(); + float quatJ = myIMU.getQuatJ(); + float quatK = myIMU.getQuatK(); + float quatReal = myIMU.getQuatReal(); + float quatRadianAccuracy = myIMU.getQuatRadianAccuracy(); + + Serial.print(quatI, 2); + Serial.print(F(",")); + Serial.print(quatJ, 2); + Serial.print(F(",")); + Serial.print(quatK, 2); + Serial.print(F(",")); + Serial.print(quatReal, 2); + Serial.print(F(",")); + Serial.print(quatRadianAccuracy, 2); + Serial.print(F(",")); + + Serial.println(); + } } //Check if it is time to change the power state @@ -102,4 +110,6 @@ void loop() lastPowerState ^= 1; // Invert lastPowerState (using ex-or) } + + delay(10); // Don't pound the bus too hard (Comment this if you are interested in how it effects the sleep current) } diff --git a/src/SparkFun_BNO080_Arduino_Library.cpp b/src/SparkFun_BNO080_Arduino_Library.cpp index 179f624..61d6139 100644 --- a/src/SparkFun_BNO080_Arduino_Library.cpp +++ b/src/SparkFun_BNO080_Arduino_Library.cpp @@ -504,6 +504,18 @@ void BNO080::getQuat(float &i, float &j, float &k, float &real, float &radAccura float BNO080::getQuatI() { float quat = qToFloat(rawQuatI, rotationVector_Q1); + if (_printDebug == true) + { + if ((quat < -1.0) || (quat > 1.0)) + { + _debugPort->print(F("getQuatI: quat: ")); // Debug the occasional non-unitary Quat + _debugPort->print(quat, 2); + _debugPort->print(F(" rawQuatI: ")); + _debugPort->print(rawQuatI); + _debugPort->print(F(" rotationVector_Q1: ")); + _debugPort->println(rotationVector_Q1); + } + } return (quat); } @@ -511,6 +523,18 @@ float BNO080::getQuatI() float BNO080::getQuatJ() { float quat = qToFloat(rawQuatJ, rotationVector_Q1); + if (_printDebug == true) + { + if ((quat < -1.0) || (quat > 1.0)) // Debug the occasional non-unitary Quat + { + _debugPort->print(F("getQuatJ: quat: ")); + _debugPort->print(quat, 2); + _debugPort->print(F(" rawQuatJ: ")); + _debugPort->print(rawQuatJ); + _debugPort->print(F(" rotationVector_Q1: ")); + _debugPort->println(rotationVector_Q1); + } + } return (quat); } @@ -518,6 +542,18 @@ float BNO080::getQuatJ() float BNO080::getQuatK() { float quat = qToFloat(rawQuatK, rotationVector_Q1); + if (_printDebug == true) + { + if ((quat < -1.0) || (quat > 1.0)) // Debug the occasional non-unitary Quat + { + _debugPort->print(F("getQuatK: quat: ")); + _debugPort->print(quat, 2); + _debugPort->print(F(" rawQuatK: ")); + _debugPort->print(rawQuatK); + _debugPort->print(F(" rotationVector_Q1: ")); + _debugPort->println(rotationVector_Q1); + } + } return (quat); } From 64d00c67ac88d7406be5a1b6751d7bc357693f43 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Aug 2021 11:06:43 +0100 Subject: [PATCH 3/5] Update Example21: change default I2C address; remove printf's (printf is not supported on some platforms) --- .../Example21-ResetCheck/Example21-ResetCheck.ino | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/Example21-ResetCheck/Example21-ResetCheck.ino b/examples/Example21-ResetCheck/Example21-ResetCheck.ino index a2c76b0..20bfbd0 100644 --- a/examples/Example21-ResetCheck/Example21-ResetCheck.ino +++ b/examples/Example21-ResetCheck/Example21-ResetCheck.ino @@ -15,8 +15,8 @@ #include "SparkFun_BNO080_Arduino_Library.h" // Click here to get the library: http://librarymanager/All#SparkFun_BNO080 -#define BNO08X_ADDR 0x4A -//#define BNO08X_ADDR 0x4B +#define BNO08X_ADDR 0x4B // SparkFun BNO080 Breakout (Qwiic) defaults to 0x4B +//#define BNO08X_ADDR 0x4A // Alternate address if ADR jumper is closed BNO080 myIMU; @@ -53,7 +53,8 @@ void loop() // Check resetReason() for the difference between different resets. if (myIMU.hasReset()) { Serial.println(" ------------------ BNO085 has reset. ------------------ "); - Serial.printf(" Reason: %i\n",myIMU.resetReason()); + Serial.print(F(" Reason: ")); + Serial.println(myIMU.resetReason()); enableReports(); // We'll need to re-enable reports after any reset. } @@ -61,7 +62,11 @@ void loop() if (myIMU.dataAvailable()) { cyclecount++; - Serial.printf("[%2i] ",cyclecount); + + Serial.print(F("[")); + if (cyclecount < 10) Serial.print(F("0")); + Serial.print(cyclecount); + Serial.print(F("] ")); float x = myIMU.getGyroX(); float y = myIMU.getGyroY(); From 14cc216d469be9197fcf70680fd6809016d6d500 Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Aug 2021 11:10:23 +0100 Subject: [PATCH 4/5] v1.1.11 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 5615a31..357fe5d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=SparkFun BNO080 Cortex Based IMU -version=1.1.10 +version=1.1.11 author=SparkFun Electronics maintainer=SparkFun Electronics sentence=Library for the SparkFun Qwiic VR IMU - BNO080/BNO085 From 33c20918bb678b42b5b95f46c7794aac6cf03d3d Mon Sep 17 00:00:00 2001 From: PaulZC Date: Fri, 20 Aug 2021 11:16:13 +0100 Subject: [PATCH 5/5] Update thanks --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a05a877..c634ef6 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,8 @@ Thanks to all those who have helped improve the library: * Filimindji for AR/VR Stabilized RotationVector and AR/VR Stabilized GameRotationVector support - [PR 46](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/46) * ya-mouse for the getreadings improvements - [PR 55](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/55) * 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) +* aedancullen for the tap detector - [PR 64](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/64) +* mattbradford83 for the hasReset code and example - [PR 92](https://github.com/sparkfun/SparkFun_BNO080_Arduino_Library/pull/92) Repository Contents -------------------