MinIMU-9 AHRS code


I recently purchased the 9-axis MinIMU here:

I am using it with an Arduino Uno, and have downloaded and set up the sample AHRS code given on the product page. The problem is, it doesn’t give me correct roll/pitch/yaw values. Here is a brief summary of the behavior I have been seeing:
-It calibrates the offset correctly, and remains stable if not moved. That part is fine.
-If the IMU is rotated up to 45 degrees along its roll or pitch axis, the serial output reflects a change, but not the correct value. It seems a bit low, a 30 degree actual rotation only shows a 20 degree rotation on the serial monitor of the arduino.
-If the IMU is rotated beyond approximately 45 degrees along the roll or pitch axis, the respective axis value on the serial monitor will start to tick up at about a degree per second, and not stop as long as the device is held at an angle.

My main question is: Has anyone been able to get the sample AHRS code to work? Has anyone experienced similar behavior, and if so, did you find a solution?

When I have the arduino just spit out raw analog values, they all look correct. It seems like a coding issue. I am currently dissecting the program looking for something that might manifest itself as I described, but the going is slow. Any help or advice, even just someone saying theirs worked fine, would be fantastic.


I’m having similar issues. a 360 yaw move isn’t reflected correctly. I’ve just set it up and am still playing with it, but the first impression is that something is a bit off.


Have both of you made sure to run the Calibrate example from the LSM303 library and updated the calibration constants in MinIMU9AHRS.pde? We have found that the offsets of the readings from the LSM303 can be so large that it is often useless to try to compute a heading from uncalibrated readings.

When calibrating, be sure to rotate the IMU through as many possible orientations as you can, for example by repeatedly tilting it up and down to vertical while turning it to face different directions, to ensure that the minimum and maximum possible readings are recorded for each axis.

- Kevin

Yes, I calibrated.

#define M_X_MIN -1210
#define M_Y_MIN -711
#define M_Z_MIN -594
#define M_X_MAX 440
#define M_Y_MAX 556
#define M_Z_MAX 463

What I am seeing is that if I yaw 180 degrees the unit is drifting 100 degrees or more.

I have an arduino mini pro 5v in a breadboard. I am using a sparkfun ftdi basic to power and run the serial. I have the IMU on 12" breadboard jumpers. I clamp the IMU with a cheap harbor freight alligator clamp and wait maybe 20 seconds after powering up to move the IMU. I then un-clamp and move it about with my hands. I move it so it’s reading a yaw of about zero. I move it around a bit and make sure it’s prety level and about zero yaw. I then rotate it 180 degrees of yaw and hold it. At this point the yaw reading will drift back towards zero, but will not reach zero.

Let me know what testing you would like me to perform and I’ll run it.

I’m just going to make a quick note here to point out that compass sensors work poorly near PCs (hard drives have neodymium magnets), large metal objects and motors. They also don’t like being surrounded by AC power cables (such as industrial buildings).

Doesn’t mean this is affecting you, but it could be. Can’t hurt to test it outside a few feet away from a laptop.

I calibrated a few more times and am seeing some wide variances in some of the numbers between calibrations. That said the last set of calibration numbers is working much better.

M min X: -690 Y: -710 Z: -520 M max X: 417 Y: 420 Z: 458

Hello, pounce.

I am glad to hear you are having more success with this set of calibration values.

Darth Maker has some good points about things that could be influencing your compass readings, so if any of those are present in your setup, you could try to get rid of them or move them farther away so they are less likely to affect the compass.

Another thing I forgot to mention is to make sure the orientation of your IMU board matches what the code expects. By default, the AHRS code assumes that the IMU board starts lying flat with the component side down, so that the Z axis points into the ground. If you are using the board with the component side up, look for the comments in MinIMU9AHRS.pde that say “Uncomment the below line to use this axis definition” and comment/uncomment the appropriate lines.

- Kevin

Up thread I mention I clamp the IMU and wait for boot. I am putting the IC’s face down. Nothing within about 4 feet of the IMU. I’m also in a house with no electrical panels within 60 feet.

I realize magnetic things affect the compass.

Any idea how stable the calibration numbers are over time? I’m wondering if dynamic calibration is going to be required in the field.


You were correct - I had my board oriented with the Z axis facing the wrong direction. I switched the commented lines in the AHRS code, and now it works great. Such a simple fix. Thanks for your advice.


Unfortunately, we haven’t done any long-term tests to see if the magnetometer ranges and offsets change significantly over time. If you come to any conclusions about this, we would be interested to hear about it.

Pieter, I am glad to hear you solved your problem. Thanks for the update.

- Kevin

Hi Everyone, just joined the forums!

I’m having a similar issue + one additional issue…
I’ve got the MinIMU-9 Hooked up to a Teensy 2.0 and everything is connected properly, I can see all the Data, and change values in Arduino etc…

First Issue: Get the YAW to Stop Drifting! :frowning:
This is really important to me because I am working on a HeadTracker… I’ve tried calibrating it, but no matter what I do, it still just drifts ever so slightly to the positive Axis… if I leave it for say… 5 minutes it will read 3.45… then another five minutes it will read 7.99 etc… it just keeps increasing by itself.

Second Issue: Power off/on Re-calibration
If I unplug the Teensy/USB… then plug it in Again - and load the AHRS Python program, The Pitch and Roll are slightly off… It’s like it doesn’t re-calibrate itself when it turns on/off… is this something I would have to change inside the Arduino code?

