FreeIMU: an Open Hardware Framework for Orientation and Motion Sensing

FreeIMU is an ongoing research project which aims to design Open Hardware 9/10 DOM/DOF Inertial Measurement Units as well as easy to use Orientation and Motion Sensing libraries, built on top of the Arduino platform.
The goal of the FreeIMU Framework is to simplify the development of projects based upon the most powerful and new consumer grade inertial, magnetic and pressure sensors.

FreeIMU version 0.2 (left) and version 0.1 (right)

The main application of FreeIMU is orientation sensing: by reading the data from the various sensors is possible to compute precisely the orientation of FreeIMU in the space. Recent boards also feature an high resolution barometer allowing to precisely track the device altitude. This can be useful in many applications: human-computer interaction device prototyping, flying machines, robots, human movement tracking and everywhere orientation sensing is a key aspect.

As FreeIMU breakout the sensors interrupt pins, it's also possible to detect per axis single and double taps, free fall as well as activity or inactivity. This makes FreeIMU a very good choice for Human-Computer devices prototyping. Interrupts pins are also very useful if you are into interrupt based reading of the sensors, useful to develop high frequency interrupt based sensor reading.

Video presentation of FreeIMU

Older video presentations: FreeIMU v0.3, FreeIMU v0.1 and 0.2.

A true Open Hardware project

Open Hardware Logo

FreeIMU is a true Open hardware, released under the CC-BY-SA. You are free, actually encouraged, to use it for any purpose, to study and modify its designs, to make your own copies of FreeIMU and even sell your own FreeIMU based hardware. But, you will have to share your designs based on FreeIMU keeping attribution and sharing them using the same libre license.

On FreeIMU repository (see development section below) and from the downloads on this page, you have access to everything you need to build your own FreeIMU board. You have access to the schematics, the PCB designs and even the bill of material so that you can build your own FreeIMU.

Moreover, FreeIMU has been designed using KiCAD, an excellent libre PCB design software, so you don't have to rely on proprietary software to study or modify FreeIMU.

Getting FreeIMU

An assembled, tested and ready to use FreeIMU board can be bought from:

The FreeIMUs boards bought from the above shops financially support the project. The boards have been produced and assembled in Italy by reasonably paid workers in a safe environment in respect with European and Italian laws.

Build your own FreeIMU

If you have SMD soldering experience (or if you are up for experimentation) you can build your own FreeIMU. From the downloads below you have access to all the designs needed to have your FreeIMU PCB manufactured.

You can get cheap PCB with awesome quality from Dorkbot PDX and order the various components needed from you favorite electronic distributor: the Bill of Materials (BOM) files will tell you exactly which components you'll need for your FreeIMU.

The are various ways of soldering the board. If you only need a couple of boards done, tack flux, solder wire and hot air reflow station are enough to build your boards (Remember not to use hot air over the pressure sensor). See this video for good instructions. In case you are building more units, an SMD stencil with solder paste is the suggested method.

In case you need help, just post a comment below.

FreeIMU versions

FreeIMU version 0.1

FreeIMU v0.1

WARNING: Discontinued due to the phasing out of the HMC5843.

FreeIMU v0.1 is the simplest FreeIMU available. It contains the ADXL345 accelerometer, the ITG3200 gyroscope and the HMC5843 magnetometer, their respective capacitors and an additional 10uF capacitor to help keeping the power to the sensors stable. It doesn't have any voltage regulator nor any level translator so it needs to be connected to a 3.3V power source and the I2C level signals have to be 3.3V. When used on a 5V microcontroller, an I2C level converter and a voltage regulator are needed.

FreeIMU version 0.2

FreeIMU v0.2

WARNING: Discontinued due to the phasing out of the HMC5843.

FreeIMU v0.2 has the same sensors (ADXL345, ITG3200 and HMC5843) and size of v0.1 but I added an integrated voltage regulator (MIC5205) and a logic level converter (PCA9306). With these components it's extremely simple to use FreeIMU v0.2 on 5V boards like 16MHz Arduinos, just connect FreeIMU to the 5V, GND, SDA and SCL on Arduino and you are ready to go!

IMPORTANT: in version 0.2 sent to production there is a bug in the drill size of the connectors. The drill hole should have been 0.04" while it is actually 0.032". Consequence of this is that only rounded pins will fit inside the drill and standard squared pins won't fit. This is not really a problem as the big oval pad makes actually possible to use 90 deg squared pin arrays using the pad as a smd connector. The Kicad sources above and the gerbers marked with "Fixed" have this issue fixed. However they haven't been tested on production so double check them before send them to fabrication.

