Closed okme7 closed 1 year ago
Hi, Thanks for reporting this. It will be tricky for me to replicate as I don't have a nRF52832 board. Which board are you using? Please post a link. Is Example6 unmodified - apart from the header prints? Best wishes, Paul
Hi, Thanks for reporting this. It will be tricky for me to replicate as I don't have a nRF52832 board. Which board are you using? Please post a link. Is Example6 unmodified - apart from the header prints? Best wishes, Paul
I did not modify Example6, I just added a print statement for the header. However, I have ported the library to the MDK environment. I would like to ask, what does the header data look like on your original board?
Hi,
You say you "have ported the library to the MDK". Have you made any changes to the code? I am wondering if the DMP is not being loaded correctly, or maybe the DMP data is not being parsed correctly? Can you share a link to your code?
Best wishes, Paul
For what it's worth, when I print the header I get consistent 0x800 when running this on a Teensy. I don't ever see an 0x8800.
Full code is below. I'm using two ICM-20948s so there's extra stuff in there.
#include "ICM_20948.h" // Click here to get the library: http://librarymanager/All#SparkFun_ICM_20948_IMU
#define SERIAL_PORT Serial
#define SPI_FRQ 900000 // 900kHZ
#define BLUE_SPI SPI
#define BLUE_CS 10
#define RED_SPI SPI
#define RED_CS 9
ICM_20948_SPI blueICM;
ICM_20948_SPI redICM;
void setup() {
SERIAL_PORT.begin(115200); // or 6_000_000
SERIAL_PORT.println(F("ICM-20948 Example"));
while (SERIAL_PORT.available()) { // Make sure the serial RX buffer is empty
SERIAL_PORT.read();
}
SPI.begin();
bool initialized = false;
while (!initialized) {
// TODO: Add more IMUs here.
blueICM.begin(BLUE_CS, BLUE_SPI, SPI_FRQ);
redICM.begin(RED_CS, RED_SPI, SPI_FRQ);
SERIAL_PORT.print(F("Initialization of the sensor returned: "));
SERIAL_PORT.println(blueICM.statusString());
if (blueICM.status != ICM_20948_Stat_Ok) {
SERIAL_PORT.println(F("Trying again..."));
delay(500);
} else {
initialized = true;
}
}
SERIAL_PORT.println(F("Device connected!"));
bool success = true;
// Initialize the DMP. initializeDMP is a weak function. You can overwrite it if you want to e.g. to change the sample rate
success &= (blueICM.initializeDMP() == ICM_20948_Stat_Ok);
success &= (redICM.initializeDMP() == ICM_20948_Stat_Ok);
// Enable the DMP orientation sensor
success &= (blueICM.enableDMPSensor(INV_ICM20948_SENSOR_GAME_ROTATION_VECTOR) == ICM_20948_Stat_Ok);
success &= (redICM.enableDMPSensor(INV_ICM20948_SENSOR_GAME_ROTATION_VECTOR) == ICM_20948_Stat_Ok);
// Enable any additional sensors / features
//success &= (blueICM.enableDMPSensor(INV_ICM20948_SENSOR_RAW_ACCELEROMETER) == ICM_20948_Stat_Ok);
success &= (blueICM.setDMPODRrate(DMP_ODR_Reg_Quat6, 0) == ICM_20948_Stat_Ok); // Set to the maximum
success &= (redICM.setDMPODRrate(DMP_ODR_Reg_Quat6, 0) == ICM_20948_Stat_Ok); // Set to the maximum
// Enable the FIFO
success &= (blueICM.enableFIFO() == ICM_20948_Stat_Ok);
success &= (redICM.enableFIFO() == ICM_20948_Stat_Ok);
// Enable the DMP
success &= (blueICM.enableDMP() == ICM_20948_Stat_Ok);
success &= (redICM.enableDMP() == ICM_20948_Stat_Ok);
// Reset DMP
success &= (blueICM.resetDMP() == ICM_20948_Stat_Ok);
success &= (redICM.resetDMP() == ICM_20948_Stat_Ok);
// Reset FIFO
success &= (blueICM.resetFIFO() == ICM_20948_Stat_Ok);
success &= (redICM.resetFIFO() == ICM_20948_Stat_Ok);
// Check success
if (success) {
SERIAL_PORT.println(F("DMP enabled!"));
} else {
SERIAL_PORT.println(F("Enable DMP failed!"));
while (1); // :(
}
}
void loop() {
icm_20948_DMP_data_t blue_data;
blueICM.readDMPdataFromFIFO(&blue_data);
icm_20948_DMP_data_t red_data;
redICM.readDMPdataFromFIFO(&red_data);
SERIAL_PORT.print("blue header: ");
SERIAL_PORT.print(blue_data.header, HEX);
SERIAL_PORT.print(" red header: ");
SERIAL_PORT.println(red_data.header, HEX);
// Was valid data available?
if ((blueICM.status == ICM_20948_Stat_Ok) || (blueICM.status == ICM_20948_Stat_FIFOMoreDataAvail)
|| (redICM.status = ICM_20948_Stat_Ok) || (redICM.status == ICM_20948_Stat_FIFOMoreDataAvail)) {
if ((blue_data.header & DMP_header_bitmap_Quat6) > 0 || (red_data.header & DMP_header_bitmap_Quat6) > 0) {
double blue_q1 = ((double)blue_data.Quat6.Data.Q1) / 1073741824.0; // Convert to double. Divide by 2^30
double blue_q2 = ((double)blue_data.Quat6.Data.Q2) / 1073741824.0; // Convert to double. Divide by 2^30
double blue_q3 = ((double)blue_data.Quat6.Data.Q3) / 1073741824.0; // Convert to double. Divide by 2^30
double blue_q0 = sqrt(1.0 - ((blue_q1 * blue_q1) + (blue_q2 * blue_q2) + (blue_q3 * blue_q3)));
double red_q1 = ((double)red_data.Quat6.Data.Q1) / 1073741824.0; // Convert to double. Divide by 2^30
double red_q2 = ((double)red_data.Quat6.Data.Q2) / 1073741824.0; // Convert to double. Divide by 2^30
double red_q3 = ((double)red_data.Quat6.Data.Q3) / 1073741824.0; // Convert to double. Divide by 2^30
double red_q0 = sqrt(1.0 - ((red_q1 * red_q1) + (red_q2 * red_q2) + (red_q3 * red_q3)));
// Bunch of prints below ...
}
}
delay(5);
}
For what it's worth, when I print the header I get consistent 0x800 when running this on a Teensy. I don't ever see an 0x8800.
Full code is below. I'm using two ICM-20948s so there's extra stuff in there.
#include "ICM_20948.h" // Click here to get the library: http://librarymanager/All#SparkFun_ICM_20948_IMU #define SERIAL_PORT Serial #define SPI_FRQ 900000 // 900kHZ #define BLUE_SPI SPI #define BLUE_CS 10 #define RED_SPI SPI #define RED_CS 9 ICM_20948_SPI blueICM; ICM_20948_SPI redICM; void setup() { SERIAL_PORT.begin(115200); // or 6_000_000 SERIAL_PORT.println(F("ICM-20948 Example")); while (SERIAL_PORT.available()) { // Make sure the serial RX buffer is empty SERIAL_PORT.read(); } SPI.begin(); bool initialized = false; while (!initialized) { // TODO: Add more IMUs here. blueICM.begin(BLUE_CS, BLUE_SPI, SPI_FRQ); redICM.begin(RED_CS, RED_SPI, SPI_FRQ); SERIAL_PORT.print(F("Initialization of the sensor returned: ")); SERIAL_PORT.println(blueICM.statusString()); if (blueICM.status != ICM_20948_Stat_Ok) { SERIAL_PORT.println(F("Trying again...")); delay(500); } else { initialized = true; } } SERIAL_PORT.println(F("Device connected!")); bool success = true; // Initialize the DMP. initializeDMP is a weak function. You can overwrite it if you want to e.g. to change the sample rate success &= (blueICM.initializeDMP() == ICM_20948_Stat_Ok); success &= (redICM.initializeDMP() == ICM_20948_Stat_Ok); // Enable the DMP orientation sensor success &= (blueICM.enableDMPSensor(INV_ICM20948_SENSOR_GAME_ROTATION_VECTOR) == ICM_20948_Stat_Ok); success &= (redICM.enableDMPSensor(INV_ICM20948_SENSOR_GAME_ROTATION_VECTOR) == ICM_20948_Stat_Ok); // Enable any additional sensors / features //success &= (blueICM.enableDMPSensor(INV_ICM20948_SENSOR_RAW_ACCELEROMETER) == ICM_20948_Stat_Ok); success &= (blueICM.setDMPODRrate(DMP_ODR_Reg_Quat6, 0) == ICM_20948_Stat_Ok); // Set to the maximum success &= (redICM.setDMPODRrate(DMP_ODR_Reg_Quat6, 0) == ICM_20948_Stat_Ok); // Set to the maximum // Enable the FIFO success &= (blueICM.enableFIFO() == ICM_20948_Stat_Ok); success &= (redICM.enableFIFO() == ICM_20948_Stat_Ok); // Enable the DMP success &= (blueICM.enableDMP() == ICM_20948_Stat_Ok); success &= (redICM.enableDMP() == ICM_20948_Stat_Ok); // Reset DMP success &= (blueICM.resetDMP() == ICM_20948_Stat_Ok); success &= (redICM.resetDMP() == ICM_20948_Stat_Ok); // Reset FIFO success &= (blueICM.resetFIFO() == ICM_20948_Stat_Ok); success &= (redICM.resetFIFO() == ICM_20948_Stat_Ok); // Check success if (success) { SERIAL_PORT.println(F("DMP enabled!")); } else { SERIAL_PORT.println(F("Enable DMP failed!")); while (1); // :( } } void loop() { icm_20948_DMP_data_t blue_data; blueICM.readDMPdataFromFIFO(&blue_data); icm_20948_DMP_data_t red_data; redICM.readDMPdataFromFIFO(&red_data); SERIAL_PORT.print("blue header: "); SERIAL_PORT.print(blue_data.header, HEX); SERIAL_PORT.print(" red header: "); SERIAL_PORT.println(red_data.header, HEX); // Was valid data available? if ((blueICM.status == ICM_20948_Stat_Ok) || (blueICM.status == ICM_20948_Stat_FIFOMoreDataAvail) || (redICM.status = ICM_20948_Stat_Ok) || (redICM.status == ICM_20948_Stat_FIFOMoreDataAvail)) { if ((blue_data.header & DMP_header_bitmap_Quat6) > 0 || (red_data.header & DMP_header_bitmap_Quat6) > 0) { double blue_q1 = ((double)blue_data.Quat6.Data.Q1) / 1073741824.0; // Convert to double. Divide by 2^30 double blue_q2 = ((double)blue_data.Quat6.Data.Q2) / 1073741824.0; // Convert to double. Divide by 2^30 double blue_q3 = ((double)blue_data.Quat6.Data.Q3) / 1073741824.0; // Convert to double. Divide by 2^30 double blue_q0 = sqrt(1.0 - ((blue_q1 * blue_q1) + (blue_q2 * blue_q2) + (blue_q3 * blue_q3))); double red_q1 = ((double)red_data.Quat6.Data.Q1) / 1073741824.0; // Convert to double. Divide by 2^30 double red_q2 = ((double)red_data.Quat6.Data.Q2) / 1073741824.0; // Convert to double. Divide by 2^30 double red_q3 = ((double)red_data.Quat6.Data.Q3) / 1073741824.0; // Convert to double. Divide by 2^30 double red_q0 = sqrt(1.0 - ((red_q1 * red_q1) + (red_q2 * red_q2) + (red_q3 * red_q3))); // Bunch of prints below ... } } delay(5); }
Because I have enabled the DMP for the accelerometer, the header will show 0x8800. However, the issue I am currently experiencing is that the header often contains other data, making it difficult for me to smoothly read the quaternion values.
Hi,
You say you "have ported the library to the MDK". Have you made any changes to the code? I am wondering if the DMP is not being loaded correctly, or maybe the DMP data is not being parsed correctly? Can you share a link to your code?
Best wishes, Paul
code_link: https://github.com/okme7/nrf52832_icm20948_dmp The DMP code is located in the "nrf52832_icm20948_dmp/app/" folder.Due to the initial failure to load the firmware file when initializing the DMP, I made some modifications to the code.Specific modifications were made in the inv_icm20948_write_mems function within the nrf52832_icm20948_DMP/app/util/ICM_20948_C.C file. I added a uint8_t array, dmp3[], to store the incoming data.The function inv_icm20948_write_mems can be found at line 1479.
uint8_t dmp3[length];
for(int i = 0; i < length; i++)
{
dmp3[i] = (uint8_t)data[i];
}
.......
result = ICM_20948_execute_w(pdev, AGB0_REG_MEM_R_W, &dmp3[bytesWritten], thisLen);
Hi,
You have made so many changes to the library, I can not even start to debug this for you.
For example, you have removed all of the default parameters:
Library: ICM_20948_Status_e setDMPstartAddress(unsigned short address = DMP_START_ADDRESS);
Your code: ICM_20948_Status_e ICM_20948_setDMPstartAddress(unsigned short address);
Perhaps something is defaulting to the wrong value?
I am sorry, I can not help you further.
Best wishes, Paul
The DMP header data is abnormal.
When reading the 6-axis quaternion using Example 6, I noticed that the data is not continuous and there are occasional freezes. So I added print statements for the header value and found that the header value is strange. Instead of the expected value of 0x8800, the header often has other values.
Your workbench
Use nRF52832 platform