Skip to content

v1.2.6 #69

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
May 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,768 changes: 2,268 additions & 500 deletions DMP.md

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ void loop()
// In case of drift, the sum will not add to 1, therefore, quaternion data need to be corrected with right bias values.
// The quaternion data is scaled by 2^30.

//SERIAL_PORT.printf("Quat6 data is: Q1:%ld Q2:%ld Q3:%ld Accuracy:%d\r\n", data.Quat6.Data.Q1, data.Quat6.Data.Q2, data.Quat6.Data.Q3);
//SERIAL_PORT.printf("Quat6 data is: Q1:%ld Q2:%ld Q3:%ld\r\n", data.Quat6.Data.Q1, data.Quat6.Data.Q2, data.Quat6.Data.Q3);

// Scale to +/- 1
double q1 = ((double)data.Quat6.Data.Q1) / 1073741824.0; // Convert to double. Divide by 2^30
Expand Down Expand Up @@ -316,11 +316,12 @@ ICM_20948_Status_e ICM_20948::initializeDMP(void)
// Enable accel and gyro sensors through PWR_MGMT_2
// Enable Accelerometer (all axes) and Gyroscope (all axes) by writing zero to PWR_MGMT_2
result = setBank(0); if (result > worstResult) worstResult = result; // Select Bank 0
uint8_t pwrMgmt2 = 0x40; // Set the reserved bit 6
uint8_t pwrMgmt2 = 0x40; // Set the reserved bit 6 (pressure sensor disable?)
result = write(AGB0_REG_PWR_MGMT_2, &pwrMgmt2, 1); if (result > worstResult) worstResult = result; // Write one byte to the PWR_MGMT_2 register

// Configure I2C_Master/Gyro/Accel in Low Power Mode (cycled) with LP_CONFIG
result = setSampleMode((ICM_20948_Internal_Mst | ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), ICM_20948_Sample_Mode_Cycled); if (result > worstResult) worstResult = result;
// Place _only_ I2C_Master in Low Power Mode (cycled) via LP_CONFIG
// The InvenSense Nucleo example initially puts the accel and gyro into low power mode too, but then later updates LP_CONFIG so only the I2C_Master is in Low Power Mode
result = setSampleMode(ICM_20948_Internal_Mst, ICM_20948_Sample_Mode_Cycled); if (result > worstResult) worstResult = result;

// Disable the FIFO
result = enableFIFO(false); if (result > worstResult) worstResult = result;
Expand All @@ -343,6 +344,11 @@ ICM_20948_Status_e ICM_20948::initializeDMP(void)
// dps2000
result = setFullScale((ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), myFSS); if (result > worstResult) worstResult = result;

// The InvenSense Nucleo code also enables the gyro DLPF (but leaves GYRO_DLPFCFG set to zero = 196.6Hz (3dB))
// We found this by going through the SPI data generated by ZaneL's Teensy-ICM-20948 library byte by byte...
// The gyro DLPF is enabled by default (GYRO_CONFIG_1 = 0x01) so the following line should have no effect, but we'll include it anyway
result = enableDLPF(ICM_20948_Internal_Gyr, true); if (result > worstResult) worstResult = result;

// Enable interrupt for FIFO overflow from FIFOs through INT_ENABLE_2
// If we see this interrupt, we'll need to reset the FIFO
//result = intEnableOverflowFIFO( 0x1F ); if (result > worstResult) worstResult = result; // Enable the interrupt on all FIFOs
Expand All @@ -364,8 +370,12 @@ ICM_20948_Status_e ICM_20948::initializeDMP(void)
// Set gyro sample rate divider with GYRO_SMPLRT_DIV
// Set accel sample rate divider with ACCEL_SMPLRT_DIV_2
ICM_20948_smplrt_t mySmplrt;
mySmplrt.g = 4; // ODR is computed as follows: 1.1 kHz/(1+GYRO_SMPLRT_DIV[7:0]). 4 = 220Hz
mySmplrt.a = 4; // ODR is computed as follows: 1.125 kHz/(1+ACCEL_SMPLRT_DIV[11:0]). 4 = 225Hz
//mySmplrt.g = 19; // ODR is computed as follows: 1.1 kHz/(1+GYRO_SMPLRT_DIV[7:0]). 19 = 55Hz. InvenSense Nucleo example uses 19 (0x13).
//mySmplrt.a = 19; // ODR is computed as follows: 1.125 kHz/(1+ACCEL_SMPLRT_DIV[11:0]). 19 = 56.25Hz. InvenSense Nucleo example uses 19 (0x13).
mySmplrt.g = 4; // 225Hz
mySmplrt.a = 4; // 225Hz
//mySmplrt.g = 8; // 112Hz
//mySmplrt.a = 8; // 112Hz
result = setSampleRate((ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), mySmplrt); if (result > worstResult) worstResult = result;