FreeIMU version 0.3

FreeIMU v0.3

FreeIMU version 0.3 replaces the accelerometer and magnetometers used in v0.1 and v0.2 with the ADXL346 as accelerometer and the HMC5883L as magnetometer. The gyroscope is still the ITG3200. FreeIMU v0.3 integrates a voltage regulator (MIC5205) and a logic level translator (PCA9306) as well as all the pullups resistors needed.

FreeIMU version 0.3.1

FreeIMU v0.3.1 is a minor revision of FreeIMU v0.3. There have been some corrections in the silkscreen and the footprint of the HMC5883L have been made slightly bigger to make assembly easy. Everything else is just as in FreeIMU v0.3.

FreeIMU version 0.3.5

FreeIMU 0.3.5 top view

FreeIMU 0.3.5 is a small (22x20 mm) 9 degrees of measurement IMU MARG sensor featuring the BMA180 accelerometer, the ITG3200 gyroscope and the HMC5883L magnetometer.

FreeIMU 0.3.5 also has two additional subversions, FreeIMU 0.3.5_MS which features the MS5611-01BA high resolution pressure sensor and the FreeIMU 0.3.5_BMP which features the BMP085 pressure sensor.

FreeIMU v0.3.5 has an integrated voltage regulator (MIC5203) allowing you to plug it from 3V3 to 16V providing you 80mA of current which you can use to chain it to other 3V3 sensors or devices. By using the MIC5203, no tantalum caps are used in the whole design. Tantalum is not a good idea socially and environmentally.

The board has integrated 2K2 pullups resistors (which can be enabled or disabled by means of a solder switch) but doesn't have an integrated logic level converter. We decided to not include the LLC (which is present in my FreeIMU v0.2 and v0.3) as it adds considerable complexity in the design and schematics without being strictly necessary. In fact, given a properly configured software, it's a redundant part. Moreover the upcoming development of many 3V3 based control boards (eg: Multipilot 32) makes adding an LLC not a very far-seeing choice.

The IMU board is however compatible with my LLC board which can be stacked above the IMU, so that you can easily add the LLC protection keeping the amount of additional wires at the minimum.

The board, a part from the usual power and I2C connectors, breaks out the interrupt pins for all the three sensors. This should empower software developers to design interrupt based sensor reading and sensor fusion algorithms (opposed to the currently common polling based approach) which should provide possibility to shorten the cycle path of our algorithms.

FreeIMU version 0.3.5_MS

FreeIMU v0.3.5_MS

FreeIMU v0.3.5_MS is a variation of FreeIMU v0.3.5 which features the BMA180 accelerometer, the ITG3200 gyroscope, the HMC5883L magnetometer and the MS5611-01BA high resolution pressure sensor.

The board comes with a voltage regulator (MIC5203) and 2K2 pullups optionally disabled by using of a solder switch.

FreeIMU version 0.3.5_BMP

FreeIMU v0.3.5_BMP top view

FreeIMU v0.3.5_BMP is a variation of FreeIMU v0.3.5 which features the BMA180 accelerometer, the ITG3200 gyroscope, the HMC5883L magnetometer and the BMP085 pressure sensor.

The board comes with a voltage regulator (MIC5203) and 2K2 pullups optionally disabled by using of a solder switch.

FreeIMU version 0.4

FreeIMU v0.4.1

FreeIMU v0.4 features the MPU6050 gyroscope+accelerometer, the HMC5883L magnetometer and the MS5611-01BA high resolution altimeter.

The magnetometer is attached to the AUX I2C bus of the MPU6050 thus allowing it to be read directly by the MPU6050.

FreeIMU library

FreeIMU can be easily used on Arduino compatible boards using the Arduino FreeIMU library which implements sensor fusion MARG orientation filter enabling you to do easy and straightforward orientation sensing.

FreeIMU library - 2012/11/22
Use Arduino 1.0.1 IDE or later version.

Install the libraries as explained in the Arduino Libraries Reference section Contributed Libraries.
The FreeIMU library now supports all the versions up to v0.4. By default it's configured to be used on v0.4. In order to use on different boards, open the file FreeIMU.h and uncomment the correct version of your board.

