24
24
* Distributed as-is; no warranty is given.
25
25
***************************************************************/
26
26
27
- #include " ICM_20948.h" // Click here to get the library: http://librarymanager/All#SparkFun_ICM_20948_IMU
27
+ #include " ICM_20948.h" // Click here to get the library: http://librarymanager/All#SparkFun_ICM_20948_IMU
28
28
29
29
// #define USE_SPI // Uncomment this to use SPI
30
30
31
31
#define SERIAL_PORT Serial
32
32
33
- #define SPI_PORT SPI // Your desired SPI port. Used only when "USE_SPI" is defined
34
- #define CS_PIN 2 // Which pin you connect CS to. Used only when "USE_SPI" is defined
33
+ #define SPI_PORT SPI // Your desired SPI port. Used only when "USE_SPI" is defined
34
+ #define CS_PIN 2 // Which pin you connect CS to. Used only when "USE_SPI" is defined
35
35
36
- #define WIRE_PORT Wire // Your desired Wire port. Used when "USE_SPI" is not defined
37
- #define AD0_VAL 1 // The value of the last bit of the I2C address.
38
- // On the SparkFun 9DoF IMU breakout the default is 1, and when
39
- // the ADR jumper is closed the value becomes 0
36
+ #define WIRE_PORT Wire // Your desired Wire port. Used when "USE_SPI" is not defined
37
+ #define AD0_VAL 1 // The value of the last bit of the I2C address. \
38
+ // On the SparkFun 9DoF IMU breakout the default is 1, and when \
39
+ // the ADR jumper is closed the value becomes 0
40
40
41
41
#ifdef USE_SPI
42
- ICM_20948_SPI myICM; // If using SPI create an ICM_20948_SPI object
42
+ ICM_20948_SPI myICM; // If using SPI create an ICM_20948_SPI object
43
43
#else
44
- ICM_20948_I2C myICM; // Otherwise create an ICM_20948_I2C object
44
+ ICM_20948_I2C myICM; // Otherwise create an ICM_20948_I2C object
45
45
#endif
46
46
47
-
48
- void setup () {
47
+ void setup ()
48
+ {
49
49
50
50
SERIAL_PORT.begin (115200 ); // Start the serial console
51
51
SERIAL_PORT.println (F (" ICM-20948 Example" ));
@@ -61,31 +61,35 @@ void setup() {
61
61
;
62
62
63
63
#ifdef USE_SPI
64
- SPI_PORT.begin ();
64
+ SPI_PORT.begin ();
65
65
#else
66
- WIRE_PORT.begin ();
67
- WIRE_PORT.setClock (400000 );
66
+ WIRE_PORT.begin ();
67
+ WIRE_PORT.setClock (400000 );
68
68
#endif
69
69
70
70
// myICM.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial
71
71
72
72
bool initialized = false ;
73
- while ( !initialized ){
73
+ while (!initialized)
74
+ {
74
75
75
76
// Initialize the ICM-20948
76
77
// If the DMP is enabled, .begin performs a minimal startup. We need to configure the sample mode etc. manually.
77
78
#ifdef USE_SPI
78
- myICM.begin ( CS_PIN, SPI_PORT );
79
+ myICM.begin (CS_PIN, SPI_PORT);
79
80
#else
80
- myICM.begin ( WIRE_PORT, AD0_VAL );
81
+ myICM.begin (WIRE_PORT, AD0_VAL);
81
82
#endif
82
83
83
- SERIAL_PORT.print ( F (" Initialization of the sensor returned: " ) );
84
- SERIAL_PORT.println ( myICM.statusString () );
85
- if ( myICM.status != ICM_20948_Stat_Ok ){
86
- SERIAL_PORT.println ( F (" Trying again..." ) );
84
+ SERIAL_PORT.print (F (" Initialization of the sensor returned: " ));
85
+ SERIAL_PORT.println (myICM.statusString ());
86
+ if (myICM.status != ICM_20948_Stat_Ok)
87
+ {
88
+ SERIAL_PORT.println (F (" Trying again..." ));
87
89
delay (500 );
88
- }else {
90
+ }
91
+ else
92
+ {
89
93
initialized = true ;
90
94
}
91
95
}
@@ -103,12 +107,12 @@ void setup() {
103
107
104
108
// Enable accel and gyro sensors through PWR_MGMT_2
105
109
// Enable Accelerometer (all axes) and Gyroscope (all axes) by writing zero to PWR_MGMT_2
106
- success &= (myICM.setBank (0 ) == ICM_20948_Stat_Ok); // Select Bank 0
107
- uint8_t pwrMgmt2 = 0x40 ; // Set the reserved bit 6
110
+ success &= (myICM.setBank (0 ) == ICM_20948_Stat_Ok); // Select Bank 0
111
+ uint8_t pwrMgmt2 = 0x40 ; // Set the reserved bit 6
108
112
success &= (myICM.write (AGB0_REG_PWR_MGMT_2, &pwrMgmt2, 1 ) == ICM_20948_Stat_Ok); // Write one byte to the PWR_MGMT_2 register
109
113
110
114
// Configure I2C_Master/Gyro/Accel in Low Power Mode (cycled) with LP_CONFIG
111
- success &= (myICM.setSampleMode ( (ICM_20948_Internal_Mst | ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), ICM_20948_Sample_Mode_Cycled ) == ICM_20948_Stat_Ok);
115
+ success &= (myICM.setSampleMode ((ICM_20948_Internal_Mst | ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), ICM_20948_Sample_Mode_Cycled) == ICM_20948_Stat_Ok);
112
116
113
117
// Disable the FIFO
114
118
success &= (myICM.enableFIFO (false ) == ICM_20948_Stat_Ok);
@@ -118,18 +122,18 @@ void setup() {
118
122
119
123
// Set Gyro FSR (Full scale range) to 2000dps through GYRO_CONFIG_1
120
124
// Set Accel FSR (Full scale range) to 4g through ACCEL_CONFIG
121
- ICM_20948_fss_t myFSS; // This uses a "Full Scale Settings" structure that can contain values for all configurable sensors
122
- myFSS.a = gpm4; // (ICM_20948_ACCEL_CONFIG_FS_SEL_e)
123
- // gpm2
124
- // gpm4
125
- // gpm8
126
- // gpm16
127
- myFSS.g = dps2000; // (ICM_20948_GYRO_CONFIG_1_FS_SEL_e)
128
- // dps250
129
- // dps500
130
- // dps1000
131
- // dps2000
132
- success &= (myICM.setFullScale ( (ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), myFSS ) == ICM_20948_Stat_Ok);
125
+ ICM_20948_fss_t myFSS; // This uses a "Full Scale Settings" structure that can contain values for all configurable sensors
126
+ myFSS.a = gpm4; // (ICM_20948_ACCEL_CONFIG_FS_SEL_e)
127
+ // gpm2
128
+ // gpm4
129
+ // gpm8
130
+ // gpm16
131
+ myFSS.g = dps2000; // (ICM_20948_GYRO_CONFIG_1_FS_SEL_e)
132
+ // dps250
133
+ // dps500
134
+ // dps1000
135
+ // dps2000
136
+ success &= (myICM.setFullScale ((ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), myFSS) == ICM_20948_Stat_Ok);
133
137
134
138
// Enable interrupt for FIFO overflow from FIFOs through INT_ENABLE_2
135
139
// If we see this interrupt, we'll need to reset the FIFO
@@ -154,8 +158,8 @@ void setup() {
154
158
ICM_20948_smplrt_t mySmplrt;
155
159
mySmplrt.g = 4 ; // ODR is computed as follows: 1.1 kHz/(1+GYRO_SMPLRT_DIV[7:0]). 4 = 220Hz
156
160
mySmplrt.a = 4 ; // ODR is computed as follows: 1.125 kHz/(1+ACCEL_SMPLRT_DIV[11:0]). 4 = 225Hz
157
- myICM.setSampleRate ( (ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), mySmplrt );
158
-
161
+ myICM.setSampleRate ((ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), mySmplrt);
162
+
159
163
// Setup DMP start address through PRGM_STRT_ADDRH/PRGM_STRT_ADDRL
160
164
success &= (myICM.setDMPstartAddress () == ICM_20948_Stat_Ok); // Defaults to DMP_START_ADDRESS
161
165
@@ -169,12 +173,12 @@ void setup() {
169
173
success &= (myICM.setBank (0 ) == ICM_20948_Stat_Ok); // Select Bank 0
170
174
uint8_t fix = 0x48 ;
171
175
success &= (myICM.write (AGB0_REG_HW_FIX_DISABLE, &fix, 1 ) == ICM_20948_Stat_Ok);
172
-
176
+
173
177
// Set the Single FIFO Priority Select register to 0xE4
174
178
success &= (myICM.setBank (0 ) == ICM_20948_Stat_Ok); // Select Bank 0
175
179
uint8_t fifoPrio = 0xE4 ;
176
180
success &= (myICM.write (AGB0_REG_SINGLE_FIFO_PRIORITY_SEL, &fifoPrio, 1 ) == ICM_20948_Stat_Ok);
177
-
181
+
178
182
// Configure Accel scaling to DMP
179
183
// The DMP scales accel raw data internally to align 1g as 2^25
180
184
// In order to align internal accel raw data 2^25 = 1g write 0x04000000 when FSR is 4g
@@ -194,7 +198,7 @@ void setup() {
194
198
// The AK09916 produces a 16-bit signed output in the range +/-32752 corresponding to +/-4912uT. 1uT = 6.66 ADU.
195
199
// 2^30 / 6.66666 = 161061273 = 0x9999999
196
200
const unsigned char mountMultiplierZero[4 ] = {0x00 , 0x00 , 0x00 , 0x00 };
197
- const unsigned char mountMultiplierPlus[4 ] = {0x09 , 0x99 , 0x99 , 0x99 }; // Value taken from InvenSense Nucleo example
201
+ const unsigned char mountMultiplierPlus[4 ] = {0x09 , 0x99 , 0x99 , 0x99 }; // Value taken from InvenSense Nucleo example
198
202
const unsigned char mountMultiplierMinus[4 ] = {0xF6 , 0x66 , 0x66 , 0x67 }; // Value taken from InvenSense Nucleo example
199
203
success &= (myICM.writeDMPmems (CPASS_MTX_00, 4 , &mountMultiplierPlus[0 ]) == ICM_20948_Stat_Ok);
200
204
success &= (myICM.writeDMPmems (CPASS_MTX_01, 4 , &mountMultiplierZero[0 ]) == ICM_20948_Stat_Ok);
@@ -225,7 +229,7 @@ void setup() {
225
229
// 10=102.2727Hz sample rate, ... etc.
226
230
// @param[in] gyro_level 0=250 dps, 1=500 dps, 2=1000 dps, 3=2000 dps
227
231
success &= (myICM.setGyroSF (4 , 3 ) == ICM_20948_Stat_Ok); // 0 = 225Hz (see above), 3 = 2000dps (see above)
228
-
232
+
229
233
// Configure the Gyro full scale
230
234
// 2000dps : 2^28
231
235
// 1000dps : 2^27
@@ -238,17 +242,17 @@ void setup() {
238
242
// const unsigned char accelOnlyGain[4] = {0x03, 0xA4, 0x92, 0x49}; // 56Hz
239
243
const unsigned char accelOnlyGain[4 ] = {0x00 , 0xE8 , 0xBA , 0x2E }; // InvenSense Nucleo example uses 225Hz
240
244
success &= (myICM.writeDMPmems (ACCEL_ONLY_GAIN, 4 , &accelOnlyGain[0 ]) == ICM_20948_Stat_Ok);
241
-
245
+
242
246
// Configure the Accel Alpha Var: 1026019965 (225Hz) 977872018 (112Hz) 882002213 (56Hz)
243
247
// const unsigned char accelAlphaVar[4] = {0x34, 0x92, 0x49, 0x25}; // 56Hz
244
248
const unsigned char accelAlphaVar[4 ] = {0x3D , 0x27 , 0xD2 , 0x7D }; // 225Hz
245
249
success &= (myICM.writeDMPmems (ACCEL_ALPHA_VAR, 4 , &accelAlphaVar[0 ]) == ICM_20948_Stat_Ok);
246
-
250
+
247
251
// Configure the Accel A Var: 47721859 (225Hz) 95869806 (112Hz) 191739611 (56Hz)
248
252
// const unsigned char accelAVar[4] = {0x0B, 0x6D, 0xB6, 0xDB}; // 56Hz
249
253
const unsigned char accelAVar[4 ] = {0x02 , 0xD8 , 0x2D , 0x83 }; // 225Hz
250
254
success &= (myICM.writeDMPmems (ACCEL_A_VAR, 4 , &accelAVar[0 ]) == ICM_20948_Stat_Ok);
251
-
255
+
252
256
// Configure the Accel Cal Rate
253
257
const unsigned char accelCalRate[4 ] = {0x00 , 0x00 }; // Value taken from InvenSense Nucleo example
254
258
success &= (myICM.writeDMPmems (ACCEL_CAL_RATE, 2 , &accelCalRate[0 ]) == ICM_20948_Stat_Ok);
@@ -257,7 +261,7 @@ void setup() {
257
261
// in startupMagnetometer. We need to set CPASS_TIME_BUFFER to 100 too.
258
262
const unsigned char compassRate[2 ] = {0x00 , 0x64 }; // 100Hz
259
263
success &= (myICM.writeDMPmems (CPASS_TIME_BUFFER, 2 , &compassRate[0 ]) == ICM_20948_Stat_Ok);
260
-
264
+
261
265
// Enable DMP interrupt
262
266
// This would be the most efficient way of getting the DMP data, instead of polling the FIFO
263
267
// success &= (myICM.intEnableDMP(true) == ICM_20948_Stat_Ok);
@@ -310,7 +314,7 @@ void setup() {
310
314
success &= (myICM.resetFIFO () == ICM_20948_Stat_Ok);
311
315
312
316
// Check success
313
- if ( success )
317
+ if ( success)
314
318
{
315
319
SERIAL_PORT.println (F (" DMP enabled!" ));
316
320
}
@@ -335,15 +339,15 @@ void loop()
335
339
icm_20948_DMP_data_t data;
336
340
myICM.readDMPdataFromFIFO (&data);
337
341
338
- if (( myICM.status == ICM_20948_Stat_Ok ) || ( myICM.status == ICM_20948_Stat_FIFOMoreDataAvail )) // Was valid data available?
342
+ if (( myICM.status == ICM_20948_Stat_Ok) || (myICM.status == ICM_20948_Stat_FIFOMoreDataAvail)) // Was valid data available?
339
343
{
340
344
// SERIAL_PORT.print(F("Received data! Header: 0x")); // Print the header in HEX so we can see what data is arriving in the FIFO
341
345
// if ( data.header < 0x1000) SERIAL_PORT.print( "0" ); // Pad the zeros
342
346
// if ( data.header < 0x100) SERIAL_PORT.print( "0" );
343
347
// if ( data.header < 0x10) SERIAL_PORT.print( "0" );
344
348
// SERIAL_PORT.println( data.header, HEX );
345
349
346
- if ( (data.header & DMP_header_bitmap_Quat6) > 0 ) // Check for GRV data (Quat6)
350
+ if ((data.header & DMP_header_bitmap_Quat6) > 0 ) // Check for GRV data (Quat6)
347
351
{
348
352
// Q0 value is computed from this equation: Q0^2 + Q1^2 + Q2^2 + Q3^2 = 1.
349
353
// In case of drift, the sum will not add to 1, therefore, quaternion data need to be corrected with right bias values.
@@ -355,7 +359,7 @@ void loop()
355
359
double q1 = ((double )data.Quat6 .Data .Q1 ) / 1073741824.0 ; // Convert to double. Divide by 2^30
356
360
double q2 = ((double )data.Quat6 .Data .Q2 ) / 1073741824.0 ; // Convert to double. Divide by 2^30
357
361
double q3 = ((double )data.Quat6 .Data .Q3 ) / 1073741824.0 ; // Convert to double. Divide by 2^30
358
-
362
+
359
363
SERIAL_PORT.print (F (" Q1:" ));
360
364
SERIAL_PORT.print (q1, 3 );
361
365
SERIAL_PORT.print (F (" Q2:" ));
@@ -364,12 +368,12 @@ void loop()
364
368
SERIAL_PORT.println (q3, 3 );
365
369
}
366
370
367
- if ( (data.header & DMP_header_bitmap_Accel) > 0 ) // Check for Accel
371
+ if ((data.header & DMP_header_bitmap_Accel) > 0 ) // Check for Accel
368
372
{
369
373
float acc_x = (float )data.Raw_Accel .Data .X ; // Extract the raw accelerometer data
370
- float acc_y = (float )data.Raw_Accel .Data .Y ;
371
- float acc_z = (float )data.Raw_Accel .Data .Z ;
372
-
374
+ float acc_y = (float )data.Raw_Accel .Data .Y ;
375
+ float acc_z = (float )data.Raw_Accel .Data .Z ;
376
+
373
377
SERIAL_PORT.print (F (" Accel: X:" ));
374
378
SERIAL_PORT.print (acc_x);
375
379
SERIAL_PORT.print (F (" Y:" ));
@@ -378,37 +382,36 @@ void loop()
378
382
SERIAL_PORT.println (acc_z);
379
383
}
380
384
381
- // if ( (data.header & DMP_header_bitmap_Gyro) > 0 ) // Check for Gyro
382
- // {
383
- // float x = (float)data.Raw_Gyro.Data.X; // Extract the raw gyro data
384
- // float y = (float)data.Raw_Gyro.Data.Y;
385
- // float z = (float)data.Raw_Gyro.Data.Z;
386
- //
387
- // SERIAL_PORT.print(F("Gyro: X:"));
388
- // SERIAL_PORT.print(x);
389
- // SERIAL_PORT.print(F(" Y:"));
390
- // SERIAL_PORT.print(y);
391
- // SERIAL_PORT.print(F(" Z:"));
392
- // SERIAL_PORT.println(z);
393
- // }
394
- //
395
- // if ( (data.header & DMP_header_bitmap_Compass) > 0 ) // Check for Compass
396
- // {
397
- // float x = (float)data.Compass.Data.X; // Extract the compass data
398
- // float y = (float)data.Compass.Data.Y;
399
- // float z = (float)data.Compass.Data.Z;
400
- //
401
- // SERIAL_PORT.print(F("Compass: X:"));
402
- // SERIAL_PORT.print(x);
403
- // SERIAL_PORT.print(F(" Y:"));
404
- // SERIAL_PORT.print(y);
405
- // SERIAL_PORT.print(F(" Z:"));
406
- // SERIAL_PORT.println(z);
407
- // }
408
-
385
+ // if ( (data.header & DMP_header_bitmap_Gyro) > 0 ) // Check for Gyro
386
+ // {
387
+ // float x = (float)data.Raw_Gyro.Data.X; // Extract the raw gyro data
388
+ // float y = (float)data.Raw_Gyro.Data.Y;
389
+ // float z = (float)data.Raw_Gyro.Data.Z;
390
+ //
391
+ // SERIAL_PORT.print(F("Gyro: X:"));
392
+ // SERIAL_PORT.print(x);
393
+ // SERIAL_PORT.print(F(" Y:"));
394
+ // SERIAL_PORT.print(y);
395
+ // SERIAL_PORT.print(F(" Z:"));
396
+ // SERIAL_PORT.println(z);
397
+ // }
398
+ //
399
+ // if ( (data.header & DMP_header_bitmap_Compass) > 0 ) // Check for Compass
400
+ // {
401
+ // float x = (float)data.Compass.Data.X; // Extract the compass data
402
+ // float y = (float)data.Compass.Data.Y;
403
+ // float z = (float)data.Compass.Data.Z;
404
+ //
405
+ // SERIAL_PORT.print(F("Compass: X:"));
406
+ // SERIAL_PORT.print(x);
407
+ // SERIAL_PORT.print(F(" Y:"));
408
+ // SERIAL_PORT.print(y);
409
+ // SERIAL_PORT.print(F(" Z:"));
410
+ // SERIAL_PORT.println(z);
411
+ // }
409
412
}
410
413
411
- if ( myICM.status != ICM_20948_Stat_FIFOMoreDataAvail ) // If more data is available then we should read it right away - and not delay
414
+ if (myICM.status != ICM_20948_Stat_FIFOMoreDataAvail) // If more data is available then we should read it right away - and not delay
412
415
{
413
416
delay (1 ); // Keep this short!
414
417
}
0 commit comments