Magnetometer & Gyro drift on MinIMU & LSM6DS33

Hello Everyone,

First of all, I must say that prior to this month, I never really worked with Sensors, Maths, Electronics, Arduino & C/C++ altough I’m pretty tech Savvy & used to programming.

I’m experiencing since few days a system using an Arduino & some IMU (To be exact the MinIMU-9 V5 & the 6 DoF LSM6DS33, both from Pololu) to control Armature’s bone within the 3D Software Blender, in order to build a kind of “Puppet” to control & animate rigs in real time.

Basically, what the full stack does is reading the raw data from the IMUs/Magnetometer, processing it through sensor fusion (Currently using Magdwick Filter) & then sending it to a Blender custom plugin I made in order to use the processed data.

While the introduction above is just for general context, the Blender part of it is outside the scope of my questions, as I’m having some pretty OK results by myself.

I made some tests using both 6 & 9 DOF.

  • All tests for Gyroscope/Accelerometer are done using the Pololu LSM6 Arduino Library
  • All tests for 9-DOF are done using the library mentionned above + the LIS3M Arduino Library by Pololu
  • The Magnetometer is, in theory, calibrated (but it might be messy, I will try to figure out Monday at work if I did it right)
  • I am using the same Sensitivity settings for both 6 & 9 dof Gyro & Accelero
  • In both cases, the data is then processed using MagdwickAHRS Arduino Library to obtain Quaternions.

After testing :

  • Precision is exactly what I expected for all axis, even though I got a bit of noise on X & Y axis (Pitch & Roll / Roll & Pitch don’t remember the order) while keeping the IMU Stationnary, using both 6 & 9 DOF (But I think I can handle this by filtering)
  • On the 6-DOF, as expected, there is a lot of Z (Yaw) drift over time, probably due to error accumulation but this isn’t a problem as 6-DOF will only be used for X & Y (and that X & Y are precise enough/don’t drift at all).
  • But here comes the problem : on the 9-DOF, the Z drift is like worse than on the 6-DOF + I got a bit of drift on X & Y aswell, but it appears to be for different reasons.
    • The drift isn’t constant, it’s more like a “delay” on the Z axis position. Like even though X & Y will instantly update to the correct position, Z will take 5 to 10 seconds and will be really slow

So it appears to be related to the magnetometer (On my 6 DOF, the Z rotation is barely perfect, but obviously it lacks long-term accuracy), maybe the Sensitivity ?(I now realize that I didn’t really tried to change it). Or might it be the Magdwick Algo that needs time to estimate with more accuracy ?

How can I reduce this drift ? Do I need to calibrate Gyro & Accelerometer aswell ? If so, how can I do this ?
Is this long delay simply part of the game & non-avoidable ? What could be the causes ?
Is Magdwick the better Sensor Fusion Algorithm or is the Mahony Filter a better choice ?

Thanks by advance for all your answers !


To clarify what is happening, could you let us know which one of these descriptions sounds more like what you are seeing:

  1. Your Z-heading initially responds to Z-rotation correctly, but then it slowly drifts back to an incorrect heading.
  2. Your Z-heading initially responds to Z-rotation incorrectly, but then slowly drifts towards the right heading.

The first case would suggest there’s a problem with your magnetometer calibration, and the second case would suggest there is a mismatch between your gyro’s actual sensitivity and what the program is expecting.

Unfortunately, we do not have any particular recommendations about choosing between sensor fusion algorithms.

- Patrick

Hi Patrick & thanks for your reply,

I’m in the 2nd case. The Z axis (not too sure but it may be the x/y axis aswell, cf this video I recorded)

In the video attached, I first don’t do anything for ± 5sec, then only move on the Z axis until the middle of the video, and then make a 180° rotation on Y. Most ‘IRL’ movements are really rough and quick.

As you can see, in every scenario there is a lot of drift (Im not talking about the little noise while Idle, which I think I’ll be able to easily reduce using some low pass filter or so).

It will eventually come to the correct position, but after like 10 seconds of correction.

Thanks by advance !

Could you try using the MinIMU-9 + Arduino AHRS software linked from the product page under the “Resources” tab to see if you can reproduce the same behavior with that?

- Patrick

Actually, my first tests were made using this code ! I didn’t used the OpenGL visualiser though, and re used the data in blender.
Unfortunately, the problem is the same with both my code & this software.

Can you post some pictures of your setup that show all of your connections?

When you use our AHRS software, please confirm whether you uncommented the line that says //#define IMU_V5 at the beginning of MinIMU9AHRS.ino. Also, can you check that you are setting the definition of SENSOR_SIGN[9] appropriately for your setup?

Finally, the MinIMU9AHRS program takes a few seconds at startup to calibrate (measure zero offsets for) the gyro and accelerometer. Are you ensuring that the sensor board is stationary at startup?

- Patrick

Thanks Patrick for your reply and sorry for being long to reply,