The FreeIMU library also supports the following 3rd parties boards:

  • Sparkfun IMU Digital Combo Board - 6 Degrees of Freedom ITG3200/ADXL345 SEN-10121
  • Sparkfun 9 Degrees of Freedom - Razor IMU SEN-10736
  • Sparkfun 9 Degrees of Freedom - Sensor Stick SEN-10724
  • Sparkfun 9 Degrees of Freedom - Sensor Stick SEN-10183
  • DIYDrones ArduIMU+ V3
  • Generic MPU6050 Breakout boards (eg: GY-521, SEN-11028 and other MPU6050 wich have the MPU6050 AD0 pin connected to GND.)

Note for FreeIMU v0.1 and 0.2 users: from April 2011 the default magnetometer configuration is for HMC5883L. In order to use the library with HMC5843 (v0.1 and v0.2) edit the file HMC58X3.h and uncomment the line #define ISHMC5843.

FreeIMU Processing Programs
The FreeIMU library comes with Processing visualization demos. In order to use them, Download and install Processing. Copy the folders within the processing folder of the FreeIMU library archive into your Processing sketchbook.
Remember to change the Serial port address in the Processing code to match the address used by arduino on your system.

Ports to Other platforms

FreeIMU library on PIC 24 microcontroller by Hari Nair hair [dot] nair [at] gmail [dot] com. Author notes: 1. assumes a 6MHz crystal is attached and x4PLL internally, so Fosc = (6x4)/2 = 12 Mhz 2. trivial to use the internal FRC oscillator, instead of FNOSC_PRIPLL in the configuration words, use FNOSC_FRCPLL. This will give you Fosc = (8x4)/2 = 16MHz, but of course with less precision. 3. transmits ascii quaternion data at 38400baud. This does slow down the sampling rate. Without the quaternion print, the code completes in less than 10mS, so the sampling rate is exactly 100Hz as set by the timer.

FreeIMU library on NXP LPC1343 Cortex m3 processor by Hari Nair hair [dot] nair [at] gmail [dot] com. More details and possibility to contact the author on the FreeIMU community development forum.

Have you ported the FreeIMU library to other platforms? Please let me know and I'll list your work here!


A calibration GUI application is available. The software is currently in alpha state, however many people are already using it.

The calibration, when properly executed, drastically improve the orientation sensing performance of the FreeIMU framework. If you are experiencing drifting or inconsistent results, your sensors may need to be calibrated using the Calibration GUI.


There is now a FreeIMU Community website, which has been set up to become the central point of interaction between users of the FreeIMU framework. This is the place where you can get help, join others in developing new features, discuss IMUs applications and much more.

Previously we used FreeIMU answers on Launchpad as well as comments on Fabio's website for supporting users, however we decided to create an ad-hoc website to facilitate information gathering and collaboration between people.

Development, Bug Reports and Suggestions

Development of FreeIMU boards and libraries can be followed on FreeIMU project page on Launchpad which also hosts our software and hardware repository.

Suggestions or bug reports can be made on the FreeIMU Community, in the development forum.Previously bug reports were posted on the Launchpad bug reporting interface but that's not used anymore.

FreeIMU repository holds all the various library sources as well as design files and schematics. Everything is revisioned meaning that all the changes are logged and annotated.

The contents of the repository are available using Bazaar (bzr) with the command:
bzr co lp:freeimu

Never used bzr before? Not a big deal, it's very similar to git, svn or others. You may wanna have a look at the cheatsheet to have an overview of the commands available or read more documentation on bzr.

Alternatively, in case you have problems setting up bzr on your system, you can simply get the latest repository contents from here. The resulting file is a .tar.gz archive which can be opened with the excellent 7zip under Windows. Mac and Linux users shouldn't have problems opening such files.

The files on the repository can also browsed from a browser here. A list of recent changes is available here.

FreeIMU users videos

Here some videos made by FreeIMU users on their projects using FreeIMU.

rtsdrums flies like crazy with FreeIMU on his quadcopter.. check out the triple flip!

Warthox testing indoor FreeIMU v0.4r3 on one of his quadcopters.

Warthox stress test FreeIMU v0.3.5_MS on one of his quadcopters.

Chris uses FreeIMU on his VTOL EDF Tricopter powered by the MultiWii software.

Danilo Del Console uses FreeIMU in a 2 wheels self balancing robot.

Francesco Ferrara uses FreeIMU for a camera stabilization system.

Francesco Ferrara with his super fast implementation of the AHRS algorithm capable of displaying the rotating cube at 333Hz with FreeIMU! Great work!

Marchino65 with his first test with FreeIMU and the FreeIMU library on Arduino. The cube is spinning pretty good!

Francesco Ferrara in his first flight with FreeIMU on his very young quadcopter project called Simplo.

Seems that somehow Processing

Submitted by fabio on Wed, 2012-02-15 17:28.

