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