Clone this wiki locally
minimu9-ahrs is a program for reading data from the Pololu MinIMU-9 over I²C. It supports MinIMU-9 versions v0, v1, v2, and v3. The program can output the raw sensor data from the magnetometor, accelerometer, and gyro or it can use that raw data to compute the orientation of the IMU. This program was designed and tested on the Raspberry Pi, but it will probably work on any embedded Linux board that supports I²C with a device matching
/dev/i2c*. A Debian package is available for easy installation and the minimu9-ahrs source code is on github.
Getting started for experts
If you are an embedded Linux expert, the only getting-started instructions you will need are:
- Make an I²C bus device such as
- Power the MinIMU-9 and hook it up to your board.
- Install the latest minimu9-ahrs Debian package or compile minimu9-ahrs from source. Sorry, only armhf packages are available for the latest version.
- Calibrate the magnetometer by running
minimu9-ahrs-calibrateand turning the board in all directions.
First, you need to make sure your system supports I²C. Try typing
ls /dev/i2c*: if you don’t see a device there named something like
/dev/i2c-0 then your I²C is not enabled properly.
On a Raspberry Pi running Raspbian, the I²C support is provided by kernel modules named
i2c-dev. You should add these modules to the list in
/etc/modules so they get loaded automatically when you boot up. You should also add the line
dtparam=i2c1=on to the bottom of
/boot/config.txt to enable the Raspberry Pi’s external I2C interface. After making these changes, reboot. If you run
lsmod | grep i2c you should see the modules mentioned above, which means they were successfully loaded into the kernel. If you run
ls /dev/i2c* you should see `/dev/i2c-1`.
If this information doesn’t work for you, please search Google for tips about how to enable I²C for your particular board and your particular Linux distribution. When you find the answer, please add information to this wiki page to help other people in your situation.
One good source for how to configure your Pi for I²C is at Adafruit.
Another overview on connecting to the MinIMU-9 v2 is at OzzMaker.com.
After enabling the I²C devices, you should set them up so that your user has permission to access them. That way, you won’t have to run sudo.
groups to see what groups your user belongs to. If
i2c is on the list, then that is good. If you are not on the
i2c group, then you should add yourself to it by running
sudo usermod -a -G i2c `whoami`, logging out, and then logging in again. If your system does not have an
i2c group, you can create one or use a different group like
ls -l /dev/i2c* to make sure that your I²C devices have their group set to
i2c. The group name is shown in the fourth column, and will usually be
i2c. If the devices are not in the
i2c group, then you should fix that by making a file called
/etc/udev.d/rules.d/i2c.rules with the following line in it:
After making this file, you can make it take effect by running
sudo udevadm trigger (or rebooting).
If you get an error about permission being denied, double check that you have done these steps correctly.
The MinIMU-9 comes with male header pins and you will need to solder these into the board in order to make a solid connection.
You will need to power the MinIMU-9 and connect it to the I²C bus of your board. The correct connections for the Raspberry Pi are listed below:
|Raspberry Pi pin||MinIMU-9 pin|
|GPIO 0 (SDA)||SDA|
|GPIO 1 (SCL)||SCL|
Below is a picture with a MinIMU-9 v2 showing how to make those connections:
You will need four female-female jumper wires designed for 0.1"-spaced pins. Pololu’s Female-Female Premium Jumper Wires work well.
Determining which bus to use
The default I²C bus used by this program is
/dev/i2c-0. If you want to use a different bus then you will need to provide the
-b DEVNAME option to both
minimu9-ahrs-calibrate in the later steps.
For most Raspberry Pis, the exposed I²C bus is bus 1 instead of bus 0, so you will need to use
-b /dev/i2c-1 whenever you run minimu9-ahrs. However, on an early Raspberry Pi with 256 MB of memory, you should omit the
-b option to use
If you are not sure which bus to use, you could try running
i2cdetect on each available bus as described below.
Checking your setup
After you have enabled I²C, given yourself the proper permissions, soldered the MinIMU-9, and connected it to the Raspberry Pi, you should check your setup by running
i2cdetect. Try running
i2cdetect -y N, where
N is the number of the I²C bus you want to use (typically 1 or 0). The output should look similar to this. The exact output will depend on the type of IMU you are using, but the important thing is that the body of the printed table should contain two or three hex numbers, representing the addresses of I²C devices that were detected on the bus.
i2cdetect command is not recognized, you should install the
i2c-tools package. On Raspbian, you can run
sudo apt-get install i2c-tools to install it.
If you do not see two or three hex numbers in the body of the table, then make sure your soldering and wiring are correct and try selecting a different bus by changing the bus number argument
If you get a permission denied error, make sure you have configured the device permissions properly as described above.
If you get a “No such file or directory” error referring to your I²C device, make sure that you have properly enabled I²C as described above.
If you are using Debian or some other distribution that allows you to install
.deb package files, and you are using the armhf EABI (as opposed to armel), I recommend installing minimu9-ahrs using the Debian package. You can find the latest Debian package at http://www.davidegrayson.com/minimu9-ahrs/debian/ . Copy the URL of the latest
minimu9-ahrs_*.deb file, use the
wget utility to fetch it from the web onto your Linux board, and then use
dpkg -i to install it. For example, you could run the following commands to install a hypothetical version VERSION:
wget http://www.davidegrayson.com/minimu9-ahrs/debian/minimu9-ahrs_VERSION_armhf.deb dpkg -i minimu9-ahrs_VERSION_armhf.deb
(When you run the two commands above, you should replace VERSION with the actual version number you are trying to install, such as 1.2.3-4. I did not want to write real version numbers on this page because I might forget to update the page when I release a new version.)
Alternatively, you can install the program from source. Please see
README.textile in the source code repository for help.
Looking at raw values
As a first test, you should look at the raw readings from the sensors on your IMU to make sure it is OK. Run
minimu9-ahrs --mode raw. The output should look something like this:
-138 129 -416 112 -8 228 -50 14 9 -138 129 -419 120 -4 232 -49 20 18 -138 129 -419 116 -12 228 -51 15 8 -138 129 -419 116 -12 228 -50 21 17 -137 130 -421 116 -8 232 -51 22 11 -137 130 -421 120 -12 220 -56 20 14
Yes, there will be noise in all the readings, even if your IMU is not moving at all. That is totally normal for almost any kind of sensor.
This output consists of three vectors. From left to right they are the raw magnetometer reading, the raw accelerometer reading, and the raw gyro reading. Each vector consists of three integers, in X-Y-Z order. You should turn the device and make sure that the raw readings change correspondingly. For example, when the X axis of the board is pointing straight up, the accelerometer’s X reading (the 4th number on each line) should be positive and the other two components of the acceleration should be close to zero.
Calibrating the magnetometer
The magnetometer will need to be calibrated to create a mapping from the ellipsoid shape of the raw readings to the unit sphere shape that we want the scaled readings to have. The calibration feature for the minimu9-ahrs assumes that the shape of the raw readings will be an ellipsoid that is offset from the origin and stretched along the X, Y, and Z axes. It cannot handle a rotated ellipsoid. It is interesting to run
minimu9-ahrs --mode raw > output.tsv while moving the magnetometer and then make some scatter plots of the raw magnetometer readings in a spreadsheet program to see what shape the readings have.
The calibration is done with a shell script that pipes raw sensor readings from
minimu9-ahrs into a Python script. This requires Python and SciPy, and both of those should already be installed on your system if you installed the minimu9-ahrs Debian package. (I have only tested the script with Python 2; if you have to use Python 3 it might be possible to make it work with both and you should send me a copy of the improved script.)
To calibrate, run
minimu9-ahrs-calibrate and follow the on-screen instructions when they tell you to start rotating the IMU through as many different orientations as possible. Once the data is done being read, you can stop rotating the IMU and relax for about 20 minutes while the Python script figures out the optimal calibration. The calibration will be written to the file
The calibration file
~/.minimu9-ahrs-cal is simply a one-line file with 6 numbers separated by spaces: minimum x, maximum x, minimum y, maximum y, minimum z, maximum z. These numbers specify the linear mapping from the raw ellipsoid to the unit sphere. For example, if “minimum x” is -414, it means that a magnetometer reading of -414 on the X axis will get mapped to -1.0 when the readings are scaled.
Looking at Euler angles
minimu9-ahrs --output euler. It will print a stream of floating-point numbers, nine per line. The first three numbers are the pitch, yaw, and roll angles of the board in degrees. All three Euler angles should be close zero when the board is oriented with the Z axis facing down and the X axis facing towards magnetic north. From that starting point:
- A positive yaw corresponds to a rotation about the Z axis that is clockwise when viewed from above.
- A positive pitch correspond to a rotation about the Y axis that would cause the X axis to aim higher into the sky.
- A positive roll would correspond to a counter-clockwise rotation about the X axis.
The way you should think about it is that board starts in the neutral position, then the yaw rotation is applied, then the pitch rotation is applied, and then the roll rotation is applied to get the board to its final position.
Look at the Euler angle output as you turn the board and make sure that it looks good.
For more information about
minimu9-ahrs, including all the options it supports and a precise description of its output format, view the man page by running
Visualizing the orientation
The direction-cosine-matrix output from
minimu9-ahrs with no parameters can be piped into the ahrs-visualizer program to generate a slick three-dimensional view of the rotation. For more information, see the ahrs-visualizer tutorial.
When I made this program, I had several goals in mind.
First of all, this AHRS isn’t just for model planes. I wanted it to be generally useful, so I wanted to avoid making any assumptions about what orientation the IMU is in. Therefore, I wanted to use an algorithm that treats all three axes (X, Y, and Z) equally. I looked at existing algorithms that stored the current state as a Direction Cosine Matrix (DCM) and found that when they normalized the DCM, they usually treated one axis specially. For an example of this problem, see the algorithm presented in the “Renormalization” section of Direction Cosine Matrix IMU: Theory by William Premerlani and Paul Bizard. I decided to use a quaternion instead of a DCM to store the internal state because normalizing a quaternion is straightforward and treats all axes equally.
Secondly, I wanted to have “gyro only” and “compass only” modes as a tool for teaching people about how IMUs work and also to help troubleshoot systems where one of those components might be acting incorrectly. Therefore, I designed the program to have different sensor fusion algorithms in it and you can easily pick one at runtime with a command-line parameter.
Third, I wanted it to be easy to integrate the output of the program into a larger system. That’s why I send the output as numbers to the standard output pipe and provide several different output formats.
And finally, I wanted the code to have all the usual attributes that good code has. Short functions, small classes, and avoiding lots of magic numbers and global variables are some of the things I had in mind.