Seems that somehow Processing is trying to compile something from the Android SDK wich you probably have installed.. I'm not sure how to fix this... probably changing the Processing mode into standard? See top right corner of Processing IDE.

I ran into a similar problem.

Submitted by Tom (not verified) on Wed, 2012-03-14 12:32.

I ran into a similar problem. It seems that the file sets processing into Android mode. The file should probably be removed from

gains in ADXL345.cpp

Submitted by fino (not verified) on Tue, 2012-02-14 08:35.

Hi Fabio, in the FreeIMU library there is ADXL345 driver directory which contain ADXL345.cpp file. In this file, I found there are gains values that will be multiplied with the accelerometer data. What is the function of the gains values? Is it for calibrating the accelerometer? thanks for your help :D

Yeah, I think that the

Submitted by fabio on Wed, 2012-02-15 14:44.

Yeah, I think that the original idea with gains was that.. however, I don't think I'm using them in the FreeIMU library.. so basically they are useless.

Dear Fabio many thanks for

Submitted by Hamid (not verified) on Sat, 2012-02-11 20:01.

Dear Fabio
many thanks for nice attention and share your project with all,
would you please aware me where we can download FreeIMU_cube processing?

Have nice time

See FreeIMU Processing

Submitted by fabio on Sat, 2012-02-11 20:48.

See FreeIMU Processing sketches under FreeIMU library above.

Free IMU Library example

Submitted by fino (not verified) on Thu, 2012-02-09 06:56.

Hi fabio,
I want to test my IMU Digital Coombo board form sparkfun and using your FreeIMU library example named FreeIMU_raw. Should I modify something in the code? because in my IMU board there are no magnetomter and barometer?


You can just edit the file

Submitted by fabio on Thu, 2012-02-09 11:06.

You can just edit the file FreeIMU.h and uncomment the line matching your board and comment the one enabled by default.

Baud Rates

Submitted by Sven (not verified) on Sun, 2012-02-05 00:32.

Hi Fabio!

How could I change the baud rate to 38400, and do you think this is still an acceptable baud rate for the sensors to function properly?


Just look in both the Arduino

Submitted by fabio on Sun, 2012-02-05 00:50.

Just look in both the Arduino and Processing programs for the number 115200 and change it to 38400. The library should work just fine at different speeds.


Submitted by Stanley (not verified) on Sat, 2012-02-04 20:13.

Hi Fabio!
Thank you very much for your help.
I have another question, I am trying using FreeIMU and ADXL345 mesure displacement. As you advised me before I have to:
1. compensate gravity vector:
2. double integrate
d(i+1) = V(i+1) ⋅ ∆t + d(i)
V(i+1) = a(i +1) ⋅ ∆t + V(i) ⇔ a(i +1) = a(i)
V(i+1) = sgn(a(i) − a(i+1) ) |a(i+1)| ⋅ ∆t + V(i) ⇔ a(i) +1 ≠ a(i)

One thing I do not know is: ∆t (probably it is obvious).
∆t - it is time between one measurement and another.
I am using "6 Degrees of Freedom ITG3200/ADXL345 " and Arduino Duemilanove, please, do you know what is ∆t? or how to measure it?

Kind regards,

Displacement, me too!

Submitted by Eric (not verified) on Wed, 2012-03-21 21:08.

Hi Stanley,

I'm trying to do the same thing using the "6 Degrees of Freedom ITG3200/ADXL345 ", and was wondering if you had made any progress?

I found this site;

and this article;

Which I've been drawing from to find a method of calculating displacement if they help at all.

I was forced to stop my project.

Submitted by Stanley (not verified) on Thu, 2012-03-22 09:42.

Unfortunately, because lack of the time, I was forced to stop my project.


Dear Stanley, I am very

Submitted by Optim (not verified) on Fri, 2012-03-02 13:57.

Dear Stanley,
I am very glad to hear that you would use the IMU to measure the displacement, because I also want to make this idea come true! While I am very dubious of the precision. Is it good enough to measure the displacement of 10 millimeter after I move the device to a place 100 meter away. Obviously the double integrate would change a very tiny offset into a large displacement!
Can you share me how to deal with the offset of IMU?

Hope you have a great success for you project!


precision wasn't good enought

Submitted by Stanley (not verified) on Thu, 2012-03-22 09:38.

Unfortunately, because of the offset, in my case, precision wasn't good enought


See the code from getQ

Submitted by fabio on Sun, 2012-02-05 00:48.

See the code from getQ function in FreeIMU.cpp:

