sparkfun / sparkfun_icm-20948_arduinolibrary Goto Github PK
View Code? Open in Web Editor NEWArduino support for ICM_20948 w/ portable C backbone
License: Other
Arduino support for ICM_20948 w/ portable C backbone
License: Other
I'm still working on the MEGA to get access to the DMP, but in the meanwhile, I'm also interested in having a working orientation sensor using an Arduino Uno. I'm using the (MadgwickAHRS)[https://github.com/arduino-libraries/MadgwickAHRS] to perform the sensor fusion. I'm having some issues where the orientation drifts over time.
What can I do to remedy this?
So far this is my code:
// This is meant to be nothing more than a sketch that dumps data on the serial port
// for the python application to show/visualize.
//
// For the actual application:
// - This should use the DMP on the chip for Sensor fusion instead of the Madgwick code
// - Probably can't use Arduino then anymore, since the Sparkfun code breaks the Memory limits of the Arduino UNO chip
// - Gyroscope sensitivity probably needs to be adjusted to be a little less sensitive (giving a greater DPS range)
// - Should properly use the interrupt pin
//
// Communication protocol: This print strings on the Serial port, at the rate of 115200 baud; it never reads data
// It might print out status messages like "waiting for data"
// Actual orientation data will follow the format:
//
// HPR <heading/yaw deg> <pitch deg> <roll deg>
//
// For example:
//
// HPR 5.5 -10.07773 0.22000023
//
#include <Arduino.h>
#include <Wire.h>
#include <ICM_20948.h>
#include "MadgwickAHRS.h"
#define SERIAL_BAUD_RATE 115200
#define I2C_RATE 400000
#define IMU_TIMEOUT_MS 500 // When there was a failure in talking to the IMU (or no data ready), how many milliseconds should we wait?
#define IMU_DATA_READING_WAIT_MS 25 // How many milliseconds to wait before attempting the next data reading
#define IMU_FUSION_FREQUENCY (1000.0f / float(IMU_DATA_READING_WAIT_MS)) // The sensor fusion algorithm needs to know how often the IMU is being read from
#define SERIAL_PRECISION 12 // How many digits of the float to print to Serial
// TODO research this better
#define AD0_VAL 1 // The value of the last bit of the I2C address.
// On the SparkFun 9DoF IMU breakout the default is 1, and when
// the ADR jumper is closed the value becomes 0
// Using I2C to connect to the imu
ICM_20948_I2C imu;
// For orientation calculation
Madgwick filter;
float heading, pitch, roll; // The orientation
void setup() {
// Setup communications
Serial.begin(SERIAL_BAUD_RATE); // To computer
Wire.begin(); // To IMU
Wire.setClock(I2C_RATE);
// imu.enableDebugging();
// Try to enable the IMU
bool connected = false;
while (!connected) {
imu.begin(Wire, AD0_VAL);
// Print status to serial
Serial.print("Init connection to ICM 20948: ");
Serial.println(imu.statusString());
// If it didn't work, try again shortly
if (imu.status != ICM_20948_Stat_Ok) {
Serial.println("Try again in 500 ms");
delay(IMU_TIMEOUT_MS);
} else
connected = true;
}
Serial.println("Connected to ICM 20948");
// Setup filter
filter.begin(IMU_FUSION_FREQUENCY);
}
void loop() {
if (imu.dataReady()) {
// Some data is ready
imu.getAGMT(); // Retrieves data
// Update the sensor fusion state
filter.update(
imu.gyrX(), imu.gyrY(), imu.gyrZ(), // These units might be in degrees and not radiasn
imu.accX(), imu.accY(), imu.accZ(),
imu.magX(), imu.magY(), imu.magZ()
);
// Read data
heading = filter.getYaw();
pitch = filter.getPitch();
roll = filter.getRoll();
// Send Orientation data to the PC
Serial.print("HPR "); // HPR = Heading, Pitch, Roll
Serial.print(heading, SERIAL_PRECISION);
Serial.print(" ");
Serial.print(pitch, SERIAL_PRECISION);
Serial.print(" ");
Serial.print(roll, SERIAL_PRECISION);
Serial.println(""); // End the line reading
// Wait a little before the next reading
delay(IMU_DATA_READING_WAIT_MS);
} else {
// Nothing, pause for a moment
Serial.println("Waiting for data...");
delay(IMU_TIMEOUT_MS);
}
}
I made a 3D model of the breakout board and a Python (w/ Panda3D) visualization:
The parts where the movement jerks fast is actually where I move the board. The parts where the rotation is linear is actually drift. I've before had the board completely stationary but then seen it drift slowly at the rate of about 2 deg / second, for minutes on end. I really want to eliminate this drift when using an Uno
Hi,
I'm trying to use the ICM20948 for both orientation and acceleration sensors.
With your Example7_DMP_Quat6_EulerAngles file it's easy to get the corrected orientation data.
But for the acceleration it seems more difficule.
I tryed to add the sensor linear acceleration mode for the DMP:
success &= (myICM.enableDMPSensor(INV_ICM20948_SENSOR_GAME_ROTATION_VECTOR) == ICM_20948_Stat_Ok);
// Enable any additional sensors / features
success &= (myICM.enableDMPSensor(INV_ICM20948_SENSOR_LINEAR_ACCELERATION) == ICM_20948_Stat_Ok);
The result is that the DMP data contains now raw acceleration : data.Raw_Accel.Data
these accelerations are not corrected by the orientation of the IMU, then I can't use it directly (and I don't know how to use it !)
it seems that this configuration provide the same result as
success &= (myICM.enableDMPSensor(INV_ICM20948_SENSOR_RAW_ACCELEROMETER) == ICM_20948_Stat_Ok);
Is there a way to have the x, y, z acceleration (without the 1g gravity and calibrated ) to be able to know if my sensor is moving left, right, up or down ?
thanks.
Compile generates an error when SPI_INTERFACES_COUNT 0
Custom variants.h has no SPI ports defined.
Edit variants.h:
// SPI Interfaces
// --------------
#define SPI_INTERFACES_COUNT 0
Code compiles with SPI disabled
Sketch does not compile.
error: 'SPI' was not declared in this scope
ICM_20948_Status_e begin( uint8_t csPin, SPIClass &spiPort = SPI );
Im making a project that automatically points a camera to a star, moon, planet, galaxy etc.
It gets the coordinates of the desired star or moon etc from stellarium (open source astronomy program), and then its supposed to use the ICM-29048 (attached to the camera) and little motors to move the camera until it points to the proper coordinates using positional feedback from the ICM-20948.
I was willing to pay someone to help me get that working using Arduino since i dont have time to do it all myself.
Please contact me at [email protected] if you are interested, and let me know your price.
For the Example6_DMP_Quat9_Orientation sketch, when calculating Q0 (line 376) you do:
q0 = sqrt( 1.0 - ((q1 * q1) + (q2 * q2) + (q3 * q3)));
Isn't this incorrect because q0 can be positive or negative? The equation above always makes q0 positive, which is incorrect.
I am thinking of how to solve this issue but my understand of quaternions is entry level in terms of finding Q0 from the DMP or through math with XYZ while getting the correct sign. Is there a way to get Q0 directly from the DMP like we do for Q1, Q2, and Q3?
Thank you,
Zed
I can't find/understand the way, the value of the agmt are set.
Currently I am starting the process of re purposing your library for a Raspberry 4. I am already able to get readings from accY(); and the others, now in testing the readouts they are either nonsensical or unchanging. So i am trying to understand where the values are actually "created".
Thank you for your patience.
PS.: I am only aware of your library, you don't know randomly of a raspberry library for the SparkFun_ICM-20948?
Hello,
we really appreciate the simplification in this library over the original drivers from Invensense.
The hope was to use the DMP for 9-axis sensor fusion with Orientation output referenced to magnetic north.
Using example 6 (Quat9_Orientation) and 9 (MultipleSensors) as a basis, we get stable quaternion output. However, the heading always starts out at zero, and changes in the magnetic field do not seem to matter at all. Digging into this, it is quick to see that there are issues reading the magnetic sensor. If true, this might also explain some other issues posted here.
Steps to reproduce:
What we would expect is to receive valid magnetometer readings at 55Hz.
The magnetometer was configured to 100Hz continuous mode previously.
I do not know how the sample rate for the external I2C slave (magnetometer) is configured in the DMP.
The actual output is the following:
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x -677.00 y -256.00 z -103.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x -661.00 y -256.00 z -107.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x -665.00 y -256.00 z -111.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
Compass: x 32767.00 y 32767.00 z 32767.00
There are occasional valid readings in the output, but most values are invalid.
Readings that are not 32767 change with the sensor orientation and seem to be the actual magnetic field.
No matter what other options I changed, the DMP keeps posting mostly invalid magnetometer data into the FIFO.
If this is the same data the DMP uses for 9-axis fusion, it is clear why magnetometer is not used in the Quat9 result.
So far, I did not manage to find a different library to cross-reference a possible configuration error.
Please advise if you can reproduce this behaviour.
Thank you!
Unable to compile for Arduino Nano 33 BLE
Use an Arduino Nano 33 BLE and attempt to compile and upload the Basic example sketch provided with this library.
Should successfully compile the example sketch and upload it to the device
Arduino: 1.8.13 (Windows Store 1.8.42.0) (Windows 10), Board: "Arduino Nano 33 BLE"
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\arduino-builder -dump-prefs -logger=machine -hardware C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware -hardware C:\Users\Aaron\Documents\ArduinoData\packages -tools C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\tools-builder -tools C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\tools\avr -tools C:\Users\Aaron\Documents\ArduinoData\packages -built-in-libraries C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries -libraries C:\Users\Aaron\Documents\Arduino\libraries -fqbn=arduino:mbed:nano33ble -vid-pid=2341_805A -ide-version=10813 -build-path C:\Users\Aaron\AppData\Local\Temp\arduino_build_589287 -warnings=none -build-cache C:\Users\Aaron\AppData\Local\Temp\arduino_cache_73247 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arm-none-eabi-gcc.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4 -prefs=runtime.tools.arm-none-eabi-gcc-7-2017q4.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4 -prefs=runtime.tools.openocd.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\openocd\0.10.0-arduino13 -prefs=runtime.tools.openocd-0.10.0-arduino13.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\openocd\0.10.0-arduino13 -prefs=runtime.tools.dfu-util.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\dfu-util\0.9.0-arduino2 -prefs=runtime.tools.dfu-util-0.9.0-arduino2.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\dfu-util\0.9.0-arduino2 -prefs=runtime.tools.bossac.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\bossac\1.9.1-arduino2 -prefs=runtime.tools.bossac-1.9.1-arduino2.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\bossac\1.9.1-arduino2 -verbose C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\examples\Arduino\Example1_Basics\Example1_Basics.ino
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\arduino-builder -compile -logger=machine -hardware C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware -hardware C:\Users\Aaron\Documents\ArduinoData\packages -tools C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\tools-builder -tools C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\hardware\tools\avr -tools C:\Users\Aaron\Documents\ArduinoData\packages -built-in-libraries C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\libraries -libraries C:\Users\Aaron\Documents\Arduino\libraries -fqbn=arduino:mbed:nano33ble -vid-pid=2341_805A -ide-version=10813 -build-path C:\Users\Aaron\AppData\Local\Temp\arduino_build_589287 -warnings=none -build-cache C:\Users\Aaron\AppData\Local\Temp\arduino_cache_73247 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arm-none-eabi-gcc.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4 -prefs=runtime.tools.arm-none-eabi-gcc-7-2017q4.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\arm-none-eabi-gcc\7-2017q4 -prefs=runtime.tools.openocd.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\openocd\0.10.0-arduino13 -prefs=runtime.tools.openocd-0.10.0-arduino13.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\openocd\0.10.0-arduino13 -prefs=runtime.tools.dfu-util.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\dfu-util\0.9.0-arduino2 -prefs=runtime.tools.dfu-util-0.9.0-arduino2.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\dfu-util\0.9.0-arduino2 -prefs=runtime.tools.bossac.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\bossac\1.9.1-arduino2 -prefs=runtime.tools.bossac-1.9.1-arduino2.path=C:\Users\Aaron\Documents\ArduinoData\packages\arduino\tools\bossac\1.9.1-arduino2 -verbose C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\examples\Arduino\Example1_Basics\Example1_Basics.ino
Using board 'nano33ble' from platform in folder: C:\Users\Aaron\Documents\ArduinoData\packages\arduino\hardware\mbed\1.3.1
Using core 'arduino' from platform in folder: C:\Users\Aaron\Documents\ArduinoData\packages\arduino\hardware\mbed\1.3.1
Detecting libraries used...
"C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -c -w -g -Os -nostdlib "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/defines.txt" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/cxxflags.txt" -DARDUINO_ARCH_NRF52840 -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -w -x c++ -E -CC -DARDUINO=10813 -DARDUINO_ARDUINO_NANO33BLE -DARDUINO_ARCH_MBED -DARDUINO_LIBRARY_DISCOVERY_PHASE=0 "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino/api/deprecated" "-iprefixC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/includes.txt" "C:\\Users\\Aaron\\AppData\\Local\\Temp\\arduino_build_589287\\sketch\\Example1_Basics.ino.cpp" -o nul -DARDUINO_LIB_DISCOVERY_PHASE
Alternatives for ICM_20948.h: [[email protected]]
ResolveLibrary(ICM_20948.h)
-> candidates: [[email protected]]
"C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -c -w -g -Os -nostdlib "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/defines.txt" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/cxxflags.txt" -DARDUINO_ARCH_NRF52840 -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -w -x c++ -E -CC -DARDUINO=10813 -DARDUINO_ARDUINO_NANO33BLE -DARDUINO_ARCH_MBED -DARDUINO_LIBRARY_DISCOVERY_PHASE=0 "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE" "-IC:\\Users\\Aaron\\Documents\\Arduino\\libraries\\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\\src" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino/api/deprecated" "-iprefixC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/includes.txt" "C:\\Users\\Aaron\\AppData\\Local\\Temp\\arduino_build_589287\\sketch\\Example1_Basics.ino.cpp" -o nul -DARDUINO_LIB_DISCOVERY_PHASE
Alternatives for Wire.h: [Wire]
ResolveLibrary(Wire.h)
-> candidates: [Wire]
"C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -c -w -g -Os -nostdlib "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/defines.txt" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/cxxflags.txt" -DARDUINO_ARCH_NRF52840 -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -w -x c++ -E -CC -DARDUINO=10813 -DARDUINO_ARDUINO_NANO33BLE -DARDUINO_ARCH_MBED -DARDUINO_LIBRARY_DISCOVERY_PHASE=0 "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE" "-IC:\\Users\\Aaron\\Documents\\Arduino\\libraries\\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\\src" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\Wire" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino/api/deprecated" "-iprefixC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/includes.txt" "C:\\Users\\Aaron\\AppData\\Local\\Temp\\arduino_build_589287\\sketch\\Example1_Basics.ino.cpp" -o nul -DARDUINO_LIB_DISCOVERY_PHASE
Alternatives for SPI.h: [SPI]
ResolveLibrary(SPI.h)
-> candidates: [SPI]
"C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -c -w -g -Os -nostdlib "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/defines.txt" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/cxxflags.txt" -DARDUINO_ARCH_NRF52840 -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -w -x c++ -E -CC -DARDUINO=10813 -DARDUINO_ARDUINO_NANO33BLE -DARDUINO_ARCH_MBED -DARDUINO_LIBRARY_DISCOVERY_PHASE=0 "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE" "-IC:\\Users\\Aaron\\Documents\\Arduino\\libraries\\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\\src" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\Wire" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\SPI" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino/api/deprecated" "-iprefixC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/includes.txt" "C:\\Users\\Aaron\\AppData\\Local\\Temp\\arduino_build_589287\\sketch\\Example1_Basics.ino.cpp" -o nul -DARDUINO_LIB_DISCOVERY_PHASE
"C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -c -w -g -Os -nostdlib "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/defines.txt" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/cxxflags.txt" -DARDUINO_ARCH_NRF52840 -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -w -x c++ -E -CC -DARDUINO=10813 -DARDUINO_ARDUINO_NANO33BLE -DARDUINO_ARCH_MBED -DARDUINO_LIBRARY_DISCOVERY_PHASE=0 "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE" "-IC:\\Users\\Aaron\\Documents\\Arduino\\libraries\\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\\src" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\Wire" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\SPI" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino/api/deprecated" "-iprefixC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/includes.txt" "C:\\Users\\Aaron\\Documents\\Arduino\\libraries\\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\\src\\ICM_20948.cpp" -o nul -DARDUINO_LIB_DISCOVERY_PHASE
"C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -c -w -g -Os -nostdlib "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/defines.txt" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/cxxflags.txt" -DARDUINO_ARCH_NRF52840 -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -w -x c++ -E -CC -DARDUINO=10813 -DARDUINO_ARDUINO_NANO33BLE -DARDUINO_ARCH_MBED -DARDUINO_LIBRARY_DISCOVERY_PHASE=0 "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE" "-IC:\\Users\\Aaron\\Documents\\Arduino\\libraries\\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\\src" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\Wire" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\SPI" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino/api/deprecated" "-iprefixC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/includes.txt" "C:\\Users\\Aaron\\Documents\\Arduino\\libraries\\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\\src\\util\\ICM_20948_C.c" -o nul -DARDUINO_LIB_DISCOVERY_PHASE
"C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -c -w -g -Os -nostdlib "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/defines.txt" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/cxxflags.txt" -DARDUINO_ARCH_NRF52840 -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -w -x c++ -E -CC -DARDUINO=10813 -DARDUINO_ARDUINO_NANO33BLE -DARDUINO_ARCH_MBED -DARDUINO_LIBRARY_DISCOVERY_PHASE=0 "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE" "-IC:\\Users\\Aaron\\Documents\\Arduino\\libraries\\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\\src" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\Wire" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\SPI" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino/api/deprecated" "-iprefixC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/includes.txt" "C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\Wire\\Wire.cpp" -o nul -DARDUINO_LIB_DISCOVERY_PHASE
"C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -c -w -g -Os -nostdlib "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/defines.txt" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/cxxflags.txt" -DARDUINO_ARCH_NRF52840 -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -w -x c++ -E -CC -DARDUINO=10813 -DARDUINO_ARDUINO_NANO33BLE -DARDUINO_ARCH_MBED -DARDUINO_LIBRARY_DISCOVERY_PHASE=0 "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE" "-IC:\\Users\\Aaron\\Documents\\Arduino\\libraries\\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\\src" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\Wire" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\SPI" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino/api/deprecated" "-iprefixC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/includes.txt" "C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\SPI\\SPI.cpp" -o nul -DARDUINO_LIB_DISCOVERY_PHASE
Generating function prototypes...
"C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -c -w -g -Os -nostdlib "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/defines.txt" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/cxxflags.txt" -DARDUINO_ARCH_NRF52840 -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -w -x c++ -E -CC -DARDUINO=10813 -DARDUINO_ARDUINO_NANO33BLE -DARDUINO_ARCH_MBED -DARDUINO_LIBRARY_DISCOVERY_PHASE=0 "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE" "-IC:\\Users\\Aaron\\Documents\\Arduino\\libraries\\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\\src" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\Wire" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\SPI" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino/api/deprecated" "-iprefixC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/includes.txt" "C:\\Users\\Aaron\\AppData\\Local\\Temp\\arduino_build_589287\\sketch\\Example1_Basics.ino.cpp" -o "C:\\Users\\Aaron\\AppData\\Local\\Temp\\arduino_build_589287\\preproc\\ctags_target_for_gcc_minus_e.cpp" -DARDUINO_LIB_DISCOVERY_PHASE
"C:\\Program Files\\WindowsApps\\ArduinoLLC.ArduinoIDE_1.8.42.0_x86__mdqgnx93n4wtt\\tools-builder\\ctags\\5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "C:\\Users\\Aaron\\AppData\\Local\\Temp\\arduino_build_589287\\preproc\\ctags_target_for_gcc_minus_e.cpp"
Compiling sketch...
"C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\tools\\arm-none-eabi-gcc\\7-2017q4/bin/arm-none-eabi-g++" -c -w -g -Os -nostdlib "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/defines.txt" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/cxxflags.txt" -DARDUINO_ARCH_NRF52840 -MMD -mcpu=cortex-m4 -mfloat-abi=softfp -mfpu=fpv4-sp-d16 -DARDUINO=10813 -DARDUINO_ARDUINO_NANO33BLE -DARDUINO_ARCH_MBED -DARDUINO_LIBRARY_DISCOVERY_PHASE=0 "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE" "-IC:\\Users\\Aaron\\Documents\\Arduino\\libraries\\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\\src" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\Wire" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\libraries\\SPI" "-IC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino/api/deprecated" "-iprefixC:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\cores\\arduino" "@C:\\Users\\Aaron\\Documents\\ArduinoData\\packages\\arduino\\hardware\\mbed\\1.3.1\\variants\\ARDUINO_NANO33BLE/includes.txt" "C:\\Users\\Aaron\\AppData\\Local\\Temp\\arduino_build_589287\\sketch\\Example1_Basics.ino.cpp" -o "C:\\Users\\Aaron\\AppData\\Local\\Temp\\arduino_build_589287\\sketch\\Example1_Basics.ino.cpp.o"
In file included from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\examples\Arduino\Example1_Basics\Example1_Basics.ino:13:0:
C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:122:7: error: using typedef-name 'TwoWire' after 'class'
class TwoWire;
^~~~~~~
In file included from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:14:0,
from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\examples\Arduino\Example1_Basics\Example1_Basics.ino:13:
C:\Users\Aaron\Documents\ArduinoData\packages\arduino\hardware\mbed\1.3.1\libraries\Wire/Wire.h:87:26: note: 'TwoWire' has a previous declaration here
typedef arduino::MbedI2C TwoWire;
^~~~~~~
In file included from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\examples\Arduino\Example1_Basics\Example1_Basics.ino:13:0:
C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:148:8: error: reference to 'SPIClass' is ambiguous
extern SPIClass SPI;
^~~~~~~~
C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:147:7: note: candidates are: class SPIClass
class SPIClass;
^~~~~~~~
In file included from C:\Users\Aaron\Documents\ArduinoData\packages\arduino\hardware\mbed\1.3.1\libraries\SPI/SPI.h:22:0,
from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:15,
from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\examples\Arduino\Example1_Basics\Example1_Basics.ino:13:
C:\Users\Aaron\Documents\ArduinoData\packages\arduino\hardware\mbed\1.3.1\cores\arduino/api/HardwareSPI.h:128:21: note: typedef class arduino::HardwareSPI arduino::SPIClass
typedef HardwareSPI SPIClass;
^~~~~~~~
In file included from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\examples\Arduino\Example1_Basics\Example1_Basics.ino:13:0:
C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:155:5: error: reference to 'SPIClass' is ambiguous
SPIClass *_spi;
^~~~~~~~
C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:147:7: note: candidates are: class SPIClass
class SPIClass;
^~~~~~~~
In file included from C:\Users\Aaron\Documents\ArduinoData\packages\arduino\hardware\mbed\1.3.1\libraries\SPI/SPI.h:22:0,
from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:15,
from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\examples\Arduino\Example1_Basics\Example1_Basics.ino:13:
C:\Users\Aaron\Documents\ArduinoData\packages\arduino\hardware\mbed\1.3.1\cores\arduino/api/HardwareSPI.h:128:21: note: typedef class arduino::HardwareSPI arduino::SPIClass
typedef HardwareSPI SPIClass;
^~~~~~~~
In file included from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\examples\Arduino\Example1_Basics\Example1_Basics.ino:13:0:
C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:162:45: error: reference to 'SPIClass' is ambiguous
ICM_20948_Status_e begin(uint8_t csPin, SPIClass &spiPort = SPI, uint32_t SPIFreq = ICM_20948_SPI_DEFAULT_FREQ);
^~~~~~~~
C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:147:7: note: candidates are: class SPIClass
class SPIClass;
^~~~~~~~
In file included from C:\Users\Aaron\Documents\ArduinoData\packages\arduino\hardware\mbed\1.3.1\libraries\SPI/SPI.h:22:0,
from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:15,
from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\examples\Arduino\Example1_Basics\Example1_Basics.ino:13:
C:\Users\Aaron\Documents\ArduinoData\packages\arduino\hardware\mbed\1.3.1\cores\arduino/api/HardwareSPI.h:128:21: note: typedef class arduino::HardwareSPI arduino::SPIClass
typedef HardwareSPI SPIClass;
^~~~~~~~
In file included from C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\examples\Arduino\Example1_Basics\Example1_Basics.ino:13:0:
C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:162:45: error: 'SPIClass' has not been declared
ICM_20948_Status_e begin(uint8_t csPin, SPIClass &spiPort = SPI, uint32_t SPIFreq = ICM_20948_SPI_DEFAULT_FREQ);
^~~~~~~~
C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library\src/ICM_20948.h:162:65: error: could not convert 'SPI' from 'arduino::MbedSPI' to 'int&'
ICM_20948_Status_e begin(uint8_t csPin, SPIClass &spiPort = SPI, uint32_t SPIFreq = ICM_20948_SPI_DEFAULT_FREQ);
^~~
Using library SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library at version 1.1.2 in folder: C:\Users\Aaron\Documents\Arduino\libraries\SparkFun_9DoF_IMU_Breakout_-_ICM_20948_-_Arduino_Library
Using library Wire in folder: C:\Users\Aaron\Documents\ArduinoData\packages\arduino\hardware\mbed\1.3.1\libraries\Wire (legacy)
Using library SPI in folder: C:\Users\Aaron\Documents\ArduinoData\packages\arduino\hardware\mbed\1.3.1\libraries\SPI (legacy)
exit status 1
Error compiling for board Arduino Nano 33 BLE.
#define INV_NEEDS_ACCEL_MASK ((1L<<1)| (1L<<3)| (1L<<9)|(1L<<10)|(1L<<11)| (1L<<15)| (1L<<17)|(1L<<18)|(1L<<19)|(1L<<20)|(1<<23)| (1<<25)| (1<<29)|(1<<30)|(1<<31))
L suffix lost for some items, that cause compile time warnings
SparkFun_ICM-20948_ArduinoLibrary/src/util/ICM_20948_C.h
Lines 217 to 219 in c5a699b
Appears to have been duplicated by whitespace fixes in ed6edf6.
I want to calculate gravity values at rest horizontal position. Ideally for 2g sensitivity , it should give me raw values around 16500 but it gives me values around 14000 for positive z axis and 17000 for negative z axis. Which eventually makes calculation 8.8m/s2 and 10m/s2 respectively. What should be reason for such higher and lower raw values ? What is solution to this problem ?
How can I read calibration value of DMP and set it back later? Is there an interface for this in the library?
I'm sorry if this is not the best place to make this question, but I wasn't sure where else to do it on.
Im trying to understand and validate the raw data I'm getting from the DMP (acc, gyro and mag) and also understand how one gets from that raw data to the processed data: quaternion.
So questions like:
What sensor data is calibrated
How is the sensor fusion done in the DMP to calculate the 9DoF quaternions?
All of this, of course, considering the ICM 20948. I've searched the dataset but I found nothing to clarify my questions...
Hi,
I tried to change the full scale settings of the accelerometer in the arduino Example2_Advanced code and it did not seem to work.
I am using ICM20948 with SPI communication.
myFSS.a = gpm8; // (ICM_20948_ACCEL_CONFIG_FS_SEL_e)
// gpm2
// gpm4
// gpm8
// gpm16
This is all I need to do to change the settings to +-8G, is that correct?
(In the example code this was myFSS.a = gpm2);
The output raw values for the vertically pointed axis (z-axis in my case) shows +16384 value for all the 4 settings (gpm2, gpm4, gmp8 and gmp16).
If the 4G, 8G, 16G settings have been configured successfully, then the expected output for z-axis raw values is:
approx 8192 for +-4G setting
approx 4096 for +-8G setting
approx 2048 for +-16G setting
Have you observed the same problem or am I doing something wrong here?
I understand that this chip will output the game rotation vectors as quaternions. Is it possible to extract them using this library? I looked through the examples, but did not see any mention of quaternions.
I cannot receive SPI data from multiple ICM-20948 sensors. I have four ICM-20948 sensors soldered to a custom PCB which connects to an Arduino Nano. The PCB layout is nearly identical to the Adafruit TDK InvenSense ICM-20948 9-DoF IMU board. Each sensor has its own CS line.
I am using the Example1_Basics.ino code, but I include three additional ICM_20948 objects and CS lines:
`#include "ICM_20948.h" // Click here to get the library: http://librarymanager/All#SparkFun_ICM_20948_IMU
#define USE_SPI
#define SERIAL_PORT Serial
#define SPI_PORT SPI // Your desired SPI port. Used only when "USE_SPI" is defined
#define CS_PIN 10 // Which pin you connect CS to. Used only when "USE_SPI" is defined
#define CS_PIN_orange 9
#define CS_PIN_white 8
#define CS_PIN_gray 7
#define WIRE_PORT Wire // Your desired Wire port. Used when "USE_SPI" is not defined
#define AD0_VAL 1 // The value of the last bit of the I2C address.
// On the SparkFun 9DoF IMU breakout the default is 1, and when
// the ADR jumper is closed the value becomes 0
#ifdef USE_SPI
ICM_20948_SPI myICM; // If using SPI create an ICM_20948_SPI object
ICM_20948_SPI orange;
ICM_20948_SPI white;
ICM_20948_SPI gray;
#else
ICM_20948_I2C myICM; // Otherwise create an ICM_20948_I2C object
#endif
void setup() {
SERIAL_PORT.begin(115200);
while(!SERIAL_PORT){};
pinMode (CS_PIN, OUTPUT);
pinMode (CS_PIN_orange, OUTPUT);
pinMode (CS_PIN_white, OUTPUT);
pinMode (CS_PIN_gray, OUTPUT);
#ifdef USE_SPI
SPI_PORT.begin();
#else
WIRE_PORT.begin();
WIRE_PORT.setClock(400000);
#endif
bool initialized = false;
while( !initialized ){
#ifdef USE_SPI
myICM.begin( CS_PIN, SPI_PORT );
orange.begin( CS_PIN_orange, SPI_PORT );
white.begin( CS_PIN_white, SPI_PORT );
gray.begin( CS_PIN_gray, SPI_PORT );
#else
myICM.begin( WIRE_PORT, AD0_VAL );
#endif
initialized = true;
}
}
void loop() {
Serial.println("1st Sensor:");
myICM.getAGMT(); // The values are only updated when you call 'getAGMT'
printRawAGMT( myICM.agmt ); // Uncomment this to see the raw values, taken directly from the agmt structure
Serial.println("2nd Sensor:");
orange.getAGMT(); // The values are only updated when you call 'getAGMT'
printRawAGMT( orange.agmt ); // Uncomment this to see the raw values, taken directly from the agmt structure
Serial.println("3rd Sensor:");
white.getAGMT(); // The values are only updated when you call 'getAGMT'
printRawAGMT( white.agmt ); // Uncomment this to see the raw values, taken directly from the agmt structure
Serial.println("4th Sensor:");
gray.getAGMT(); // The values are only updated when you call 'getAGMT'
printRawAGMT( gray.agmt ); // Uncomment this to see the raw values, taken directly from the agmt structure
delay(30);
}`
I should expect to receive nonzero values from my serial monitor from each ICM-20948 sensor.
Only the first ICM-20948 sensor produces a nonzero reading. My serial monitor data look like this:
1st Sensor:
RAW. Acc [ 02264, -07008, 15064 ], Gyr [ 00167, 00075, 00021 ], Mag [ 00072, -00211, 00299 ], Tmp [ 03232 ]
2nd Sensor:
RAW. Acc [ -00000, -00000, -00000 ], Gyr [ -00000, -00000, -00000 ], Mag [ -00000, -00000, -00000 ], Tmp [ -00000 ]
3rd Sensor:
RAW. Acc [ -00000, -00000, -00000 ], Gyr [ -00000, -00000, -00000 ], Mag [ -00000, -00000, -00000 ], Tmp [ -00000 ]
4th Sensor:
RAW. Acc [ -00000, -00000, -00000 ], Gyr [ -00000, -00000, -00000 ], Mag [ -00000, -00000, -00000 ], Tmp [ -00000 ]
Hey @oclyke, I'm trying to place the ICM-20948 into its full-chip sleep mode (8 ΞΌA draw), but the lowPower
function doesn't appear to have any effect on current consumption.
myICM.sleep(true)
and myICM.lowPower(true)
commands.myICM.sleep(true)
command reducing the ICM-20948 current consumption from 7.4 mA to 3.4 mA.myICM.lowPower(true)
has no effect on current draw, either on its own, or when paired with the sleep command.void loop() {
myICM.sleep(false);
//myICM.lowPower(false);
if ( myICM.dataReady() ) {
myICM.getAGMT(); // The values are only updated when you call 'getAGMT'
//printRawAGMT( myICM.agmt ); // Uncomment this to see the raw values, taken directly from the agmt structure
printScaledAGMT( myICM.agmt); // This function takes into account the sclae settings from when the measurement was made to calculate the values with units
delay(2000);
} else {
Serial.println("Waiting for data");
delay(500);
}
myICM.sleep(true);
//myICM.lowPower(true);
delay(2000);
}
Curious if you have any thoughts! In the meantime, I'll delve into the registers to see what could be up.
Cheers,
Adam
Hi @PaulZC,
Great work on the ICM-20948 library!
A quick note to let you know that the DMP examples make use of Serial.printf
for displaying outputs, which is not supported on all platforms (e.g. SAMD21).
Cheers,
Adam
Could you please add CMakeLists.txt to the library to create compatibility with Π‘Make projects?
And also for compatibility with (ESP-IDF4.0 + arduino-esp32-4.0 as a component) enviroment combination.
I tried the following CMakeLists.txt code and it performed very well:
idf_component_register(SRCS "src/ICM_20948.cpp"
"src/util/ICM_20948_C.c"
INCLUDE_DIRS "src"
"src/util"
REQUIRES "arduino")
component_compile_options(-std=c++17)
Several vars defined in header (ICM_20948_DMP.h).
I am using x86_64 with CJMCU-20948 board connected to PC via i2c_tiny_usb adapter (cheap chinese USBASP v2 reflashed with another firmware to get /dev/i2c-X device in Linux env).
cc util/ICM_20948_C.c ./main.c ./i2c.c -o ./i2c-test
where main.c includes ICM_20948_C.h
Compilation should work
As several vars define in header (ICM_20948_DMP.h), I have following errors:
/usr/bin/ld: /tmp/ccVjw7df.o:(.rodata+0x0): multiple definition of `inv_androidSensor_to_control_bits'; /tmp/cc5DSmAB.o:(.rodata+0x0): first defined here
/usr/bin/ld: /tmp/ccVjw7df.o:(.rodata+0x60): multiple definition of `DMP_Quat9_Byte_Ordering'; /tmp/cc5DSmAB.o:(.rodata+0x60): first defined here
/usr/bin/ld: /tmp/ccVjw7df.o:(.rodata+0xa0): multiple definition of `DMP_Quat6_Byte_Ordering'; /tmp/cc5DSmAB.o:(.rodata+0xa0): first defined here
/usr/bin/ld: /tmp/ccVjw7df.o:(.rodata+0xd0): multiple definition of `DMP_PQuat6_Byte_Ordering'; /tmp/cc5DSmAB.o:(.rodata+0xd0): first defined here
/usr/bin/ld: /tmp/ccVjw7df.o:(.rodata+0x100): multiple definition of `DMP_Raw_Gyro_Byte_Ordering'; /tmp/cc5DSmAB.o:(.rodata+0x100): first defined here
/usr/bin/ld: /tmp/ccVjw7df.o:(.rodata+0x130): multiple definition of `DMP_Activity_Recognition_Byte_Ordering'; /tmp/cc5DSmAB.o:(.rodata+0x130): first defined here
/usr/bin/ld: /tmp/ccVjw7df.o:(.rodata+0x148): multiple definition of `DMP_Secondary_On_Off_Byte_Ordering'; /tmp/cc5DSmAB.o:(.rodata+0x148): first defined here
I made them static, like this:
// ICM-20948 data is big-endian. We need to make it little-endian when writing into icm_20948_DMP_data_t
const static int DMP_Quat9_Byte_Ordering[icm_20948_DMP_Quat9_Bytes] =
{
3,2,1,0,7,6,5,4,11,10,9,8,13,12 // Also used for Geomag
};
const static int DMP_Quat6_Byte_Ordering[icm_20948_DMP_Quat6_Bytes] =
{
3,2,1,0,7,6,5,4,11,10,9,8 // Also used for Gyro_Calibr, Compass_Calibr
};
const static int DMP_PQuat6_Byte_Ordering[icm_20948_DMP_PQuat6_Bytes] =
{
1,0,3,2,5,4 // Also used for Raw_Accel, Compass
};
const static int DMP_Raw_Gyro_Byte_Ordering[icm_20948_DMP_Raw_Gyro_Bytes + icm_20948_DMP_Gyro_Bias_Bytes] =
{
1,0,3,2,5,4,7,6,9,8,11,10
};
const static int DMP_Activity_Recognition_Byte_Ordering[icm_20948_DMP_Activity_Recognition_Bytes] =
{
0,1,5,4,3,2
};
const static int DMP_Secondary_On_Off_Byte_Ordering[icm_20948_DMP_Secondary_On_Off_Bytes] =
{
1,0
};
It is no problem to patch lib this way, but maybe it is possible to redeclare this vars in source (.c) file, as now several copies of these vars will appear in final binary.
P.S. the problem seems because I use c, not c++.
Hi, does anybody know how to get data from external sensors connected to the icm-20948?
because ICM-20948 supports an auxiliary I2C interface to external sensors
Thank you!
I am having the same problem described.
Using the correct library and example code.
To use the I2C feature, do I keep the ICM-20948 breakout (original state without touching the jumpers) correct?
Originally posted by @EstevesDouglas in #7 (comment)
Hello,
I try to reading motorbike tilt angle and I experiment a problem I also have with MPU-6050 in fact.
These chip seem to work well on desktop but using it on vehicle seem to be a challenge.
As ICM-20948 seems to be usable on drone, I though it was dedicated to give accurate tilt angle but it seems to be more complicated than it appears.
First, I tested it on my desktop, applying the same movements to my Samsung S10+ (embedding a LSM6DSO) and the ICM-20948 breakout.
The result is this one
as you can see, the waveforms perfectly match.
Here, I did the same mounting both devices on my motorbike.
Between 547 and 807, I really was in stable turn, with the same tilt angle as given by my S10+. But the ICM-20948 was seriously drifting to 0 and the offset accumulated at 807 seems to appear at 911.
Between 1639 and 1925, I was accelerating as the turn decreases. S10+ gives an understandable value from my S10, but the ICM-20948 dramatically drift to 0, probably while the z accel increases.
I guess the problem could come from the pitch drift correction made with the g acceleration. And as on motorbike, as well as on drone, a turn cause the g acceleration to increase, maybe this algorithm causes the pitch reading to be false.
I hope I was clear enough, do you have an idea about the problem and how to solve it?
Using Sparkfun ICM 20948 v 1.2.7 library and Example7_DMP_Quat6_EulerAngles.ino sketch running on ESP32 FireBeetle, no filter enable.
Thank you for creating this useful library.
I have just bought a new set of SparkFun ICM-20948 and SparkFun Thing Plus - ESP32 WROOM, after successfully compiling and uploading the Example1_Basics, I got the error on the Serial Monitor:
Initialization of the sensor returned: Data Underflow
Trying again...
Did I miss out anything?
Thank you for your help.
Hi Paul,
now that the compass data is available to the DMP, I tried to verify the output against a BNO055 board from production.
In modes ORIENTATION and ROTATION_VECTOR the heading (x-axis) will drift to the a magnetic direction, but roll and pitch axis always start at 0Β°. Even if the sensor is kept at a constant 90Β° tilt (vertical), the output stays permanently at the initial ~0Β° value in those modes.
Only the mode GEOMAGNETIC_ROTATION_VECTOR seems to give an absolute orientation and outputs the 90Β° tilt correctly.
However, for some reason this mode is extremely slow to update. A 90Β° change in tilt takes over 10sec to settle, even tough the DMP is supposed to run at 55Hz.
Other 9-axis modes show large rotations instantly + get the heel and pitch axis correct, but do not give absolute orientation. Even worse, if you tilt the sensor by only 45Β° the heading suddenly changes. It should be steady as long as it "points" in the same direction. This makes none of the modes very useful for real world applications where absolute orientation is important.
In summary, the following things do not work for me when using DMP results:
This leads me to believe that at least the axis configuration of of the magnetometer could be wrong.
For testing we have to be able to convert the Quaternion output into Euler angles.
I would like to contribute the following code for that:
#include <cmath>
// heading, roll, pitch in degrees
struct Vector3D { double x, y, z; }
const double RAD2DEG = (180.0 / M_PI);
const double DEG2RAD = (M_PI / 180.0);
Vector3D toEuler( double w, double x, double y, double z)
{
Vector3D ret;
double sqw = w*w;
double sqx = x*x;
double sqy = y*y;
double sqz = z*z;
ret.x = atan2(2.0*(x*y+z*w),(sqx-sqy-sqz+sqw)) * RAD2DEG;
ret.z = atan2(2.0*(y*z+x*w),(-sqx-sqy+sqz+sqw)) * RAD2DEG;
double siny = -2.0*(x*z-y*w)/(sqx+sqy+sqz+sqw);
// prevent NaN and use 90 deg when out of range
if (fabs(siny) >= 1.0)
ret.y = copysign(90.0, siny);
else
ret.y = asin(siny) * RAD2DEG;
return ret;
}
Sorry for the bother with these issues, but I would really like to get some "truth" out of this sensor.
I know this IMU is especially difficult to configure, but I have a good reference, some experience, and would like to help :)
Best regards,
Bernhard
Hello. In the readme it is stated that the code is released under GPL v3, but in License.md it says that SparkFun code is released under the MIT license. Could you please clarify under which license the code is released?
Thanks for your time and great work :)
This library implements a mechanism to reduce the amount of I2C traffic by caching the previously used register bank and skip the bank change operation when it is not required.
Currently, no initialization method for ICM_20948_Device_t
is provided and therefore all members including _last_bank
is initialized as 0
(if declared as a global or static variable).
It means that if the first register access uses register bank 0 no bank change operation is performed.
This behavior can be problematic if the MCU is reset while the power to ICM-20948 is kept on.
Suppose the MCU is performing register access using bank 2, for example, and then the MCU resets, and the first register access after the reset is intended to use register bank 0.
Since the register bank change operation is skipped, the register access is recognized as access to the register bank 2.
To prevent this problem, I would suggest implementing an initialization method for ICM_20948_Device_t
that sets an invalid value (e.g. 4
) to _last_bank
so the first register bank change operation is performed 100%.
ICM_20948_Device_t
as a global variableThe MCU should access bank 0 after the reset.
The MCU accesses bank 2 since no bank change operation is performed after the reset.
Hello ICM-20948 Team,
I am attempting to use the aforementioned sensor in a project I'm working on. I am attempting to run the "Example1_Basics" code provided with the library to get a feel for how the sensor reacts to certain movements. However, every time I upload the code onto the Arduino UNO I've connected to the sensor, the initialization returns "Wrong ID" and then loops infinitely trying to correctly initialize.
I've hooked up the sensor to the UNO using the SPI breakout pins as recommended by the SparkFun Hookup guide (as seen here: https://learn.sparkfun.com/tutorials/sparkfun-9dof-imu-icm-20948-breakout-hookup-guide?_ga=2.24541626.1092070436.1611006899-1783455205.1549928219 ). The only change I have made to the code is adjusting the baud rate to be the same as other devices used o the project. The reason I am using the SPI method is that the UNO I'm using currently has another sensor attached to it that is using I2C. From what I've read on the subject this shouldn't cause an issue with an SPI device (especially since the I2C sensor shouldn't even be transmitting anything when I upload the "Example1_Basics code onto the Arduino). The Arduino IDE I'm using is version 1.8.13 and the ICM-20948 library I'm using is 1.1.2. The sensor is being powered directly from the 3.3V pin and GND pins on the UNO, and everything is connected using hook-up wires and headers (which I have triple checked all the connections are secure.
I've tried to solve the issue myself, but every instance of the "Wrong ID" error found in the code I looked through in the depository does not explain what it means. Even in instances where there are comments explaining certain error codes, no comment exists for the "Wrong ID" error. Hopefully you can provide me with an explanation of what it means so we can solve this problem as quickly as possible.
Thank you very much to create this very good and useful lib! This helps a lot to test out the new imu sensor. Will there be a chance to get DMP supported in this library? As the sensor claims to have a better DMP performance and I really want to see how it goes. Thank you so much!
Enabling either step counter or step detection features on the DMP appear non funcional
Using example 10, enable the step counter or step detection feature as below
// Enable the DMP Game Rotation Vector sensor (Quat6)
// success &= (myICM.enableDMPSensor(INV_ICM20948_SENSOR_GAME_ROTATION_VECTOR) == ICM_20948_Stat_Ok);
// Enable additional sensors / features
//success &= (myICM.enableDMPSensor(INV_ICM20948_SENSOR_RAW_GYROSCOPE) == ICM_20948_Stat_Ok);
// success &= (myICM.enableDMPSensor(INV_ICM20948_SENSOR_RAW_ACCELEROMETER) == ICM_20948_Stat_Ok);
//success &= (myICM.enableDMPSensor(INV_ICM20948_SENSOR_MAGNETIC_FIELD_UNCALIBRATED) == ICM_20948_Stat_Ok);
success &= (myICM.enableDMPSensor(INV_ICM20948_SENSOR_STEP_DETECTOR) == ICM_20948_Stat_Ok);
success &= (myICM.enableDMPSensor(INV_ICM20948_SENSOR_STEP_COUNTER) == ICM_20948_Stat_Ok);
success &= (myICM.enableDMPSensorInt(INV_ICM20948_SENSOR_STEP_DETECTOR) == ICM_20948_Stat_Ok);
// Configuring DMP to output data at multiple ODRs:
// DMP is capable of outputting multiple sensor data at different rates to FIFO.
// Setting value can be calculated as follows:
// Value = (DMP running rate / ODR ) - 1
// E.g. For a 225Hz ODR rate when DMP is running at 225Hz, value = (225/225) - 1 = 0.
// success &= (myICM.setDMPODRrate(DMP_ODR_Reg_Quat6, 0) == ICM_20948_Stat_Ok); // Set to 225Hz
// success &= (myICM.setDMPODRrate(DMP_ODR_Reg_Accel, 0) == ICM_20948_Stat_Ok); // Set to 225Hz
//success &= (myICM.setDMPODRrate(DMP_ODR_Reg_Gyro, 0) == ICM_20948_Stat_Ok); // Set to 225Hz
//success &= (myICM.setDMPODRrate(DMP_ODR_Reg_Cpass, 0) == ICM_20948_Stat_Ok); // Set to 225Hz
How i'm processing the data on my loop
// works
if ((dmp_data.header & DMP_header_bitmap_Compass_Calibr) > 0) { // Check for Compass
float scale_div = 1.0f / (1 << 16);
pout->mag.axes.z = dmp_data.Compass_Calibr.Data.Z * scale_div;
pout->mag.axes.x = dmp_data.Compass_Calibr.Data.X * scale_div;
pout->mag.axes.y = dmp_data.Compass_Calibr.Data.Y * scale_div;
}
// doesn't work
if ((dmp_data.header & (DMP_header_bitmap_Step_Detector | DMP_header_bitmap_PQuat6)) > 0) { // Check for Step Detector
static uint64_t steps = 0;
steps++;
printf("step %lld %lu\n", steps, dmp_data.Pedometer_Timestamp);
nrf_gpio_pin_toggle(LED_BT);
}
I should be able to extract step data ou have an interrupt generated from the IC
Very sporadically, i get garbage on the data read from the FIFO relative to the steps, but i can't pinpoint times or movements to trigger it
I know that these features aren't guaranteed to be working as said on the DMP.md, but either a few pointer to something i might be doing that's dumb or a bit of help would be much appreciated...
Also, idk if it's of interest, but, i found this git that claims it has support for the step counting feature, but unfortunately i can't test it cause i don't have any breakout boards with an ICM-20948...
Best regards.
Xavier
I read the ICM 20948 code in the src directory. I can't see if FIFO is enabled by default. Also, I could not find any code that do so.
Hi,
I'm testing the IMU with the Example7_DMP_Quat6_EulerAngles example.
I tried to turn around the yaw axis with IMU put on the table, so that "normaly" the roll and pitch axis needs to be constant during the rotation.
The result is that the yaw axis works perfectly, but I can see angular bias on both pitch and roll axis during the rotation (of about 20Β° max), this bias seems repeatable in function of the yaw angle.
Am I alone with this problem ?
We are creating a device based on a ESP32 and an ICM20948, using 4 actuators to physically level out platforms.
The actuators are activated based on the Roll and Pitch that is calculated from the output of the ICM20948.
For the calculation of the Roll and Pitch, we "borrowed" code from the internet (https://en.wikipedia.org/w/index.php?title=Conversion_between_quaternions_and_Euler_angles§ion=8#Source_code_2 ), incoorporated in the examples by @PaulZC as I understand)
We are technically schooled but no mathematicians and do not really understand what it's doing ... but its working :)
The actuators are on a well known location on the platform, so we know that if i.e. Roll = 10 that we need to extend the forward and backward actuators on the right of the platform to get the Roll to become smaller.
The problem now arrises that the way that our device is mounted on the platform can vary between installations, the ICM will not always be mounted parallel to the top surface of the platform, but can be mounted in any orientation (we can assume that it will only be 90degree rotations, so the Roll or Pitch axis can point forward, left, backwrd, right, up or down in regards to the platform.)
Our question is how can we add a configuration specifiying the mounted orientation, and (more importantly) use that configuration to get the right Roll and Pitch angles of the platform to steer the correct actuators.
Any help or reference to other sources would be welcome.
Thanks!
I'm using the C backend of this library on a raspberry pi. When compiling using arm-linux-gnueabihf-gcc the __arm__ macro is defined causing ICM_20948_C.c to attempt to include the avr/pgmspace.h header. I've corrected this in my local copy by changing line 11 from:
#if defined(__AVR__) || defined(__arm__) || defined(__ARDUINO_ARC__)
to
#if defined(__AVR__) || defined(__ARDUINO_ARC__)
I would submit a pull request but I'm not sure whether there was some reason for checking the __arm__ macro?
Hello,
First off, awesome library, thank you very much! I'm integrating it into a project here:
https://github.com/Blueprint-Foundry/Shelly
I edited the DMP_RawAccel example to get Raw Gyro data, so replacing where needed:
INV_ICM20948_SENSOR_RAW_GYROSCOPE
DMP_ODR_Reg_Gyro
DMP_header_bitmap_Gyro
etc.
I then read the XYZ values for gyro, and XYZ bias values instead of the original Accel values.
I should be able to read both gyro data and bias data
I only get gyro data, bias data is always 0.00. Example:
gyro: X:4.00 Y:14.00 Z:5.00 XB:0.00 YB:0.00 ZB:0.00
gyro: X:3.00 Y:5.00 Z:7.00 XB:0.00 YB:0.00 ZB:0.00
This all started in trying to use the calibrated Gyro field, however that never output data of any kind. Hence I though to use raw data + bias and make my own, but the bias is missing.
I assume there is some configuration step missing?
Request to you awesome folks: Perhaps an example .ino file for Gyro calibrated data and Raw data? :)
(note: all other functions I've tried so far work fine: Quat9, Accel, etc. So I think my chip is healthy since the Quat9 values seem sane.)
This looks interesting. I have starting working with the ICM 20648 which I understand is similar to the ICM 20948 but without the magnetometer. Do you know if this library will also work with the ICM 20648?
Hi @PaulZC,
I'm testing the ICM-20948 and DMP this morning and have been observing some strange behaviour with Example7_DMP_Quat6_EulerAngles.ino.
When the ICM-20948 is powered up, it appears to drift over several seconds before stabilizing. This can be seen in the graph below. The IMU is not moved while the data is being recorded. The IMU is also on a level surface and the pitch and roll values should be much closer to zero.
Is there any form of calibration that needs to first be performed?
Cheers,
Adam
Many thanks for adding the DMP support for this library.
I followed the recent example Example5_DMP_Quat9_Orientation and was successful getting the quaternion values from the sensor as the example shows. However, I would also want to get multiple data values at the same time, including quaternions and raw accel,gyro,mag data.
To test it out, I added the following lines in the setup;
success &= (myICM.enableDMPSensor(INV_ICM20948_SENSOR_ACCELEROMETER) == ICM_20948_Stat_Ok);
success &= (myICM.setDMPODRrate(DMP_ODR_Reg_Accel, 200) == ICM_20948_Stat_Ok);
and in the loop
else if ((data.header & DMP_header_bitmap_Accel) > 0)
{
float acc_x = ((float)data.Raw_Accel.Data.X);
float acc_y = ((float)data.Raw_Accel.Data.Y);
float acc_z = ((float)data.Raw_Accel.Data.Z);
char sensor_string_buff[128];
sprintf(sensor_string_buff, "{\"accel_x\":%f, \"accel_y\":%f, \"accel_z\":%f}", acc_x,acc_y,acc_z);
Serial.println(sensor_string_buff);
}
However, I am not getting any data (both quaternion and accel values), and it seems like the fifo is empty.
When reading the data if ((myICM.status == ICM_20948_Stat_Ok) || (myICM.status == ICM_20948_Stat_FIFOMoreDataAvail))
is always false.
Appreciate any help to fix this.
When the advanced example is run (including fix needed, see PR #67) on a stationary board, especially Accellero are far from stationary, even after rotating device on all axis to calibrate.
Magneto values seem pretty stable,
AccX values run from 1 to 31, AccY from 83 to 110, AccZ values from 1041 to 1070
Gyro all directions jump from 0 to 3 degrees per second
Running a espressif32@~3.2.0 with the Arduino framework, using address $68
Scaled. Acc (mg) [ -00011.72, -00083.98, 01050.78 ], Gyr (DPS) [ -00001.27, -00001.08, 00001.19 ], Mag (uT) [ 00013.50, -00006.00, 00083.25 ], Tmp (C) [ 00028.37 ] Scaled. Acc (mg) [ -00001.46, -00096.19, 01068.85 ], Gyr (DPS) [ -00001.02, 00001.76, 00001.42 ], Mag (uT) [ 00013.65, -00005.55, 00084.15 ], Tmp (C) [ 00028.51 ] Scaled. Acc (mg) [ -00014.65, -00088.87, 01050.29 ], Gyr (DPS) [ -00002.46, -00000.62, -00000.85 ], Mag (uT) [ 00014.55, -00006.75, 00083.25 ], Tmp (C) [ 00028.51 ] Scaled. Acc (mg) [ -00031.25, -00084.96, 01056.64 ], Gyr (DPS) [ -00000.56, -00001.31, -00002.40 ], Mag (uT) [ 00014.85, -00005.40, 00084.30 ], Tmp (C) [ 00028.41 ] Scaled. Acc (mg) [ -00026.86, -00084.96, 01057.13 ], Gyr (DPS) [ -00001.39, 00000.26, 00001.07 ], Mag (uT) [ 00014.70, -00005.55, 00083.40 ], Tmp (C) [ 00028.41 ] Scaled. Acc (mg) [ -00008.79, -00100.10, 01067.87 ], Gyr (DPS) [ -00000.09, -00000.11, 00001.72 ], Mag (uT) [ 00014.40, -00005.10, 00084.90 ], Tmp (C) [ 00028.32 ] Scaled. Acc (mg) [ -00016.60, -00097.66, 01065.92 ], Gyr (DPS) [ 00000.03, -00001.97, 00001.38 ], Mag (uT) [ 00014.85, -00006.75, 00084.75 ], Tmp (C) [ 00028.37 ] Scaled. Acc (mg) [ -00030.27, -00090.82, 01060.55 ], Gyr (DPS) [ -00000.85, -00000.98, -00003.08 ], Mag (uT) [ 00014.25, -00005.70, 00085.35 ], Tmp (C) [ 00028.60 ] Scaled. Acc (mg) [ -00012.70, -00091.31, 01051.27 ], Gyr (DPS) [ -00000.93, 00000.76, -00000.29 ], Mag (uT) [ 00014.25, -00005.40, 00083.55 ], Tmp (C) [ 00028.56 ] Scaled. Acc (mg) [ -00017.09, -00089.84, 01058.11 ], Gyr (DPS) [ -00001.10, -00000.85, -00000.27 ], Mag (uT) [ 00014.40, -00005.85, 00084.15 ], Tmp (C) [ 00028.56 ] Scaled. Acc (mg) [ -00023.93, -00093.75, 01055.18 ], Gyr (DPS) [ -00002.36, 00001.12, -00000.37 ], Mag (uT) [ 00013.35, -00005.55, 00084.90 ], Tmp (C) [ 00028.37 ] Scaled. Acc (mg) [ -00011.72, -00082.52, 01056.64 ], Gyr (DPS) [ -00001.34, -00000.69, -00002.05 ], Mag (uT) [ 00013.65, -00005.85, 00083.40 ], Tmp (C) [ 00028.60 ] Scaled. Acc (mg) [ -00018.07, -00082.52, 01064.45 ], Gyr (DPS) [ -00001.95, -00000.92, -00002.27 ], Mag (uT) [ 00014.85, -00006.45, 00084.00 ], Tmp (C) [ 00028.41 ] Scaled. Acc (mg) [ 00001.95, -00076.66, 01049.32 ], Gyr (DPS) [ -00003.15, 00000.73, 00000.76 ], Mag (uT) [ 00013.80, -00007.20, 00083.55 ], Tmp (C) [ 00028.22 ] Scaled. Acc (mg) [ -00021.48, -00083.01, 01050.78 ], Gyr (DPS) [ -00001.37, -00000.73, 00000.25 ], Mag (uT) [ 00015.45, -00007.05, 00084.15 ], Tmp (C) [ 00027.98 ] Scaled. Acc (mg) [ -00009.77, -00087.89, 01062.50 ], Gyr (DPS) [ -00004.31, 00002.25, -00001.50 ], Mag (uT) [ 00014.55, -00007.50, 00085.05 ], Tmp (C) [ 00028.51 ] Scaled. Acc (mg) [ -00013.18, -00096.68, 01060.55 ], Gyr (DPS) [ -00000.85, 00000.46, 00001.74 ], Mag (uT) [ 00015.45, -00007.35, 00083.85 ], Tmp (C) [ 00028.41 ] Scaled. Acc (mg) [ -00024.90, -00096.19, 01058.11 ], Gyr (DPS) [ -00002.50, 00000.95, 00001.44 ], Mag (uT) [ 00014.55, -00005.40, 00085.05 ], Tmp (C) [ 00028.51 ] Scaled. Acc (mg) [ -00018.07, -00100.10, 01061.52 ], Gyr (DPS) [ -00002.05, 00000.30, -00000.54 ], Mag (uT) [ 00014.85, -00005.40, 00084.75 ], Tmp (C) [ 00028.56 ] Scaled. Acc (mg) [ -00033.20, -00095.70, 01040.53 ], Gyr (DPS) [ -00000.53, 00000.99, 00001.15 ], Mag (uT) [ 00015.60, -00006.75, 00084.30 ], Tmp (C) [ 00028.37 ] Scaled. Acc (mg) [ -00017.58, -00094.73, 01059.08 ], Gyr (DPS) [ -00002.02, 00002.08, -00000.01 ], Mag (uT) [ 00013.65, -00005.85, 00084.90 ], Tmp (C) [ 00028.17 ] Scaled. Acc (mg) [ -00014.16, -00091.31, 01061.04 ], Gyr (DPS) [ -00001.69, 00001.98, -00001.17 ], Mag (uT) [ 00015.45, -00006.30, 00084.45 ], Tmp (C) [ 00028.41 ] Scaled. Acc (mg) [ -00016.60, -00091.80, 01062.01 ], Gyr (DPS) [ -00001.46, 00001.24, -00001.16 ], Mag (uT) [ 00014.40, -00006.30, 00084.90 ], Tmp (C) [ 00028.56 ] Scaled. Acc (mg) [ -00031.25, -00110.35, 01069.34 ], Gyr (DPS) [ -00001.66, 00000.60, -00003.24 ], Mag (uT) [ 00013.50, -00006.75, 00084.00 ], Tmp (C) [ 00028.41 ] Scaled. Acc (mg) [ -00014.65, -00087.89, 01054.69 ], Gyr (DPS) [ -00002.19, 00000.49, -00000.58 ], Mag (uT) [ 00012.90, -00006.60, 00083.85 ], Tmp (C) [ 00028.51 ] Scaled. Acc (mg) [ -00024.90, -00090.82, 01044.92 ], Gyr (DPS) [ -00000.14, -00000.18, 00001.03 ], Mag (uT) [ 00015.15, -00006.60, 00084.45 ], Tmp (C) [ 00028.60 ] Scaled. Acc (mg) [ -00023.44, -00090.82, 01053.22 ], Gyr (DPS) [ -00002.63, 00000.31, -00002.95 ], Mag (uT) [ 00014.70, -00007.35, 00084.15 ], Tmp (C) [ 00028.41 ] Scaled. Acc (mg) [ -00028.32, -00091.31, 01064.94 ], Gyr (DPS) [ -00001.31, 00001.27, -00002.93 ], Mag (uT) [ 00013.65, -00006.60, 00084.45 ], Tmp (C) [ 00028.56 ] Scaled. Acc (mg) [ -00026.86, -00098.14, 01066.41 ], Gyr (DPS) [ -00002.60, 00000.74, 00001.02 ], Mag (uT) [ 00013.35, -00007.05, 00083.85 ], Tmp (C) [ 00028.17 ] Scaled. Acc (mg) [ -00010.74, -00098.14, 01050.78 ], Gyr (DPS) [ -00001.30, -00000.18, -00002.82 ], Mag (uT) [ 00013.80, -00006.75, 00085.05 ], Tmp (C) [ 00028.56 ] Scaled. Acc (mg) [ -00025.39, -00100.59, 01045.90 ], Gyr (DPS) [ -00002.27, 00001.02, -00000.79 ], Mag (uT) [ 00013.80, -00004.95, 00085.80 ], Tmp (C) [ 00028.60 ] Scaled. Acc (mg) [ -00005.37, -00086.91, 01048.34 ], Gyr (DPS) [ -00001.23, -00000.21, 00000.24 ], Mag (uT) [ 00014.70, -00006.60, 00084.90 ], Tmp (C) [ 00028.37 ] Scaled. Acc (mg) [ -00027.34, -00088.38, 01057.13 ], Gyr (DPS) [ -00001.63, 00001.21, -00002.69 ], Mag (uT) [ 00015.30, -00005.70, 00084.30 ], Tmp (C) [ 00028.60 ] Scaled. Acc (mg) [ -00021.48, -00089.84, 01053.71 ], Gyr (DPS) [ -00002.62, 00001.20, -00000.58 ], Mag (uT) [ 00013.95, -00005.85, 00085.20 ], Tmp (C) [ 00028.51 ] Scaled. Acc (mg) [ -00024.90, -00099.12, 01058.59 ], Gyr (DPS) [ -00001.95, 00000.44, -00001.21 ], Mag (uT) [ 00012.75, -00005.70, 00084.00 ], Tmp (C) [ 00028.56 ] Scaled. Acc (mg) [ -00013.18, -00091.80, 01039.55 ], Gyr (DPS) [ -00001.76, 00001.09, -00001.30 ], Mag (uT) [ 00015.15, -00004.80, 00083.85 ], Tmp (C) [ 00028.08 ] Scaled. Acc (mg) [ -00022.95, -00087.89, 01051.27 ], Gyr (DPS) [ -00001.89, 00000.86, 00000.03 ], Mag (uT) [ 00014.70, -00006.60, 00084.45 ], Tmp (C) [ 00028.51 ] Scaled. Acc (mg) [ -00017.58, -00088.87, 01050.29 ], Gyr (DPS) [ -00000.75, -00000.11, -00000.33 ], Mag (uT) [ 00014.25, -00005.70, 00084.30 ], Tmp (C) [ 00028.37 ] Scaled. Acc (mg) [ -00014.65, -00093.26, 01057.13 ], Gyr (DPS) [ -00001.30, 00002.66, 00001.25 ], Mag (uT) [ 00013.80, -00006.75, 00085.05 ], Tmp (C) [ 00028.37 ] Scaled. Acc (mg) [ -00011.72, -00103.52, 01066.89 ], Gyr (DPS) [ -00000.27, 00002.05, 00000.61 ], Mag (uT) [ 00013.80, -00006.00, 00084.30 ], Tmp (C) [ 00028.51 ] Scaled. Acc (mg) [ -00024.41, -00087.89, 01053.71 ], Gyr (DPS) [ -00000.12, 00000.09, -00000.20 ], Mag (uT) [ 00014.55, -00006.45, 00084.30 ], Tmp (C) [ 00028.41 ] Scaled. Acc (mg) [ -00016.11, -00087.40, 01057.62 ], Gyr (DPS) [ -00003.13, 00000.49, -00001.82 ], Mag (uT) [ 00014.85, -00005.70, 00083.55 ], Tmp (C) [ 00028.51 ] Scaled. Acc (mg) [ -00010.74, -00093.26, 01056.64 ], Gyr (DPS) [ -00001.17, 00001.82, 00000.02 ], Mag (uT) [ 00014.55, -00006.75, 00084.75 ], Tmp (C) [ 00028.32 ] Scaled. Acc (mg) [ -00026.37, -00097.66, 01055.66 ], Gyr (DPS) [ -00003.73, 00000.74, -00002.21 ], Mag (uT) [ 00014.55, -00006.00, 00084.75 ], Tmp (C) [ 00028.22 ] Scaled. Acc (mg) [ -00030.27, -00095.21, 01059.57 ], Gyr (DPS) [ -00001.27, 00000.78, 00000.74 ], Mag (uT) [ 00014.55, -00005.70, 00084.75 ], Tmp (C) [ 00028.51 ] Scaled. Acc (mg) [ -00023.44, -00092.77, 01058.59 ], Gyr (DPS) [ -00001.22, 00000.73, 00002.84 ], Mag (uT) [ 00013.95, -00005.10, 00084.45 ], Tmp (C) [ 00028.41 ] Scaled. Acc (mg) [ -00018.55, -00083.50, 01041.02 ], Gyr (DPS) [ -00002.71, -00000.78, -00000.98 ], Mag (uT) [ 00015.15, -00006.30, 00083.85 ], Tmp (C) [ 00028.51 ] Scaled. Acc (mg) [ -00020.02, -00083.50, 01043.46 ], Gyr (DPS) [ -00002.50, 00000.82, -00001.18 ], Mag (uT) [ 00013.65, -00006.30, 00085.20 ], Tmp (C) [ 00028.41 ] Scaled. Acc (mg) [ -00024.41, -00086.43, 01070.80 ], Gyr (DPS) [ -00000.73, 00000.52, -00003.96 ], Mag (uT) [ 00014.55, -00004.95, 00084.00 ], Tmp (C) [ 00028.51 ]
In all DMP examples there is following thing:
if ( myICM.status != ICM_20948_Stat_FIFOMoreDataAvail ) // If more data is available then we should read it right away - and not delay
{
delay(10);
}
As I understand DMP is working following way:
All time it is getting raw values for some rate, perform calculations, finally produce for example Quat and put it to FIFO.
According example code, it is supposed to read FIFO fast enough.
But what if I don`t want to grab data always, In my case I need sometimes get actual data(actual current orientation).
How can I reach this?
How deep is FIFO? Will DMP still push new data to FIFO, when it will be full (deleting oldest data)?
Even yes, I will always get some old data (depending on FIFIO size).
Is it possible to disable FIFO or adjust it`s size?
Hi !
First of all, thanks for the tremendous amount of work you've made here !
I have a question about the way you calculate the value that will be store in the DMP in order to scale the raw accelerometer data. By default it's set for 4g as it is written in the ICM_20948.ccp file
Line 1220 :
ICM_20948_fss_t myFSS; // This uses a "Full Scale Settings" structure that can contain values for all configurable sensors
myFSS.a = gpm4;
and later Line 1287 :
// Configure Accel scaling to DMP
// The DMP scales accel raw data internally to align 1g as 2^25
// In order to align internal accel raw data 2^25 = 1g write 0x04000000 when FSR is 4g
const unsigned char accScale[4] = {0x04, 0x00, 0x00, 0x00};
result = writeDMPmems(ACC_SCALE, 4, &accScale[0]); if (result > worstResult) worstResult = result; // Write accScale to ACC_SCALE DMP register
// In order to output hardware unit data as configured FSR write 0x00040000 when FSR is 4g
const unsigned char accScale2[4] = {0x00, 0x04, 0x00, 0x00};
result = writeDMPmems(ACC_SCALE2, 4, &accScale2[0]); if (result > worstResult) worstResult = result; // Write accScale2 to ACC_SCALE2 DMP register
So, I want to set the full scale setting at +-16g and after I changed the Line 1220 myFSS.a = gpm4;
to myFSS.a = gpm16;
, I wonder now how to calculate the new values of accScale & accScale2 that will be passed to the DMP.
It states that 1g=2^25 but, for +-4g the value is 0x04000000=2* 2^25 and not 4* 2^25... Same issue for accScale2, I couldn't figure from where 0x00040000 come from and how I can calculate the correct value for my 16g setting.
If you have the way to figured these two values out it would be awesome !
Have a nice day !
Regards
I'm trying to work on a small visualization application. Using this library along with Madgwick AHRS, I was able to get my Arduino Uno sketch to output it's orientation on the serial communication line (e.g. Yaw, Pitch, Roll in degrees). On my PC, I have a python script setup to rotate a 3D model to match that orientation.
While I was initially successful, there was an unfortunate amount of drift, so say every second the computed orientation would drift about 5 seconds. This isn't acceptable.
I'd really like to use the DMP on the chip. I read the docs and it looks like there are features such as doing the sensor fusion for me, as well as calibrating the chip (in hopes of preventing drift). When I tried to enable the DMP in my Arduino Uno Sketch code, it said that there wasn't enough space on the chip.
Does the DMP require a more powerful micro controller than that of the Arduino Uno?
Hi,
Thank you for this huge effort.
In your example codes Example6 and 9, you are initializing matrix registers of the DMP, but b2sMountMultiplierZero[] and b2sMountMultiplierPlus[] are never used in the initializer. Was that intentional or a bug?
// Configure the B2S Mounting Matrix
const unsigned char b2sMountMultiplierZero[4] = {0x00, 0x00, 0x00, 0x00};
const unsigned char b2sMountMultiplierPlus[4] = {0x40, 0x00, 0x00, 0x00}; // Value taken from InvenSense Nucleo example
success &= (myICM.writeDMPmems(B2S_MTX_00, 4, &mountMultiplierPlus[0]) == ICM_20948_Stat_Ok);
success &= (myICM.writeDMPmems(B2S_MTX_01, 4, &mountMultiplierZero[0]) == ICM_20948_Stat_Ok);
success &= (myICM.writeDMPmems(B2S_MTX_02, 4, &mountMultiplierZero[0]) == ICM_20948_Stat_Ok);
success &= (myICM.writeDMPmems(B2S_MTX_10, 4, &mountMultiplierZero[0]) == ICM_20948_Stat_Ok);
success &= (myICM.writeDMPmems(B2S_MTX_11, 4, &mountMultiplierPlus[0]) == ICM_20948_Stat_Ok);
success &= (myICM.writeDMPmems(B2S_MTX_12, 4, &mountMultiplierZero[0]) == ICM_20948_Stat_Ok);
success &= (myICM.writeDMPmems(B2S_MTX_20, 4, &mountMultiplierZero[0]) == ICM_20948_Stat_Ok);
success &= (myICM.writeDMPmems(B2S_MTX_21, 4, &mountMultiplierZero[0]) == ICM_20948_Stat_Ok);
success &= (myICM.writeDMPmems(B2S_MTX_22, 4, &mountMultiplierPlus[0]) == ICM_20948_Stat_Ok);
When attempting to use the C libraries present in utils, including ICM_20948_C.h
will include ICM_20948_DMP.h
.
The aforementioned header defines the following
inv_androidSensor_to_control_bits
DMP_Quat9_Byte_Ordering
DMP_Quat6_Byte_Ordering
DMP_PQuat6_Byte_Ordering
DMP_Raw_Gyro_Byte_Ordering
DMP_Activity_Recognition_Byte_Ordering
DMP_Secondary_On_Off_Byte_Ordering
Which will cause multiple definition errors on these symbols between ICM_20948_C.c
and any other file including ICM_20948_C.h
.
The definition and declaration should be separated, and a file ICM_20948_DMP.c
should be created, containing the following
#include <stdint.h>
#include "ICM_20948_DMP.h"
const uint16_t inv_androidSensor_to_control_bits[ANDROID_SENSOR_NUM_MAX]=
{
// Data output control 1 register bit definition
// 16-bit accel 0x8000
// 16-bit gyro 0x4000
// 16-bit compass 0x2000
// 16-bit ALS 0x1000
// 32-bit 6-axis quaternion 0x0800
// 32-bit 9-axis quaternion + heading accuracy 0x0400
// 16-bit pedometer quaternion 0x0200
// 32-bit Geomag rv + heading accuracy 0x0100
// 16-bit Pressure 0x0080
// 32-bit calibrated gyro 0x0040
// 32-bit calibrated compass 0x0020
// Pedometer Step Detector 0x0010
// Header 2 0x0008
// Pedometer Step Indicator Bit 2 0x0004
// Pedometer Step Indicator Bit 1 0x0002
// Pedometer Step Indicator Bit 0 0x0001
// Unsupported Sensors are 0xFFFF
0xFFFF, // 0 Meta Data
0x8008, // 1 Accelerometer
0x0028, // 2 Magnetic Field
0x0408, // 3 Orientation
0x4048, // 4 Gyroscope
0x1008, // 5 Light
0x0088, // 6 Pressure
0xFFFF, // 7 Temperature
0xFFFF, // 8 Proximity <----------- fixme
0x0808, // 9 Gravity
0x8808, // 10 Linear Acceleration
0x0408, // 11 Rotation Vector
0xFFFF, // 12 Humidity
0xFFFF, // 13 Ambient Temperature
0x2008, // 14 Magnetic Field Uncalibrated
0x0808, // 15 Game Rotation Vector
0x4008, // 16 Gyroscope Uncalibrated
0x0000, // 17 Significant Motion
0x0018, // 18 Step Detector
0x0010, // 19 Step Counter <----------- fixme
0x0108, // 20 Geomagnetic Rotation Vector
0xFFFF, // 21 ANDROID_SENSOR_HEART_RATE,
0xFFFF, // 22 ANDROID_SENSOR_PROXIMITY,
0x8008, // 23 ANDROID_SENSOR_WAKEUP_ACCELEROMETER,
0x0028, // 24 ANDROID_SENSOR_WAKEUP_MAGNETIC_FIELD,
0x0408, // 25 ANDROID_SENSOR_WAKEUP_ORIENTATION,
0x4048, // 26 ANDROID_SENSOR_WAKEUP_GYROSCOPE,
0x1008, // 27 ANDROID_SENSOR_WAKEUP_LIGHT,
0x0088, // 28 ANDROID_SENSOR_WAKEUP_PRESSURE,
0x0808, // 29 ANDROID_SENSOR_WAKEUP_GRAVITY,
0x8808, // 30 ANDROID_SENSOR_WAKEUP_LINEAR_ACCELERATION,
0x0408, // 31 ANDROID_SENSOR_WAKEUP_ROTATION_VECTOR,
0xFFFF, // 32 ANDROID_SENSOR_WAKEUP_RELATIVE_HUMIDITY,
0xFFFF, // 33 ANDROID_SENSOR_WAKEUP_AMBIENT_TEMPERATURE,
0x2008, // 34 ANDROID_SENSOR_WAKEUP_MAGNETIC_FIELD_UNCALIBRATED,
0x0808, // 35 ANDROID_SENSOR_WAKEUP_GAME_ROTATION_VECTOR,
0x4008, // 36 ANDROID_SENSOR_WAKEUP_GYROSCOPE_UNCALIBRATED,
0x0018, // 37 ANDROID_SENSOR_WAKEUP_STEP_DETECTOR,
0x0010, // 38 ANDROID_SENSOR_WAKEUP_STEP_COUNTER,
0x0108, // 39 ANDROID_SENSOR_WAKEUP_GEOMAGNETIC_ROTATION_VECTOR
0xFFFF, // 40 ANDROID_SENSOR_WAKEUP_HEART_RATE,
0x0000, // 41 ANDROID_SENSOR_WAKEUP_TILT_DETECTOR,
0x8008, // 42 Raw Acc
0x4048, // 43 Raw Gyr
};
// ICM-20948 data is big-endian. We need to make it little-endian when writing into icm_20948_DMP_data_t
const int DMP_Quat9_Byte_Ordering[icm_20948_DMP_Quat9_Bytes] =
{
3,2,1,0,7,6,5,4,11,10,9,8,13,12 // Also used for Geomag
};
const int DMP_Quat6_Byte_Ordering[icm_20948_DMP_Quat6_Bytes] =
{
3,2,1,0,7,6,5,4,11,10,9,8 // Also used for Gyro_Calibr, Compass_Calibr
};
const int DMP_PQuat6_Byte_Ordering[icm_20948_DMP_PQuat6_Bytes] =
{
1,0,3,2,5,4 // Also used for Raw_Accel, Compass
};
const int DMP_Raw_Gyro_Byte_Ordering[icm_20948_DMP_Raw_Gyro_Bytes + icm_20948_DMP_Gyro_Bias_Bytes] =
{
1,0,3,2,5,4,7,6,9,8,11,10
};
const int DMP_Activity_Recognition_Byte_Ordering[icm_20948_DMP_Activity_Recognition_Bytes] =
{
0,1,5,4,3,2
};
const int DMP_Secondary_On_Off_Byte_Ordering[icm_20948_DMP_Secondary_On_Off_Bytes] =
{
1,0
};
Some Arduino cores have marked the boolean typedef as deprecated (see this issue). This results in a warning on compilation in STM32duino due to the following line:
Do we have to use the boolean alias? Can we change this to bool instead?
I can submit a PR if this change is desired.
Calibration needed?
I want to ask if the calibration is needed if we are using C code or C++ code? if it is needed then how we can add that automatically in the code?
Hey Guys,
I have been working on a quaternion project for quite some time and just recently saw the updated library (1.2.7) and have to say great work!!! ππΌππΌππΌ
I do have an issue ide like to discuss here:
Using:
SparkFun Pro nrf52840 Mini
ICM - 20948 connected I2C via qwiik
Bootloader - s140 6.1.1 r0
ICM Library - 1.2.7
Used the example 6 - 9DoF Quat.
I have 2 devices located on my left and right leg that transmit the quaternions to a host device via BLE.
I have noticed that the right leg is working perfectly as it is supposed to while kicking forward and sideways, but the left leg is acting weird especially when kicking to the side (to the right side).
When a kick is noticed the Quaternions (Q1 Q2 Q3) switch signs π²
This Image is the RIGHT leg. (The deltas we see are due to a lag in data coming in.. please ignore). This is what the data should look like.
This is the LEFT leg. As you can see the value of Q3 goes from (-0.893) to (0.893) when kicking to the right.
This is the Data
This is when I take my leg down after the kick it goes back to normal
The code on the Devices is the same:
Initiating the DMP exactly the same as in the Example, and grabbing the DMP data exactly the same as the example.
Any help is appreciated!
Thanks
Almog
In the file "examples/PortableC/Example999_Portable/Example999_Portable.ino" there is a Wire.endTransmission() after a Wire.requestFrom(). That Wire.endTransmission() is currently at line 205 and should be removed.
Explanation: Common-mistakes#2
See also my alternative explanation of the functions of the Wire library.
Hi,
During a recent investigation as to why the ICM-20948 temperature readings are about 5Β°C higher than other sensors (turns out the die temperature just runs hotter), I discovered a small error in the temperature formula used in this library.
SparkFun_ICM-20948_ArduinoLibrary/src/ICM_20948.cpp
Lines 123 to 126 in 4d5f843
According to the ICM-20948 the datasheet, it appears the above formula is missing the RoomTemp_Offset.
I believe the formula should end up looking something like:
float ICM_20948::getTempC(int16_t val)
{
return (((float)val - 21) / 333.87) + 21;
}
Cheers,
Adam
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.