// Setup DMP start address through PRGM_STRT_ADDRH/PRGM_STRT_ADDRL
Expand Down Expand Up @@ -436,7 +446,7 @@ ICM_20948_Status_e ICM_20948::initializeDMP(void)
// 0=1125Hz sample rate, 1=562.5Hz sample rate, ... 4=225Hz sample rate, ...
// 10=102.2727Hz sample rate, ... etc.
// @param[in] gyro_level 0=250 dps, 1=500 dps, 2=1000 dps, 3=2000 dps
result = setGyroSF(4, 3); if (result > worstResult) worstResult = result; // 0 = 225Hz (see above), 3 = 2000dps (see above)
result = setGyroSF(4, 3); if (result > worstResult) worstResult = result; // 4 = 225Hz (see above), 3 = 2000dps (see above)

// Configure the Gyro full scale
// 2000dps : 2^28
Expand All @@ -448,17 +458,20 @@ ICM_20948_Status_e ICM_20948::initializeDMP(void)

// Configure the Accel Only Gain: 15252014 (225Hz) 30504029 (112Hz) 61117001 (56Hz)
//const unsigned char accelOnlyGain[4] = {0x03, 0xA4, 0x92, 0x49}; // 56Hz
const unsigned char accelOnlyGain[4] = {0x00, 0xE8, 0xBA, 0x2E}; // InvenSense Nucleo example uses 225Hz
const unsigned char accelOnlyGain[4] = {0x00, 0xE8, 0xBA, 0x2E}; // 225Hz
//const unsigned char accelOnlyGain[4] = {0x01, 0xD1, 0x74, 0x5D}; // 112Hz
result = writeDMPmems(ACCEL_ONLY_GAIN, 4, &accelOnlyGain[0]); if (result > worstResult) worstResult = result;

// Configure the Accel Alpha Var: 1026019965 (225Hz) 977872018 (112Hz) 882002213 (56Hz)
//const unsigned char accelAlphaVar[4] = {0x34, 0x92, 0x49, 0x25}; // 56Hz
const unsigned char accelAlphaVar[4] = {0x3D, 0x27, 0xD2, 0x7D}; // 225Hz
//const unsigned char accelAlphaVar[4] = {0x3A, 0x49, 0x24, 0x92}; // 112Hz
result = writeDMPmems(ACCEL_ALPHA_VAR, 4, &accelAlphaVar[0]); if (result > worstResult) worstResult = result;

// Configure the Accel A Var: 47721859 (225Hz) 95869806 (112Hz) 191739611 (56Hz)
//const unsigned char accelAVar[4] = {0x0B, 0x6D, 0xB6, 0xDB}; // 56Hz
const unsigned char accelAVar[4] = {0x02, 0xD8, 0x2D, 0x83}; // 225Hz
//const unsigned char accelAVar[4] = {0x05, 0xB6, 0xDB, 0x6E}; // 112Hz
result = writeDMPmems(ACCEL_A_VAR, 4, &accelAVar[0]); if (result > worstResult) worstResult = result;

// Configure the Accel Cal Rate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ void loop()
// In case of drift, the sum will not add to 1, therefore, quaternion data need to be corrected with right bias values.
// The quaternion data is scaled by 2^30.

//SERIAL_PORT.printf("Quat6 data is: Q1:%ld Q2:%ld Q3:%ld Accuracy:%d\r\n", data.Quat6.Data.Q1, data.Quat6.Data.Q2, data.Quat6.Data.Q3, data.Quat6.Data.Accuracy);
//SERIAL_PORT.printf("Quat6 data is: Q1:%ld Q2:%ld Q3:%ld\r\n", data.Quat6.Data.Q1, data.Quat6.Data.Q2, data.Quat6.Data.Q3);

