I don’t have a whole lot of experience with IMUs. Currently I have the ICM 20948 module connected to an ESP32, using the Sparkfun library and this Mahony library.
The module is calibrated, and behaves as expected, in that if you slowly rotate it in a circle, it accurately shows your heading (yaw). But I’m surprised at the amount of noise. The attached image shows standard deviation of 14 degrees with the module sitting still. I tried a moving average but that slows response a lot and still deviates by half a degree. Is this what I should expect?
Second question: to reduce the possibility of I2C noise, I tried to remove the pull-up jumper on the board (the chip itself has a built-in pull-up). To remove the jumper, I cut the two tiny traces between the three rectangles in the relevant part of the board. Did I do that correctly?
Teleplot image here.
Please post images in line as shown below (drag them into the post editor window).
You do not appear to be calculating the standard deviation (root mean square difference) correctly, and the average seems to be drifting, suggesting that the gyro offsets are not well determined. Just eyeballing the plot on the left, I would guess that for a drift-free set of measurements, SD = ~3 degrees, which is perhaps a bit larger than one would expect from the combined noise figures in the sensor data sheet.
Thanks for that information. I am using ICM_20948_Mahony.ino, unmodified except for the Serial.print() to Teleplot. I got the gyro offsets from ICM_20948_get_cal_data.ino.
The offsets vary some, each time I run get_cal_data, even when the module is sitting still:
float G_offset[3] = {-18.3, 37.2, 24.8};
//G_offset[3] = {-15.2, 19.4, 14.1, };
//G_offset[3] = {-36.6, 29.0, 9.8, };
//G_offset[3] = {-23.0, 49.6, 22.5, };
I think the issue might be timing related. When I use the same code in another application, the IMU checks are less frequent, and the “noise” seems worse.
In the original code, I added a delay(100) to the loop() and I get this:
The error is very consistent. I’m still investigating, but haven’t seen anything obvious.
Also, if I uncomment the line:
Gxyz[0] = Gxyz[1] = Gxyz[2] = 0;
I get much more stable readings, but presumably then you’re not using the gyro at all?
That line sets all the gyro rotation rates for zero and is only there for testing purposes.
In the original code, I added a delay(100) to the loop()
That is a very bad idea. The IMU data have to be sampled very frequently or the numerical integration will fail. Even printing angles too often creates a problem.
The IMU sample and orientation update rate should be at least 50 Hz for good results.
If you want help with code problems, post the code, using code tags.
I put the IMU poll in a task loop running on core 1 and it seems to be working much better. Thank you for your help.