now = micros();
sampleFreq = 1.0 / ((now - lastUpdate) / 1000000.0);
lastUpdate = now;

Your ∆t would be (now - lastUpdate) in microseconds. The formula above converts the ∆t into seconds and then computes the inverse to get the sample frequency.

ADXL345 +-2G range

Submitted by Stanley (not verified) on Thu, 2012-02-02 15:44.

Hi again,

I am using "6 Degrees of Freedom ITG3200/ADXL345 " and Arduino Duemilanove.
Do you know how to set +-2G range (lowest possible range)?


By default, if you use the

Submitted by fabio on Fri, 2012-02-03 10:12.

By default, if you use the FreeIMU library, the accelerometer already starts in +-2G mode.

In case you want to explicitly set that, you can call acc.setRangeSetting(2) within the FreeIMU::init function in the code relative to the ADXL345 (within #if HAS_ADXL345()).

Hope this helps.

output frequency

Submitted by Stanley (not verified) on Thu, 2012-02-02 15:34.


I am using "6 Degrees of Freedom ITG3200/ADXL345 ", do you know what what is the (Arduino) output frequency?


IMU freezes in less than one minute

Submitted by Anonymous (not verified) on Wed, 2012-02-01 06:57.

Hey, I just got a 6 Degrees of Freedom ITG3200/ADXL345 from sparkfun and your awesome software is the only code that i could get running, Thanks for letting your code work with sparkfun stuff! I'm new to IMU's and fairly inexperienced with the arduino board. But i am having a weird problem, anywhere from two seconds to one minute into testing the output, the sensor freezes. I tried to put pullup resistors(which made the sensor work for a longer time) on and then a logic level converter(which did nothing) but nothing seemed to work. Has someone experienced similar problems?

Same here! I think it's

Submitted by andre (not verified) on Wed, 2012-02-08 16:44.

Same here! I think it's improving if you change the baud rate to something lower, for example 9600. But it's still "crashing" on the speed test.

How do you guys have your

Submitted by fabio on Wed, 2012-02-08 18:22.

How do you guys have your board connected? You may want to lower your pullups values to 2.2K, disable the internal ones (the FreeIMU library will do it for you), and use smaller wires.

I got it to work!

Submitted by Sven (not verified) on Fri, 2012-02-10 07:02.

At least for me it was an easy fix, i was using 24 gauge wires with a bread board in-between my arduino and the sensor. It turns out that using 22 gauge wires with a direct connection fixed the problem. It might also be the re-soldered wires making a cleaner connection. Good luck trying to get yours to work.


Submitted by Patrick (not verified) on Mon, 2012-04-30 19:35.

OK, I've been battling this issue for the last couple of weeks. I can get the sensor to work, but at some quite random point that's usually at least a couple of minutes into a "run", the program freezes (aka locks up) with sufficient sensor movement.

My set up has the IMU on the end of a couple of 3-foot cables; one that transmits the SCL and SDA signals and another one for 3.3 V (coming from a regulated power supply -- NOT the Arduino). These cables actually have 1.35mm barrel jacks in the mid point so that the sensor can be disconnected for transportation purposes.

Oh well.

Guess I'll try making the connections shorter.

Are you using FreeIMU? If so,

Submitted by fabio on Tue, 2012-05-01 21:55.

Are you using FreeIMU? If so, I would suggest you to use it's integrated voltage regulator to power the board (by connecting it with a 5V source into the VIN pin). I suggest this because I believe you may have some bad noise or power problem into your 3V power source... also, check that your wires are small and short.

who drops the ball here?

Submitted by Patrick (not verified) on Tue, 2012-05-01 14:42.

So, last night I started another run and sure enough, after a random amount of time, the serial monitor froze.

At that point, all I did was disconnect and reconnect my SDA and SCL via the barrel jack. Upon reconnection, the serial monitor was immediately showing scrolling, correct data.

Who's dropping the ball here? If the Arduino had overflowed a buffer, seg faulted, lost a pointer to a register, ... whatever, why then did a simple disconnect/reconnect of the clock and data bring the program back from the dead?

Thanks, I will try this

Submitted by andre (not verified) on Fri, 2012-02-10 11:35.

Thanks, I will try this later, I have a PCB coming up to solder it to.
Currently I'm also using a breadboard. I noticed that when I'm only using the ADXL345 through just the ADXL library, everything is fine. For now I'm not interested in the Gyro, so I didn't do more poking around there.

Sample program!

Submitted by Anonymous (not verified) on Sun, 2012-01-22 01:09.

Hello im a newbee! Is their a sample program here? For sparkfun 6 dof combo board..?

I suck at looking!


That board is supported. Just

Submitted by fabio on Sun, 2012-01-22 09:30.

That board is supported. Just install the FreeIMU library as explained and uncomment your board configuration in FreeIMU.h.


Submitted by Anonymous (not verified) on Mon, 2012-01-23 06:22.

what code i will upload in the arduino??

is it he freeIMU examples??

thanks alot!

Once you installed the

Submitted by fabio on Mon, 2012-01-23 10:04.

Once you installed the library, you'll see some examples coming up in the File->Examples of the Arduino IDE.

New library error

Submitted by Luc Paquin (not verified) on Wed, 2012-01-18 04:00.

Dear Fabio,

I was just reviewing and testing the latest version of the library (20120114) and found that it did not compile if you use one of the 9DOF Sparkfun IMU's.

In FreeIMU.h line 53 in your IS_9DOM() Define you forgot to add the defines for the new boards you added, thus when you compile selecting one of those boards, on line 207 of FreeIMU.ccp the AHRSupdate function does not get defined when you compile.

All in all great work from the limited testing I did so far. I am looking forward to get a few of your boards for testing in the future.

BTW, I just did some quick tests after compiling with the above fixed with a SEN_10724 IMU and the reading are bouncing all over the place and never settle down. With the previous version of the library they were bouncing a lot at first, but settled down after 20-60 seconds. Any idea what might be causing this? I am using an Arduino Mini Pro 328p 3.3V for testing.

I will do some further testing in the morning when I have some time and try to isolate from which chip is coming the unstable readings. I will let you know as it might be a faulty board. I think I have another one so I will see if I can isolate the problem with another IMU or Arduino type too just in case.


According to some comments on

Submitted by fabio on Wed, 2012-01-18 09:22.

According to some comments on that board web page, Sparkfun guys screwed up some caps on the board, resulting in a lot of noise from the accelerometer. Seems that adding a tantalum caps in parallel to the output caps from the voltage regulator fixes the problem.

I'll be fixing the issue that you discovered with the code in the next library update. Thanks for your help.

Hi Fabio, I was curious as to

Submitted by Winston (not verified) on Tue, 2012-03-06 11:58.

Hi Fabio,

I was curious as to whether you've looked at implementing a digital low-pass filter to reduce the noise

I have been experimenting a little in an older version of your IMU library inside the FreeIMU::getValues function to implement a simple LP filter.

#define LP_FILTER_ALPHA 0.2331 // = dt / (RC + dt)

//inside FreeIMU::getValues
if(useLPFilter) //perform basic LPF
//filteredValues defined in FreeIMU header file
for(int n=8;n>=0;--n)
values[n] =filteredValues[n] + LP_FILTER_ALPHA (values[n]-filteredValues[n]);
filteredValues[n] = values[n];

I used this on a sparkfun 9DOF board and it seems to smooth out the noise quite nicely. Not quite as elegant as soldering some caps on the board but then again my soldering skills are pretty terrible. Do you think this approach will cause any issues in the imu algorithm?

I'm generally against

Submitted by fabio on Tue, 2012-03-06 13:46.

I'm generally against software fixes for electrical and mechanical issues. This kind of fixes always burns you in the long run so you'd better fixing it in the hardware.

I don't think this approach will cause you issues a part some latency. Another possibility is using the on-sensors LPF capabilities of the ADXL345.

Quick Question

Submitted by Luc Paquin (not verified) on Thu, 2012-01-19 04:43.

Dear Fabio,

One quick question. I checked a few SEN-10724 I had at hand with your library and using the getRawValues routine from the library I get rock solid readings at rest (within 1-3 counts) If I use the getYawPitchRoll or getEuler at rest the angles are flying all over the place. What could be the problem? Shouldn't the angle readings be stable too if the raw data is stable? Am I doing something wrong?


What does happen when you run

Submitted by fabio on Thu, 2012-01-19 09:18.

What does happen when you run the FreeIMU_cube processing example with FreeIMU_quaternion?

Found the problem

Submitted by Luc Paquin (not verified) on Thu, 2012-01-19 23:21.

This bothered me too much, so I spent the day debugging and found the problem. It was not related to the library at all, or at least I do not think so. Your test quaternion app was working great, and when I was using the same code in my test application which contains lots of other code the data was fluctuating wildly. Strangely enough the same test application does not show that fluctuation if I use your getRawValues routine, just with the quaternion and angle one.

I spend the day compiling and testing my app with features commented out or removed until I remove Wire code for a battery fuel gauge. It was not used, but was called in an unused routine, thus it was compiled with the rest of the application. When that was commented out everything started working properly.

I have no idea why that unused Wire code was causing the problem with the fluctuating data, and only in the angles and Q routines and not in the raw data routine, but at least I found the problem. The strange thing is that if I move those routines to the FreeIMU library instead of leaving it in my apps, all works properly so it is not the code itself.

If you have any ideas of what might be going on the let me know as I am somewhat at lost. At least I will be able to sleep tonight as I found the problem.


Well, that's almost

Submitted by fabio on Fri, 2012-01-20 00:18.

Well, that's almost impossible to say. I don't have any idea of what your code could do. SRAM corruption due to fulling it up?

It works

Submitted by Luc Paquin (not verified) on Thu, 2012-01-19 16:13.

I just tested the cube example and it works perfectly. Nice and stable with smooth tracking of the movements of my wireless test rig. I guess that isolate the problem to the software and the angle computations. I will do further test with the quaternions as a base, and then test again the ypr and Euler routines when I have a bit a free time over the next few days.

This is for a personal project I plan for the next few months and I have to deliver some real work in the coming days, so I need to stop playing and get working. I will let you know what I find out when I test the angle routines again.

Keep up the great work!



Submitted by Luc Paquin (not verified) on Wed, 2012-01-18 15:22.

Thanks for the tip on the Sparkfun board. I will look it up and try that fix and see if it solves the issue.

Keep up the great work and if I find anything else while reviewing the code I will let you know.


Magnetometer use

Submitted by Andrzej Zaborowski (not verified) on Fri, 2011-12-30 22:14.

Hi Fabio,
I'm not using the FreeIMU hardware, instead I have a tiny IMU made of two boards glued together: CMPS09 (magnetometer + accelerometer) and a Wii MotionPlus board as gyroscope. Together they're similar in size to the FreeIMU, but the gyroscope (IDG-650) is probably of much lower quality. They only cost eur30.

But I decided to use your extended Kalman filter implementation and the demo Processing apps because they're nice for debugging. To help debugging I'm also sending the accelerometer & magnetometer readings to the PC beside the quaternion, so that the cube demo displays the current gravity & magnetic field vectors as lines. Once everything is working I'm going to rewrite the AHRS in fixed-point arithmetics.

In the code I'm checking that the two reference vectors are in a sensible range before using them for correction (acceleration between 0.7g and 1.3g, and field magnitude between 0.25 and 0.65 gauss). Also I set twoKi very low or zero because it doesn't seem to be helping.

I have some questions about the use of the magnetic field vector:

  • when the FreeIMU library calculates the reference direction of geomagnetic field it uses the current readings (mx, my, mz) as input. I guess what it's trying to do is assume that the current orientation is correct except for the yaw/azimuth, so that the magnetometer is only used for yaw correction. However, wouldn't it be much better to use all of the magnetometer data? In UAVs the accelerometer readings are often useless because they are so dependent on the current orientation. A plane or a helicopter always accelerates in the same direction relative to its motors, so the accelerometer reading depends very little on gravity. So (if you're flying away from power lines etc.) the magnetometer is much more reliable than the accelerometer. So I'd like to give it a higher weight. I was thinking of taking a reference field vector when arduino initialises, and then rotating that vector using the current quaternion and taking the cross product against the current reading and adding the result to "halfe". Wouldn't that work better than the current code?
  • does the magnetometer need to be calibrated before using your AHRS implementation? There's a comment that says something about a magnetic distortion compensation algorithm from Sebastian Madgwick. Does that mean that the magnetometer doesn't need to be calibrated for "hard iron" offset etc?
  • is the normalisation of the two reference vectors necessary? I think the AHRS might work slightly better without the normalisation (and faster), provided the vectors are in a sensible range.


I now use a reference

Submitted by Andrzej Zaborowski (not verified) on Tue, 2012-01-03 04:04.

I now use a reference magnetic vector sampled when the AHRS initialises, instead of calculating some reference vector based on the current measurement. This seems to work well outdoor.

Some other changes I have made to get better reliability or performance:

* instead of using 1 / sampleFreq, I take a difference between the timestamp of the previous update and the current update, since the periods are not always equal when using interrupts.

* the common calculations, q0q0, q0q1 and so on... I made those variables global instead of local, and I calculate them *after* every update instead of *before*. This way they can be used in many calculations, like the Yaw/Pitch/Roll / euler angles, and also during the quaternion normalisation. Remember to disable the interrupt flag when updating these values, and then reenable, to avoid race conditions.

* instead of calculating q0q1 = q[0] * q[1] and so on, I set q0q1 to 2.0 * q[0] * q[1]. Only q0q0, q1q1 and q2q2 are not duplicated. This simplifies all of the later calculations. And the "half" variables are no longer halved.

* I added local_to_global and global_to_local static inline methods which can be used for translating vectors between local and global frame. I also use it inside the ahrs_update function now when calculating the estimated gravity and magnetic field.

* I got rid of q3q3, this saves one variable and one multiplication. q3q3 can be easily avoided in all formulas.

* The quaternion is normalised only once every 32 updates instead of always.

For my project I rewrote the AHRS in C (instead of C++) because the rest of my auto-pilot is written in pure C.

Source code?

Submitted by Anonymous (not verified) on Tue, 2012-01-03 07:56.

Hi Andrzej

Do you have your source code somewhere publicly available?


I uploaded my ahrs code at

Submitted by Andrzej Zaborowski (not verified) on Fri, 2012-01-13 01:16.

I uploaded my ahrs code at github now that I smoothed it out a little. I don't expect it'll be useful to you (since it's not an arduino library FreeIMU) unless you're starting from scratch.

One other change I made, which may be useful to others is instead of resetting the quaternion to [1, 0, 0, 0] at start, I calculate the exact current value based on averaged accelerometer and magnetometer readings. This way there is no "catch up" period when you start updating the quaternion, and the integral part of the kalman filter doesn't build up.

Today I made a demo video with FreeIMU demos :)

Did you dig into magnetometer

Submitted by fabio on Fri, 2012-01-13 10:55.

Did you dig into magnetometer calibration? I'll be working on it soon and I'd like to know if you made any progress on this.

Magnetometer calibration

Submitted by Andrzej Zaborowski (not verified) on Fri, 2012-01-13 17:46.

I did before and the rule generally is that you just need to add a constant vector to whatever vector is returned by the magnetometer. This works on the following "ideal world" assumption:

* the sensor is mounted on a rigid body that has no moving iron parts.
* the world around it also has no moving parts, except that one body :)

So you want to measure the magnetic field vector as if your rigid body wasn't there. All you need to do is record the measurements from the magnetometer as you spin the body in all the possible directions, and you'll have a sphere of points at more or less equal distance from the centre. Then the centre equals the calibration vector that you need to subtract from your readings so after that the sphere should be centered at 0, 0, 0 and then you can assume the readings are pretty much correct.

What I do is just take the max and min value in each axis and assume that the middle of the sphere is (max + min) / 2.

You could do the same thing with just 6 measurements but you'd need to point the sensor in the exact north, south etc. directions.


Submitted by Tuomas (not verified) on Fri, 2012-01-13 08:07.

Thanks for the code, I'll check it at some point.

And yes, we are starting from scratch with our own Cortex-M4 based board and our own IMU (which we don't have even yet). The IMU will probably be a FreeIMU clone in a form factor fitting our board.

I've played a bit on Linux running on OMAP3 based Gumstix. I have a not-so-good IMU attached to it and two motors. The PID and AHRS algorithms are borrowed from some Arduino project. I've been trying to stabilize it using two motors but it's far from stable.

It's calculating the AHRS and updating the motors now roughly 90Hz but I don't know if Linux is causing just too much latency there or are my borrowed algorithms bad or what.

Anyway, I'm getting tired to trying to get it to run on Linux and I'll continue when we have it on Cortex-M4. And the software will also be more heavily copied from a known working project :)

FreeIMU 035bmp current consumption

Submitted by Richard (not verified) on Wed, 2011-12-21 15:25.

Hi Fabio,
I have completed the FreeIMU 035bmp board and put on to test. Well, may be my soldering skill very suck, the data was not stable. I tested the current consumption of the board and found it eat 110mA of current. While the MIC5203 3.3V is rated 85mA max. I assume there might be some short circuit or leakage on my board. Could you advice what is the current consumption of this board? May be the flux residue on the board suck moisture and caused short circuit and leakage..., any suggestion is appreciated! Many many thanks!
Best regards

Great you have built your

Submitted by fabio on Wed, 2011-12-21 15:33.

Great you have built your board! But, it does look you still have some problems... you probably have some short somewhere.

Btw, measured current consumption of v0.3.5_MS (don't have BMP values, but don't expect them to be much different):

  • 2.8mA when powered using 5V through the integrated voltage regulator
  • 2.5mA when powered directly from 3V3.