// Scale to +/- 1
double q1 = ((double)data.Quat6.Data.Q1) / 1073741824.0; // Convert to double. Divide by 2^30
Expand Down
2 changes: 1 addition & 1 deletion library.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name=SparkFun 9DoF IMU Breakout - ICM 20948 - Arduino Library
version=1.2.5
version=1.2.6
author=SparkFun Electronics <[email protected]>
maintainer=SparkFun Electronics <sparkfun.com>
sentence=Use the low-power high-resolution ICM 20948 9 DoF IMU from Invensense with I2C or SPI. Version 1.2 of the library includes support for the InvenSense Digital Motion Processor (DMP™).
Expand Down
24 changes: 18 additions & 6 deletions src/ICM_20948.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1215,8 +1215,9 @@ ICM_20948_Status_e ICM_20948::initializeDMP(void)
uint8_t pwrMgmt2 = 0x40; // Set the reserved bit 6 (pressure sensor disable?)
result = write(AGB0_REG_PWR_MGMT_2, &pwrMgmt2, 1); if (result > worstResult) worstResult = result; // Write one byte to the PWR_MGMT_2 register

// Configure I2C_Master/Gyro/Accel in Low Power Mode (cycled) with LP_CONFIG
result = setSampleMode((ICM_20948_Internal_Mst | ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), ICM_20948_Sample_Mode_Cycled); if (result > worstResult) worstResult = result;
// Place _only_ I2C_Master in Low Power Mode (cycled) via LP_CONFIG
// The InvenSense Nucleo example initially puts the accel and gyro into low power mode too, but then later updates LP_CONFIG so only the I2C_Master is in Low Power Mode
result = setSampleMode(ICM_20948_Internal_Mst, ICM_20948_Sample_Mode_Cycled); if (result > worstResult) worstResult = result;

// Disable the FIFO
result = enableFIFO(false); if (result > worstResult) worstResult = result;
Expand All @@ -1239,6 +1240,11 @@ ICM_20948_Status_e ICM_20948::initializeDMP(void)
// dps2000
result = setFullScale((ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), myFSS); if (result > worstResult) worstResult = result;

// The InvenSense Nucleo code also enables the gyro DLPF (but leaves GYRO_DLPFCFG set to zero = 196.6Hz (3dB))
// We found this by going through the SPI data generated by ZaneL's Teensy-ICM-20948 library byte by byte...
// The gyro DLPF is enabled by default (GYRO_CONFIG_1 = 0x01) so the following line should have no effect, but we'll include it anyway
result = enableDLPF(ICM_20948_Internal_Gyr, true); if (result > worstResult) worstResult = result;

// Enable interrupt for FIFO overflow from FIFOs through INT_ENABLE_2
// If we see this interrupt, we'll need to reset the FIFO
//result = intEnableOverflowFIFO( 0x1F ); if (result > worstResult) worstResult = result; // Enable the interrupt on all FIFOs
Expand All @@ -1262,7 +1268,10 @@ ICM_20948_Status_e ICM_20948::initializeDMP(void)
ICM_20948_smplrt_t mySmplrt;
mySmplrt.g = 19; // ODR is computed as follows: 1.1 kHz/(1+GYRO_SMPLRT_DIV[7:0]). 19 = 55Hz. InvenSense Nucleo example uses 19 (0x13).
mySmplrt.a = 19; // ODR is computed as follows: 1.125 kHz/(1+ACCEL_SMPLRT_DIV[11:0]). 19 = 56.25Hz. InvenSense Nucleo example uses 19 (0x13).
// ** Note: comment the next line to leave the sample rates at the maximum **
//mySmplrt.g = 4; // 225Hz
//mySmplrt.a = 4; // 225Hz
//mySmplrt.g = 8; // 112Hz
//mySmplrt.a = 8; // 112Hz
result = setSampleRate((ICM_20948_Internal_Acc | ICM_20948_Internal_Gyr), mySmplrt); if (result > worstResult) worstResult = result;

// Setup DMP start address through PRGM_STRT_ADDRH/PRGM_STRT_ADDRL
Expand Down Expand Up @@ -1345,17 +1354,20 @@ ICM_20948_Status_e ICM_20948::initializeDMP(void)

// Configure the Accel Only Gain: 15252014 (225Hz) 30504029 (112Hz) 61117001 (56Hz)
const unsigned char accelOnlyGain[4] = {0x03, 0xA4, 0x92, 0x49}; // 56Hz
//const unsigned char accelOnlyGain[4] = {0x00, 0xE8, 0xBA, 0x2E}; // InvenSense Nucleo example uses 225Hz
//const unsigned char accelOnlyGain[4] = {0x00, 0xE8, 0xBA, 0x2E}; // 225Hz
//const unsigned char accelOnlyGain[4] = {0x01, 0xD1, 0x74, 0x5D}; // 112Hz
result = writeDMPmems(ACCEL_ONLY_GAIN, 4, &accelOnlyGain[0]); if (result > worstResult) worstResult = result;