As I said earlier, my first tests were made using this code and this library is not far from ok for my tests, but I quickly ended up considering writing my own code for few reasons :

  • The Python OpenGL program runs on python 2.7, which is kind of a pain to setup on modern IDE given it don’t support Venv, the pip bootstrapper for this version of Python try to make requests to an URL that seems to be no longer in use thus making the simple process of setting up the project & installing dependencies a real pain.
  • This AHRS software use Degrees, which is not convenient for my implementation (I prefer to use quaternions) and as far as I looked into the code, I didn’t see any way to get a quaternion output.
  • Calibration is setting some arbitrary values for X/Y references (for exemple, if the calibration is done with the Sensors flipped 180° (but stationnary) it will take this as reference and not read absolute orientation
  • No support for 6 IMU even though it is the same Accel/Gyro in use for the 9 DOF

In your reply, you seem to forget that I ran all my tests with the 9-DOF both with your MiniMU AHRS software (With degrees output) & my custom code (Getting a WXYZ Quaternions Output).
The visualisation is done in Blender using Python, but this is clearly out of scope because I tested this part independently (among others using your 6-DOF imu03a/LSM6DS33 with my custom code) + the drift problem is also visible while only looking for digits on the serial monitor.

I know I’m not failing here, but here it is anyway :

Both Arduinos + 6 & 9 IMUs :

6 IMU Connections (I didn’t used 6DOF on your Arduino AHRS program)

9 IMU Connections :

Of course I did ! Wouldn’t work otherwise

I didn’t, because this is only for correcting Sensor orientation, right ? I already implemented it in the Blender Python addon, to be able to live correct the orientation later !

Yes I do !

Feel free to ask if you need me to do more specific troubleshooting !

Many many thanks for your kind help, and I wish you a good Monday

Could you post a video that demonstrates the issue you are having? The forum does not allow users to post very large videos, but it does work well with videos linked from other sites (like YouTube or Vimeo).

- Patrick

Here are multiple scenarios I made to better explain all the issues :

  • Using my 9 DOF with my code + Blender to demonstrate the initial problem
  • Using the same code with the 6 DOF to show you the difference
  • Using my 9 DOF with the MiniMU AHRS

None of the 6 & 9 DOF Gyro & Accel are calibrated using my own code. I am using a +/- 8 gauss magnetometer sensitivity, ± 4g for accel and 245 dps for gyro.

Here are static examples of 6 & 9 DOF, as references (using my code + Blender) :
You can notice that both of them slightly drift over time on Z.

Here is the example with my code and the 6 DOF (only accel and gyro) still using the Magdwick Arduino Library for sensor fusion. :
Even though its reversed on the video, you can see that it’s pretty accurate and correct and that the correct position is retrieved instantly. Of course, there is drift but I’m using 6 DOF so it was predictible.

Example of my code with the 9 DOF :
You can see that its position follow pretty accurately the real world one, but if im making harsh movements, a delay began to be visible before the bone in the software come close to its real world position. At the end its even worse and the position isn’t accurate at all (It might have been because of a wire connection issue though)

Example of the MinIMU AHRS with calibration at ground level :
Here the digit looks great ! accuracy is pretty good

Example of the MinIMU AHRS with calibration while tilted (to address the issue mentionned on my previous comment) :

You can see that if the calibration happens while tilted, the “tilted” position now act as absolute 0 which is kind of inconvenient for most use cases. Also, I don’t know if we see it on the video but its worth noting that in this case, there is a lot of drift over time on X & Y axis.

I’m still trying to make some tests with different calibration setups, sensitivities, while waiting for your answer.

Many thanks !

Thanks for the videos! That seems like a nice interface you have going for monitoring the MinIMU.

It seems like the only time you are really running into issues is when you rotate the board too quickly and there is a delay between the physical motion and your measurements responding. Behavior like that could be caused by the gyro being saturated. Have you tried any of the lower resolution/higher range settings?

- Patrick

Hi Patrick,

I just realized that I didn’t used the Magnetometer on all the 9-DOF examples I sent earlier, leaving it only the same capabilities as the 6 dof. I ran all tests with the Mag enabled this time, tried multiple mag sensitivities, and it only corrects a bit of drift, but most of the problem is still here so thankfully my mistake did not change a lot about my previous tests & messages.

Yes Indeed ! I might publish the source code of this project here once I’ll fixed remaining issues, if it could be helpful to anyone willing to work on a similar project.

After playing a bit with the gyroscope sensitivity using my own AHRS code, it seems that this delay is actually linked to the gyroscope, as you supposed. I’m using 125/245/500/1000/2000 specified in the datasheet, and if I’m lowering the value to 125 (was using 245 dps in those videos) my 3D representation wont move correctly anymore (Doing an IRL 90° turn will only trigger a 50° turn on the data) and the delay for it to recovery the initial position will be way higher. The drift will be slower aswell.

If i’m using higher values (500/1000/2000) the exact opposite will happen : The 3D representation will start moving excessively fast and in an abnormal way, and the drift will happen much faster.

(the links expire in 48h)

As far as I understand, changing the gyro sensitivity isn’t supposed to trigger that kind of enormous difference in the values and is more or less supposed to be part of a fine tuning process, right ? If so, I began to think that the culprit may be my functions to convert the raw LSB data into Dps. And in both cases (6 DOF & 9 DOF) the gyro sensitivity setting of 245 would just be the one that doesn’t trigger much of this calculation error, thus it affect only slightly the final AHRS computation. But I don’t see any error right now.

Here is the code I use to get the conversion factor for each sensor : (the /1000 is to convert from mdps / mGps to dps / Gps)


float SetMagnetoSensibility(){
  if (MAGNETOMETER_SENSITIVITY == 4){ return 68.42; }
  else if (MAGNETOMETER_SENSITIVITY == 8){ return 34.21; }
  else if (MAGNETOMETER_SENSITIVITY == 12){ return 22.81; }
  else if (MAGNETOMETER_SENSITIVITY == 16){ return 17.11; }
  else{ Serial.println("Mauvaise sensibilité +/- spécifiée. Valeurs typiques : 4/8/12/16"); }

Gyro :

float SetGyroSensibility(){
  if (GYROSCOPE_SENSITIVITY == 125){ return static_cast<float>(4.375)/1000; }
  else if (GYROSCOPE_SENSITIVITY == 245){ return static_cast<float>(8.75)/1000; }
  else if (GYROSCOPE_SENSITIVITY == 500){ return static_cast<float>(17.50)/1000; }
  else if (GYROSCOPE_SENSITIVITY == 1000){ return static_cast<float>(35)/1000; }
  else if (GYROSCOPE_SENSITIVITY == 2000){ return static_cast<float>(70)/1000; }
  else{ Serial.println("Mauvaise sensibilité +/- spécifiée. Valeurs typiques : 125/245/500/1000/2000"); }

Accelerometer :

float SetAccelSensibility(){
  if (ACCELEROMETER_SENSITIVITY == 2){ return 0.061/1000; }
  else if (ACCELEROMETER_SENSITIVITY == 4){ return 0.122/1000; }
  else if (ACCELEROMETER_SENSITIVITY == 8){ return 0.244/1000; }
  else if (ACCELEROMETER_SENSITIVITY == 16){ return 0.488/1000; }
  else{ Serial.println("Mauvaise sensibilité +/- spécifiée. Valeurs typiques : 2/4/8/16"); }

I know I should calibrate Gyro & Accel, but it seems to me that my problem isn’t tied to calibration. I’ll try to add it tomorrow though !

Thanks again !

One immediate concern with the variable definitions you posted is that the units for the magnetometer sensitivity are inverted from your accelerometer and gyro sensitivities.

  • The magnetometer sensitivity seems to expressed in units of bits per 100 gauss (LSB / 100 gauss)
  • Accelerometer sensitivity is expressed as g’s per bit (g / LSB)
  • gyro sensitivity is expressed as degrees-per-second per bit (dps / LSB)

So it would probably be good for you to check if that makes sense for how your code is written.

Beyond that, the sensitivity values in what you posted look okay. So, if changing the gyro sensitivity is having those kinds of effects on your system, then the most probable remaining cause is that the sensitivity values are not being used correctly in your program’s calculations.

- Patrick

Hello Patrick,

Good news !

You are right about the Mag part ! Thanks a lot about that !
I don’t know why I divided it by 100… I fixed this part and the 9 IMU benefit now of a slight improvement on the overall accuracy, with less drift & response delay - especially when doing slow movements ! The drift that used to happen idle is not anymore a problem, and my goal (and thus the end of these tests) seem way closer than before.

There is still some work to do, though. I double checked the applied transformation with the correct conversion factors for Gyro etc, and it seems OK to me. I calibrated the Gyro aswell, and ran a new calibration for the Mag. The only thing I did not calibrate is the Accelerometer.

To be sure, I’m attaching you the 3 files I used. The code is a bit messy and I know I can optimize readability & efficiency but for now I stick with this test example. The parts where I apply conversion factors are in “Magnetometer / IMU” files respectively. in the main file its basically about initializing & computing with the Magdwick Arduino lib.

ArduinoPuppet.ino (2.8 KB)
IMU.ino (2.4 KB)
Magnetometer.ino (1.6 KB)

Here are few more videos, with the new behavior with the 9 DOF & the correct magnetometer correction factor + gyro calibration :

The 9 DOF, idle in the same setup :

The 6 DOF same setup, idle : (more noisy but far from inaccurate !)

The 6 DOF, same calibration / no magnetometer :

And finally, here is a CSV of all computed values (Computed Quaternions + Processed Gyro/Accel/Magneto). The IMU had an incorrect offset just before recording those values. From row 2 to approximately 30, I am moving the IMU. From row 30 to 260, you can notice it slightly drift back to its correct value (0.76 for Quaternion W). And finally it stays idle for few seconds.

Samples.csv (29.2 KB)

I notice that there is values going from 0.5 to 3 in the gyro columns that may cause a bit of noise & drift, but I may be wrong and maybe the Accel & Magneto readings explain something I’m not aware of, so I’m sharing those samples with you !

Again, thanks for your precious help. This is already far beyond any expectations I had prior to post on any forum, and It’s fair to say that I rarely had such help from any “Support” !