In March, I posted on experimenting with the MPU-6050 IMU chip (mounted in a GY-521 breakout board). It seems that many people are using the MPU-6050, and I wanted to follow up with some more information, because there are better ways to access and process the combined sensor data than were demonstrated in that post. The previous experiment compared the raw data from the 3-axis accelerometer and 3-axis gyroscope sensors to the results when the raw data are combined via a complementary filter.
For the comparison, I had adapted a program from the Arduino Playground Wiki on MPU-6050 to pull the raw accelerometer and gyroscope data from the MPU-6050, The program calculated pitch, roll and yaw (rotation about the X, Y and Z axes, respectively, also knows as Euler Angles). These calculations were limited by certain properties of both the accelerometer and gyroscope. Gyroscope data has a tendency to drift with time, and accelerometer data is noisy and makes it difficult to calculate rotations over ranges greater than 180 degrees. The formulas(*) for computing roll, , and pitch, , (you can’t compute yaw, from accelerometer data) from the accelerometer readings are:
The range of the function is , which determines the range of motion you can detect easily from the IMU using these functions. Additionally, using Euler angles for the rotation calculations can lead to a problem known as Gimbal Lock. Because Euler angle rotations are performed in sequence (e.g, roll, pitch, and then yaw), problems arise when the second rotation in the sequence approaches 90 degrees (), because this brings first and third rotation axes into alignment with each other. This concept is tricky to explain, but the YouTube video below does quite a good job with it:
One way to avoid the problems with Euler angles is to use an alternate method of representing rotation called quaternions. Quaternions describe rotation in three dimensions by using four scalar values. Three of these scalars define an axis, and the fourth specifies a rotation around that axis. I won’t go into the mathematics of quaternions which is fairly complicated, and which I’m just starting to learn myself. The salient points of quaternions are that they avoid the problem of gimbal lock and can represent rotations over ranges of greater than 180 degrees without difficulty. Additionally, they have some useful mathematical properties, such as allowing for straightforward interpolation between two quaternions, which can be useful in animation, and reducing round-off error when multiple rotation operations are performed in sequence.
Using the DMP for Data Processing
The MPU6050 IMU contains a DMP (Digital Motion Processor) which fuses the accelerometer and gyroscope data together to minimize the effects of errors inherent in each sensor. The DMP computes the results in terms of quaternions, and can convert the results to Euler angles and perform other computations with the data as well. Invensense will not reveal the algorithm that they use to combine the data, but I was curious to see how the results the DMP produces compare to those I had computed with a complementary filter.
Therefore the next step was to figure out how to extract data from the DMP. Fortunately, Jeff Rowberg has written and made public a very useful library, i2cdevlib, which does just that. It is available for download at: https://github.com/jrowberg/i2cdevlib. To use it with the MPU 6050, you will need the library functions in the folder labeled Arduino/MPU6050. To install the library, simply copy the Arduino/MPU6050 folder to the same location as your other Arduino libraries.
I used an Arduino Nano and GY-521 breakout board containing the MPU-6050 to run the demos. This setup requires the following connections: (Arduino<->GY-521)
- 5V<->VCC (the GY-521 contains a voltage regulator and can use 3.3V or 5V)
- Arduino Pin 2<->INT (used for interrupts)
The Teapot Demo
The MPU6050 library contains a folder called “Examples”, with a demo called MPU6050_DMP6. Inside that folder are an Arduino sketch, MPU6050_DMP6.ino, to read quaternion data from the DMP and send it over the serial port, and a Processing sketch, MPUTeapot.pde, to read the data from the serial port and display the rotations graphically.
The demo ran more or less right out of the box, with a few tweaks. The only change I made to the Arduino sketch was to reduce the Serial port communication rate from 115200 to 38400 (This is set on line 163 of the sketch) . The 115200 rate seemed to overwhelm the Nano, but the 38400 rate worked well.
The Processing sketch is called MPUTeapot.pde, even though the figure it displays is a 3-D arrow, not a teapot. I assume that earlier versions of this sketch showed a teapot. I’ve seen some working demos with the teapot version online, e.g. this YouTube video:
If you are going to run this example, make sure you use the 32-bit version of Processing, since last I checked, it is the only version that works with serial communications.
To get the Processing sketch working, I had to make the following changes:
- Changed the Serial port data rate to 38400 to match the Arduino rate. I also specified which serial port to read the data from.
- The data, which comes across the Serial port in 14 byte packets was not getting properly aligned. Each 14-byte packet starts with the ‘$’ character, so I modified the program to ignore all bytes read before the first ‘$’.
- The Processing sketch sends a character over the serial port to the Arduino to tell it to begin sending data. I found that the sketch was hanging here, so I had the Processing sketch send over a couple of additional characters for good measure. It seemed to fix the problem. You can download my slightly modified version of the Processing sketch here:
Below is a video demonstration of the “teapot” demo sketches. The 3-D airplane/arrow in the Processing sketch follows the rotation of the IMU without significant jitter or lag. In addition, the demo easily performs rotations of any angle, even those greater than 180 degrees. What was also interesting is that for the first few seconds, the figure shows significant yaw drift, but after about 8 seconds of keeping the IMU motionless, the drift stops. I presume the DMP performs some sort of calibration to correct for the yaw drift. The complementary filter I had used in my previous post was able to correct for gyroscope drift in pitch and roll by combining accelerometer and gyroscope data on these axes, but since accelerometers don’t provide yaw, it was not able to correct for the yaw drift. I think that, unless you have good calibration and data fusion algorithms, there is a significant advantage to using the DMP calculated data.
I am working on a side-by-side comparison of DMP data vs. the complementary filter discussed in my previous post about the MPU-6050, and hope to be writing it up soon.
(*) As an unrelated aside, I’ve just discovered the use of LaTeX for formatting equations within WordPress, and I’m having a lot of fun with it.