// Configure the Accel Alpha Var: 1026019965 (225Hz) 977872018 (112Hz) 882002213 (56Hz)
const unsigned char accelAlphaVar[4] = {0x34, 0x92, 0x49, 0x25}; // 56Hz
//const unsigned char accelAlphaVar[4] = {0x06, 0x66, 0x66, 0x66}; // Value taken from InvenSense Nucleo example
//const unsigned char accelAlphaVar[4] = {0x3D, 0x27, 0xD2, 0x7D}; // 225Hz
//const unsigned char accelAlphaVar[4] = {0x3A, 0x49, 0x24, 0x92}; // 112Hz
result = writeDMPmems(ACCEL_ALPHA_VAR, 4, &accelAlphaVar[0]); if (result > worstResult) worstResult = result;

// Configure the Accel A Var: 47721859 (225Hz) 95869806 (112Hz) 191739611 (56Hz)
const unsigned char accelAVar[4] = {0x0B, 0x6D, 0xB6, 0xDB}; // 56Hz
//const unsigned char accelAVar[4] = {0x39, 0x99, 0x99, 0x9A}; // Value taken from InvenSense Nucleo example
//const unsigned char accelAVar[4] = {0x02, 0xD8, 0x2D, 0x83}; // 225Hz
//const unsigned char accelAVar[4] = {0x05, 0xB6, 0xDB, 0x6E}; // 112Hz
result = writeDMPmems(ACCEL_A_VAR, 4, &accelAVar[0]); if (result > worstResult) worstResult = result;

// Configure the Accel Cal Rate
Expand Down
4 changes: 2 additions & 2 deletions src/ICM_20948.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ A C++ interface to the ICM-20948
class ICM_20948
{
private:
Stream *_debugSerial; //The stream to send debug messages to if enabled
boolean _printDebug = false; //Flag to print the serial commands we are sending to the Serial port for debug
Stream *_debugSerial; //The stream to send debug messages to if enabled
bool _printDebug = false; //Flag to print the serial commands we are sending to the Serial port for debug

const uint8_t MAX_MAGNETOMETER_STARTS = 10; // This replaces maxTries

Expand Down
25 changes: 12 additions & 13 deletions src/util/ICM_20948_C.c
Original file line number Diff line number Diff line change
Expand Up @@ -1297,10 +1297,9 @@ ICM_20948_Status_e inv_icm20948_firmware_load(ICM_20948_Device_t *pdev, const un
}

//Enable LP_EN since we disabled it at begining of this function.

// result = ICM_20948_low_power(pdev, true); // Put chip into low power state
// if (result != ICM_20948_Stat_Ok)
// return result;
result = ICM_20948_low_power(pdev, true); // Put chip into low power state
if (result != ICM_20948_Stat_Ok)
return result;

if (!flag)
{
Expand Down Expand Up @@ -1602,9 +1601,9 @@ ICM_20948_Status_e inv_icm20948_set_dmp_sensor_period(ICM_20948_Device_t *pdev,
break;
}

// result = ICM_20948_low_power(pdev, true); // Put chip into low power state
// if (result != ICM_20948_Stat_Ok)
// return result;
result = ICM_20948_low_power(pdev, true); // Put chip into low power state
if (result != ICM_20948_Stat_Ok)
return result;

if (result2 > result)
result = result2; // Return the highest error
Expand Down Expand Up @@ -1774,9 +1773,9 @@ ICM_20948_Status_e inv_icm20948_enable_dmp_sensor(ICM_20948_Device_t *pdev, enum
return result;
}

// result = ICM_20948_low_power(pdev, true); // Put chip into low power state
// if (result != ICM_20948_Stat_Ok)
// return result;
result = ICM_20948_low_power(pdev, true); // Put chip into low power state
if (result != ICM_20948_Stat_Ok)
return result;

return result;
}
Expand Down Expand Up @@ -1861,9 +1860,9 @@ ICM_20948_Status_e inv_icm20948_enable_dmp_sensor_int(ICM_20948_Device_t *pdev,
// Write the interrupt control bits into memory address DATA_INTR_CTL
result = inv_icm20948_write_mems(pdev, DATA_INTR_CTL, 2, (const unsigned char *)&data_intr_ctl);

// result = ICM_20948_low_power(pdev, true); // Put chip into low power state
// if (result != ICM_20948_Stat_Ok)
// return result;
result = ICM_20948_low_power(pdev, true); // Put chip into low power state
if (result != ICM_20948_Stat_Ok)
return result;

return result;
}
Expand Down