brtaylor
Well-known member
I've been working on updating my InvenSense IMU library to include support for the ICM-20948. It is located here in the "icm-dev" branch:
The sensor has a 6 DOF IMU and a 3 DOF mag all on the same die. You can access the magnetometer either using an external I2C interface in the IMU or by placing the IMU into I2C passthrough mode and then accessing the mag directly from the microcontroller. My preference is to use the external I2C interface in the IMU, since this enables accessing the magnetometer data even when the microcontroller to IMU interface is SPI.
The issue I'm running into is that the magnetometer sample rate is not behaving how I would expect it to. To ease debugging, in my ConfigSrd method, I always set the magnetometer to a desired output rate of 10 Hz (https://github.com/bolderflight/invensense-imu/blob/icm-dev/src/icm20948.cpp#L229) and I request 9 bytes from the magnetometer starting at the status byte.
In my Read method (https://github.com/bolderflight/invensense-imu/blob/icm-dev/src/icm20948.cpp#L417), I check the magnetometer byte to see if new magnetometer data is available and pass that along with the new_mag_data flag.
I made an example to check the timing of the mag data ready:
With the SRD set to 0, I see the expected timing of 100 or occasionally 200 ms, as expected. However, if I change the SRD in this code to something like 4, which sets the IMU to run at a rate of 225 Hz, my magnetometer update rate becomes less consistent, with many updates taking over 1 second. I'm not sure what's going on. This code is similar to how I was working with the mag in the MPU-9250 and I don't experience any issues with that magnetometer, it reads at the desired rate. I tried setting the I2C_MST_P_NSR flag in the ICM-20948 thinking that it might help with the multi-byte reads, but it doesn't appear to have an effect. Similarly, I've tried setting the I2C_SLV4_DLY and I2C_SLV0_DELAY_EN flag thinking that the ICM-20948 might be polling the magnetometer too often. The behavior changed, but I didn't see an improvement.
I'll likely try setting the ICM-20948 into I2C bypass and then accessing with a Teensy directly to see if I can replicate this behavior and find a solution without having to deal with the ICM-20948 external I2C interface; however, I also thought I would post here in the meantime to see if anyone else has experienced these issues or has ideas on what might be causing them. Thanks!
GitHub - bolderflight/invensense-imu at icm-dev
Arduino and CMake library for communicating with the InvenSense MPU-6500, MPU-9250 and MPU-9255 nine-axis IMUs. - GitHub - bolderflight/invensense-imu at icm-dev
github.com
The sensor has a 6 DOF IMU and a 3 DOF mag all on the same die. You can access the magnetometer either using an external I2C interface in the IMU or by placing the IMU into I2C passthrough mode and then accessing the mag directly from the microcontroller. My preference is to use the external I2C interface in the IMU, since this enables accessing the magnetometer data even when the microcontroller to IMU interface is SPI.
The issue I'm running into is that the magnetometer sample rate is not behaving how I would expect it to. To ease debugging, in my ConfigSrd method, I always set the magnetometer to a desired output rate of 10 Hz (https://github.com/bolderflight/invensense-imu/blob/icm-dev/src/icm20948.cpp#L229) and I request 9 bytes from the magnetometer starting at the status byte.
In my Read method (https://github.com/bolderflight/invensense-imu/blob/icm-dev/src/icm20948.cpp#L417), I check the magnetometer byte to see if new magnetometer data is available and pass that along with the new_mag_data flag.
I made an example to check the timing of the mag data ready:
Code:
#include "icm20948.h"
/* Icm20649 object */
bfs::Icm20948 imu;
unsigned int t1, t2;
void setup() {
/* Serial to display data */
Serial.begin(115200);
while(!Serial) {}
/* Start the I2C bus */
Wire.begin();
Wire.setClock(400000);
/* I2C bus, 0x68 address */
imu.Config(&Wire, bfs::Icm20948::I2C_ADDR_SEC);
/* Initialize and configure IMU */
if (!imu.Begin()) {
Serial.println("Error initializing communication with IMU");
while(1) {}
}
/* Set the sample rate divider */
if (!imu.ConfigSrd(0)) {
Serial.println("Error configuring SRD");
while(1) {}
}
}
void loop() {
/* Check if data read */
if (imu.Read()) {
if (imu.new_mag_data()) {
t1 = millis();
Serial.println(t1 - t2);
t2 = t1;
}
}
}
With the SRD set to 0, I see the expected timing of 100 or occasionally 200 ms, as expected. However, if I change the SRD in this code to something like 4, which sets the IMU to run at a rate of 225 Hz, my magnetometer update rate becomes less consistent, with many updates taking over 1 second. I'm not sure what's going on. This code is similar to how I was working with the mag in the MPU-9250 and I don't experience any issues with that magnetometer, it reads at the desired rate. I tried setting the I2C_MST_P_NSR flag in the ICM-20948 thinking that it might help with the multi-byte reads, but it doesn't appear to have an effect. Similarly, I've tried setting the I2C_SLV4_DLY and I2C_SLV0_DELAY_EN flag thinking that the ICM-20948 might be polling the magnetometer too often. The behavior changed, but I didn't see an improvement.
I'll likely try setting the ICM-20948 into I2C bypass and then accessing with a Teensy directly to see if I can replicate this behavior and find a solution without having to deal with the ICM-20948 external I2C interface; however, I also thought I would post here in the meantime to see if anyone else has experienced these issues or has ideas on what might be causing them. Thanks!