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 < Wire.h>
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+ }
0 commit comments