diff --git a/examples/Example22-Tare/Example22-Tare.ino b/examples/Example22-Tare/Example22-Tare.ino new file mode 100644 index 0000000..cd94131 --- /dev/null +++ b/examples/Example22-Tare/Example22-Tare.ino @@ -0,0 +1,87 @@ +/* + Using the BNO080 IMU + + Example : Tare function + By: Sofian Audry + Date: March 2nd, 2022 + + Based on: Example9-Calibrate + By: Nathan Seidle + SparkFun Electronics + Date: December 21st, 2017 + SparkFun code, firmware, and software is released under the MIT License. + Please see LICENSE.md for further details. + + Feel like supporting our work? Buy a board from SparkFun! + https://www.sparkfun.com/products/14586 + + This example shows how to use the tare functionalities. + It is best to run a calibration before using the tare functions. + + It takes about 1ms at 400kHz I2C to read a record from the sensor, but we are polling the sensor continually + between updates from the sensor. Use the interrupt pin on the BNO080 breakout to avoid polling. + + Hardware Connections: + Attach the Qwiic Shield to your Arduino/Photon/ESP32 or other + Plug the sensor onto the shield + Serial.print it out at 115200 baud to serial monitor. +*/ +#include + +#include "SparkFun_BNO080_Arduino_Library.h" // Click here to get the library: http://librarymanager/All#SparkFun_BNO080 +BNO080 myIMU; + +void setup() +{ + Serial.begin(115200); + Serial.println(); + Serial.println("BNO080 Read Example"); + + Wire.begin(); + + myIMU.begin(); + + Wire.setClock(400000); //Increase I2C data rate to 400kHz + + //Enable Game Rotation Vector output + myIMU.enableRotationVector(100); //Send data update every 100ms + + //Once magnetic field is 2 or 3, run the Save DCD Now command + Serial.println(F("'t' to tare according to xyz")); + Serial.println(F("'z' to tare according to z axis only")); + Serial.println(F("'s' to save tare settings")); + Serial.println(F("'r' to reset/clear tare orientation registry")); + Serial.println(F("Output in form x, y, z, in uTesla")); +} + +void loop() +{ + if(Serial.available()) + { + byte incoming = Serial.read(); + + switch (incoming) { + case 't': myIMU.tareNow(); break; + case 'z': myIMU.tareNow(true); break; + case 's': myIMU.saveTare(); break; + case 'r': myIMU.clearTare(); break; + default:; + } + } + + //Look for reports from the IMU + if (myIMU.dataAvailable() == true) + { + float roll = (myIMU.getRoll()) * 180.0 / PI; // Convert roll to degrees + float pitch = (myIMU.getPitch()) * 180.0 / PI; // Convert pitch to degrees + float yaw = (myIMU.getYaw()) * 180.0 / PI; // Convert yaw / heading to degrees + + Serial.print(roll, 1); + Serial.print(F(",")); + Serial.print(pitch, 1); + Serial.print(F(",")); + Serial.print(yaw, 1); + + Serial.println(); + } +} diff --git a/src/SparkFun_BNO080_Arduino_Library.cpp b/src/SparkFun_BNO080_Arduino_Library.cpp index 1ebdfe7..eaa198a 100644 --- a/src/SparkFun_BNO080_Arduino_Library.cpp +++ b/src/SparkFun_BNO080_Arduino_Library.cpp @@ -1221,6 +1221,21 @@ boolean BNO080::calibrationComplete() return (false); } +void BNO080::tareNow(bool zAxis, uint8_t rotationVectorBasis) +{ + sendTareCommand(TARE_NOW, zAxis ? TARE_AXIS_Z : TARE_AXIS_ALL, rotationVectorBasis); +} + +void BNO080::saveTare() +{ + sendTareCommand(TARE_PERSIST); +} + +void BNO080::clearTare() +{ + sendTareCommand(TARE_SET_REORIENTATION); +} + //Given a sensor's report ID, this tells the BNO080 to begin reporting the values void BNO080::setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports) { @@ -1320,6 +1335,23 @@ void BNO080::sendCalibrateCommand(uint8_t thingToCalibrate) sendCommand(COMMAND_ME_CALIBRATE); } +void BNO080::sendTareCommand(uint8_t command, uint8_t axis, uint8_t rotationVectorBasis) +{ + for (uint8_t x = 3; x < 12; x++) //Clear this section of the shtpData array + shtpData[x] = 0; + + shtpData[3] = command; + + if (command == TARE_NOW) + { + shtpData[4] = axis; // axis setting + shtpData[5] = rotationVectorBasis; // rotation vector + } + + //Using this shtpData packet, send a command + sendCommand(COMMAND_TARE); +} + //Request ME Calibration Status from BNO080 //See page 51 of reference manual void BNO080::requestCalibrationStatus() diff --git a/src/SparkFun_BNO080_Arduino_Library.h b/src/SparkFun_BNO080_Arduino_Library.h index 0b1c811..0cde58f 100644 --- a/src/SparkFun_BNO080_Arduino_Library.h +++ b/src/SparkFun_BNO080_Arduino_Library.h @@ -122,6 +122,20 @@ const byte CHANNEL_GYRO = 5; #define CALIBRATE_ACCEL_GYRO_MAG 4 #define CALIBRATE_STOP 5 +#define TARE_NOW 0 +#define TARE_PERSIST 1 +#define TARE_SET_REORIENTATION 2 + +#define TARE_AXIS_ALL 0x07 +#define TARE_AXIS_Z 0x04 + +#define TARE_ROTATION_VECTOR 0 +#define TARE_GAME_ROTATION_VECTOR 1 +#define TARE_GEOMAGNETIC_ROTATION_VECTOR 2 +#define TARE_GYRO_INTEGRATED_ROTATION_VECTOR 3 +#define TARE_AR_VR_STABILIZED_ROTATION_VECTOR 4 +#define TARE_AR_VR_STABILIZED_GAME_ROTATION_VECTOR 5 + #define MAX_PACKET_SIZE 128 //Packets can be up to 32k but we don't have that much RAM. #define MAX_METADATA_SIZE 9 //This is in words. There can be many but we mostly only care about the first 9 (Qs, range, etc) @@ -218,6 +232,10 @@ class BNO080 void requestCalibrationStatus(); //Sends command to get status boolean calibrationComplete(); //Checks ME Cal response for byte 5, R0 - Status + void tareNow(bool zAxis=false, uint8_t rotationVectorBasis=TARE_ROTATION_VECTOR); + void saveTare(); + void clearTare(); + uint8_t getTapDetector(); uint32_t getTimeStamp(); uint16_t getStepCount(); @@ -244,6 +262,7 @@ class BNO080 void setFeatureCommand(uint8_t reportID, uint16_t timeBetweenReports, uint32_t specificConfig); void sendCommand(uint8_t command); void sendCalibrateCommand(uint8_t thingToCalibrate); + void sendTareCommand(uint8_t command, uint8_t axis=TARE_AXIS_ALL, uint8_t rotationVectorBasis=TARE_ROTATION_VECTOR); //Metadata functions int16_t getQ1(uint16_t recordID);