Thanks for any help / pointers!


Got the drift fixed … forgot I had commented out some of the drift correction calculations because I wanted to make the Yaw more responsive… :mrgreen:
Now it seems to work pretty good!! Sorry for the stupid post. Still haven’t worked out the re-calibration part though…


Are you keeping the IMU level and stationary for a few seconds after you apply power to it? The AHRS program takes a few measurements during that time and uses those as a zero reference for acceleration and rotation.

- Kevin

Hi Kevin, yes sir, I’ve leave it perfectly still for a few seconds, then load AHRS.
I’m not too worried about the Roll/Pitch… but the Yaw is still drifting a little bit when I spin the device left & Right quickly… I’m just assuming that’s because it’s reading some Accelerometer values… I understand that the Z-Axis doesn’t have a direction… but is there any way to just initialize it to “North” then have it read it’s change/delta from that “North” value to determine it’s pointing direction??? Sorry I’m a total math noob, I’m not sure how to go about it.

I’m building a Head-Tracking system so it needs to be as Precise as possible if the user quickly whips their head to the left or right…

Thanks again for all the help!


I’ve also been looking at this device:

If that would provide suitable head-tracking capabilities I would certainly consider purchasing one for a more advanced prototype… but just to keep costs at an absolute minimum now If there is any way to do it with the IMU-9 that would be great!!

Thanks again,

The AHRS program uses the gyro to measure relative rotation on a short timescale, then uses data from the accelerometer (for down on the roll/pitch axes) and the magnetometer (for north on the yaw axis) as absolute references to correct for gyro drift. If your yaw reading is drifting, it might be because the gyro and magnetometer are disagreeing by a large amount.

Have you run the Calibrate example from the LSM303 library to obtain calibration offsets for your board’s magnetometer and updated the values of M_X_MIN, M_Y_MIN, etc. accordingly in MinIMU9AHRS.pde? If you have not, doing so should make the code behave better with your particular magnetometer.

After the magnetometer is calibrated, another thing you could try is to adjust the Gyro_Gain_Z constant (although I have not tried this myself, so I am not sure if it would work). Say you turn the board through 90 degrees of yaw. If the readings reflect a fast rotation of less than 90 degrees, then drift slowly in the same direction until it reaches 90 degrees, the gain might be too small and you should try increasing it a little. On the other hand, if the readings reflect a fast rotation of more than 90 degrees, then drift slowly back in the opposite direction, the gain might be too large and you should decrease it.

If you try this, please let us know how it turns out.

- Kevin

Hi Kevin, that worked out perfectly!! I had already calibrated the board so I moved on to modifying the Z-gain… I increased it very slightly to: 0.0785 and that seems to be working great! It still seems to drift just a tiny tiny bit, but it corrects itself quicker/sharper…

I gotta say I’m really impressed with what you guys have done with this program, I’m by no means a “Math guy” so I tip my hat to you sir! haha.


I was relieved to see that other people were experiencing the same problems as I have. I misunderstood how the calibration program was meant to be used, but things distinctly improved when I calibrated properly. Despite the improvement, the underlying issues I had were still present and unacceptable, but I was able to quickly attribute that to the initial orientation of my device. I assumed the initialization routine would work under any orientation…my mistake. After correcting this the orientation estimate seems much more reliable.

My application requires that I mount the IMU at an angle perpendicular to the ground due to spatial limitations on my board. I’ve just flipped it on its end so the header pins are at the bottom and the mounting screw hole is at the top. Based on the silkscreen picture, this makes Z my roll, Y my pitch, and X my Yaw. The “SENSOR_SIGN[9]” line seems helpful if you want to flip pitch, roll, or yaw the unit half a rotation, but not quarter rotations. Is there any way to initialize the unit such that it accepts my orientation while initializing? I’m guessing that I would have to use some trigonometric proportions in place of the positive and negative 1’s, but I’m not sure if changing this array from an int to a float would pose any serious complications.

Complications aside, it was sort of cool to see the angle readings “spill” into one another as a linear combination because the basis vectors were defined off axis!

Anyway, thanks for reading this far into my long winded question!

Chad, I’m glad to hear you got an improvement with that change. By the way, we can’t take too much credit for the AHRS code; it mostly came from sf9domahrs, which is based on ArduIMU, and I only modified it to work with our MinIMU-9.

burkleypatterson, I think the easiest way to swap the axes around might be to edit I2C.pde. For example, I think the code for reading the gyro (starting on line 52) could be changed to this for your setup:

  AN[0] = gyro.g.z; // roll
  AN[1] = gyro.g.y; // pitch
  AN[2] = gyro.g.x; // yaw

and the same should be done for the rest of the sensors.

- Kevin

Thanks for your help! That seems to have mostly done the trick. I have a couple of concerns though.

Now when I open the serial monitor, the yaw reading begins at zero and slowly ticks its way up to a larger value, where it stabilizes. Everything else sits happily at zero.

The reading responds fairly consistently to rotation with little drift, but not linearly relative to its absolute angle. When I rotate it 90 degrees it only registers a rotation of about 60 degrees, except in a specific absolute angle range. When I reach this range, a 90 degree rotation is output as 180 degrees. In total a full rotation still yields 360 degrees (restoring to the original value), but that’s not the case on smaller scales. When I performed the initial calibration the unit was about a foot away from my macbook pro, but when noticed this inconsistency I was using a 10’ usb on the other side of the room. Could a skewed calibration be responsible for both of these problems?