MPU-9150 9-axis IMU, Magnetometer - Page 1
Forum section: electronics / projects

author: ryann
author_rank: Contributor
timestamp: April 16, 2013, 04:52:01 pm
content: Hey everyone,For my undergraduate senior design project, I'm working on a UAV in a blimp package. In order to maintain orientation, we're using the InvenSense MPU-9150 IMU to keep track of orientation and heading. After reading the vague data sheet on the magnetometer, and looking at other source code, I can read the flux in all 3 axes. I believe the measurements are correct. I get about 50uT in either X or Y, and about 60uT on Z. The problem is the X and Y don't change signs, either negative, or positive, as I rotate the sensor 180°. Because of this, I have a huge dead band on my sensor. It also can get to a point where it flips signs quickly, really throwing off the heading.The MPU-9150 uses the MPU-6050 IMU along with an AK8975 magnetometer integrated into a single package.Since I don't have much experience with magnetic flux of the earth or magnetometers in general. Any suggestions or tips?

author: ryann
author_rank: Contributor
timestamp: April 16, 2013, 05:00:08 pm
content: Some more information...We're using Sebastian Madgwick's IMU filter. It works very well with just the accelerometer and gyroscope, but with the magnetometer messed up, it always reverts back to the heading the magnetometer is reporting.Of course, the magnetometer corrects gyro drift and the gyro corrects magnetometer noise.Here's a video demo.http://youtu.be/PUNxwl8MX50

author: Smokey
author_rank: Super Contributor
timestamp: April 16, 2013, 06:49:14 pm
content: One of the benefits of using parts from a real company, as opposed to open source stuff from sparkfun for instance, is you can call them up and ask technical support. Their applications engineers might even help with your design. That is a really cool resource that a lot of people don't take advantage of enough. Worth a shot at least.

author: ecat
author_rank: Frequent Contributor
timestamp: April 16, 2013, 06:59:05 pm
content: From the data sheetQuoteGet rid of the filter for now.What arerawX values for the magnetometer when you rotate it? 0deg, 90deg, 180deg, 270deg. Let's say 0deg is angle that returns arawX value of 0. Repeat the test for Y and Z.Quote from: Smokey on April 16, 2013, 06:49:14 pmDon't get me started on SparkFun. I wasted the best part of a month on their SEN-10724 - poor design (under speced caps so quite a lot of noise) and what turned out to be a defective magnetometer with an unusable asymmetric range of +700 to -200 in X and Y

author: ryann
author_rank: Contributor
timestamp: April 17, 2013, 01:20:46 am
content: Okay guys.. here's the code I'm using. It's built on ESOS (http://www.ece.msstate.edu/courses/ece3724/main_pic24/docs/_e_s_o_s.html), which is an operating system for the PIC microcontroller developed by one my professors.Here's the code:Code:/** File: MPU_Test.c* Author: Ryan Nazaretian** Created on April 16, 2013, 4:47 PM*/#include "esos.h"#include "esos_pic24.h"#include "MPU.h"#define MPU_SLAVE_ADDRESS0xD0 // 0x68 << 1 == 0xD0#define MPU_REG_INT_PIN_CFG0x37 // Configures the behavior of the interrupt signals at the INT pins#define MPU_INT_PIN_CFG_I2C_BYPASS_EN0x02 // If 1 and I2C_MST_EN = 0, the host application processor will be able to directly access the auxiliary I2C bus#define MPU_MAG_I2C_ADDR0x18 // 0x0C << 1 == 0x18#define MPU_REG_MAG_WIA0x00 // When read, should report 0x48#define MPU_REG_MAG_CNTL0x0A#define MPU_MAG_SINGLE_MRMNT0x01 //Single measurement mode// ST1 Register - Contains Data Ready Bit#define MPU_REG_MAG_ST10x02#define MPU_MAG_ST1_NORMAL0x00#define MPU_MAG_ST1_READY0x01// ST2 Register - Contains Data Read Error and Magnetic Sensor Overflow Data#define MPU_REG_MAG_ST20x09#define MPU_MAG_ST2_DERR0x04#define MPU_MAG_ST2_HOFL0x08// HXL to HZH - Contains Measurement Data#define MPU_REG_MAG_HXL0x03 //Magnetometer X-Axis Low Byte#define MPU_REG_MAG_HXH0x04 //Magnetometer X-Axis High Byte#define MPU_REG_MAG_HYL0x05 //Magnetometer Y-Axis Low Byte#define MPU_REG_MAG_HYH0x06 //Magnetometer Y-Axis High Byte#define MPU_REG_MAG_HZL0x07 //Magnetometer Z-Axis Low Byte#define MPU_REG_MAG_HZH0x08 //Magnetometer Z-Axis High ByteESOS_USER_TASK(ReadMagnetometer){static UINT16 U16_MagX, U16_MagY, U16_MagZ;static uint8 u8_WIA, u8_ST1, u8_ST2;ESOS_TASK_BEGIN();// Set clock to Phase Locked Loop - Gyroscop X-Axis ReferenceESOS_TASK_WAIT_ON_WRITE2I2C1(I2C_WADDR(MPU_SLAVE_ADDRESS), MPU_REG_PWR_MGMT_1, MPU_PWR_MGMT_CLKSEL_PLL_X);// Enable I2C Bypass to talk to the AK8975 MagnetometerESOS_TASK_WAIT_ON_WRITE2I2C1(I2C_WADDR(MPU_SLAVE_ADDRESS), MPU_REG_INT_PIN_CFG, MPU_INT_PIN_CFG_I2C_BYPASS_EN);// Poke the AK8975 to see its Who Am I (WIA), which should return 0x48ESOS_TASK_WAIT_ON_WRITE1I2C1(I2C_WADDR(MPU_MAG_I2C_ADDR), MPU_REG_MAG_WIA);ESOS_TASK_WAIT_ON_READ1I2C1(I2C_RADDR(MPU_MAG_I2C_ADDR), u8_WIA);// Print off WIA Register ReadingESOS_TASK_WAIT_ON_AVAILABLE_OUT_COMM();ESOS_TASK_WAIT_ON_SEND_STRING("MPU> MAG> WIA Register: Expected 0x48, Read ");ESOS_TASK_WAIT_ON_SEND_UINT8_AS_HEX_STRING(u8_WIA);ESOS_TASK_WAIT_ON_SEND_UINT8('\n');ESOS_TASK_SIGNAL_AVAILABLE_OUT_COMM();while(TRUE){// Tell AK8975 to take a measurementESOS_TASK_WAIT_ON_WRITE2I2C1(I2C_WADDR(MPU_MAG_I2C_ADDR), MPU_REG_MAG_CNTL, MPU_MAG_SINGLE_MRMNT);// Wait for data to returndo{ESOS_TASK_WAIT_ON_WRITE1I2C1(I2C_WADDR(MPU_MAG_I2C_ADDR), MPU_REG_MAG_ST1);ESOS_TASK_WAIT_ON_READ1I2C1(I2C_RADDR(MPU_MAG_I2C_ADDR), u8_ST1);ESOS_TASK_YIELD();} while(u8_ST1 != MPU_MAG_ST1_READY);// Read ST2 StatusESOS_TASK_WAIT_ON_WRITE1I2C1(I2C_WADDR(MPU_MAG_I2C_ADDR), MPU_REG_MAG_ST2);ESOS_TASK_WAIT_ON_READ1I2C1(I2C_RADDR(MPU_MAG_I2C_ADDR), u8_ST2);// Print ST2 StatusESOS_TASK_WAIT_ON_AVAILABLE_OUT_COMM();ESOS_TASK_WAIT_ON_SEND_STRING("\nMPU> MAG> Status 2: ");ESOS_TASK_WAIT_ON_SEND_UINT8_AS_HEX_STRING(u8_ST2);if(u8_ST2 & MPU_MAG_ST2_DERR)ESOS_TASK_WAIT_ON_SEND_STRING("\nMPU> MAG> Data Read Error occurred.");if(u8_ST2 & MPU_MAG_ST2_HOFL)ESOS_TASK_WAIT_ON_SEND_STRING("\nMPU> MAG> Magnetic sensor overflow occurred.");ESOS_TASK_WAIT_ON_SEND_UINT8('\n');ESOS_TASK_SIGNAL_AVAILABLE_OUT_COMM();/********************************************************************** Page 21/33 of Data Sheet:* Addresses from 02H to 09H and from 10H to 12H are compliant with* automatic increment function of serial interface respectively.*********************************************************************/// Set Register to HXL (First register for measurement data)ESOS_TASK_WAIT_ON_WRITE1I2C1(I2C_WADDR(MPU_MAG_I2C_ADDR), MPU_REG_MAG_HXL);// Read Magnetometer X-AxisESOS_TASK_WAIT_ON_READ2I2C1(I2C_RADDR(MPU_MAG_I2C_ADDR), U16_MagX.u8Lsb, U16_MagX.u8Msb);// Read Magnetometer Y-AxisESOS_TASK_WAIT_ON_READ2I2C1(I2C_RADDR(MPU_MAG_I2C_ADDR), U16_MagY.u8Lsb, U16_MagY.u8Msb);// Read Magnetometer Z-AxisESOS_TASK_WAIT_ON_READ2I2C1(I2C_RADDR(MPU_MAG_I2C_ADDR), U16_MagZ.u8Lsb, U16_MagZ.u8Msb);// Print raw measurement dataESOS_TASK_WAIT_ON_AVAILABLE_OUT_COMM();ESOS_TASK_WAIT_ON_SEND_STRING("MPU> MAG> X-Axis: ");ESOS_TASK_WAIT_ON_SEND_UINT16_AS_HEX_STRING(U16_MagX.u16);ESOS_TASK_WAIT_ON_SEND_STRING("\nMPU> MAG> Y-Axis: ");ESOS_TASK_WAIT_ON_SEND_UINT16_AS_HEX_STRING(U16_MagY.u16);ESOS_TASK_WAIT_ON_SEND_STRING("\nMPU> MAG> Z-Axis: ");ESOS_TASK_WAIT_ON_SEND_UINT16_AS_HEX_STRING(U16_MagZ.u16);ESOS_TASK_WAIT_ON_SEND_UINT8('\n');ESOS_TASK_SIGNAL_AVAILABLE_OUT_COMM();// Delay 500msESOS_TASK_WAIT_TICKS(500);}ESOS_TASK_END();}void user_init(void){__esos_unsafe_PutString(HELLO_MSG);esos_pic24_configI2C1(400);esos_RegisterTask(ReadMagnetometer);}Here was the output:Code:MPU_Test.c, built on Apr 16 2013 at 19:36:05MPU> MAG> WIA Register: Expected 0x48, Read 0x48MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFC4MPU> MAG> Y-Axis: 0x007CMPU> MAG> Z-Axis: 0x009EMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFC2MPU> MAG> Y-Axis: 0x007AMPU> MAG> Z-Axis: 0x009CMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFC4MPU> MAG> Y-Axis: 0x007EMPU> MAG> Z-Axis: 0x009EMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFD2MPU> MAG> Y-Axis: 0x0074MPU> MAG> Z-Axis: 0x009CMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFD1MPU> MAG> Y-Axis: 0x0073MPU> MAG> Z-Axis: 0x0097MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFDDMPU> MAG> Y-Axis: 0x0073MPU> MAG> Z-Axis: 0x0095MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFEAMPU> MAG> Y-Axis: 0x0070MPU> MAG> Z-Axis: 0x0092MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFECMPU> MAG> Y-Axis: 0x006CMPU> MAG> Z-Axis: 0x0096MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFF0MPU> MAG> Y-Axis: 0x0066MPU> MAG> Z-Axis: 0x0092MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFF8MPU> MAG> Y-Axis: 0x005EMPU> MAG> Z-Axis: 0x0092MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFFDMPU> MAG> Y-Axis: 0x0057MPU> MAG> Z-Axis: 0x0095MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x0002MPU> MAG> Y-Axis: 0x0054MPU> MAG> Z-Axis: 0x0094MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x0007MPU> MAG> Y-Axis: 0x004DMPU> MAG> Z-Axis: 0x0095MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x0006MPU> MAG> Y-Axis: 0x004CMPU> MAG> Z-Axis: 0x0092MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x000BMPU> MAG> Y-Axis: 0x0047MPU> MAG> Z-Axis: 0x0097MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x0012MPU> MAG> Y-Axis: 0x0038MPU> MAG> Z-Axis: 0x0090MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x0017MPU> MAG> Y-Axis: 0x0037MPU> MAG> Z-Axis: 0x0091MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x0013MPU> MAG> Y-Axis: 0x0031MPU> MAG> Z-Axis: 0x0093MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x001BMPU> MAG> Y-Axis: 0x0029MPU> MAG> Z-Axis: 0x008FMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x0019MPU> MAG> Y-Axis: 0x001DMPU> MAG> Z-Axis: 0x0093MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x0010MPU> MAG> Y-Axis: 0x0012MPU> MAG> Z-Axis: 0x0094MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x0011MPU> MAG> Y-Axis: 0x0007MPU> MAG> Z-Axis: 0x0097MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x0008MPU> MAG> Y-Axis: 0xFFFCMPU> MAG> Z-Axis: 0x0098MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x0007MPU> MAG> Y-Axis: 0xFFFDMPU> MAG> Z-Axis: 0x0093MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFFFMPU> MAG> Y-Axis: 0xFFF7MPU> MAG> Z-Axis: 0x0093MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0x0002MPU> MAG> Y-Axis: 0xFFECMPU> MAG> Z-Axis: 0x008EMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFF5MPU> MAG> Y-Axis: 0xFFEFMPU> MAG> Z-Axis: 0x0089MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFF1MPU> MAG> Y-Axis: 0xFFE3MPU> MAG> Z-Axis: 0x0091MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFE7MPU> MAG> Y-Axis: 0xFFEBMPU> MAG> Z-Axis: 0x0099MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFE2MPU> MAG> Y-Axis: 0xFFEAMPU> MAG> Z-Axis: 0x009CMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFD1MPU> MAG> Y-Axis: 0xFFE7MPU> MAG> Z-Axis: 0x009DMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFCAMPU> MAG> Y-Axis: 0xFFE2MPU> MAG> Z-Axis: 0x009EMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFBFMPU> MAG> Y-Axis: 0xFFE5MPU> MAG> Z-Axis: 0x009BMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFB1MPU> MAG> Y-Axis: 0xFFE5MPU> MAG> Z-Axis: 0x009FMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFADMPU> MAG> Y-Axis: 0xFFE9MPU> MAG> Z-Axis: 0x00A1MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFA5MPU> MAG> Y-Axis: 0xFFF7MPU> MAG> Z-Axis: 0x00A1MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFF9DMPU> MAG> Y-Axis: 0xFFFBMPU> MAG> Z-Axis: 0x00A3MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFF9BMPU> MAG> Y-Axis: 0x0001MPU> MAG> Z-Axis: 0x00A9MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFF94MPU> MAG> Y-Axis: 0x0006MPU> MAG> Z-Axis: 0x00A2MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFF84MPU> MAG> Y-Axis: 0x0012MPU> MAG> Z-Axis: 0x009EMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFF87MPU> MAG> Y-Axis: 0x0027MPU> MAG> Z-Axis: 0x009FMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFF84MPU> MAG> Y-Axis: 0x003AMPU> MAG> Z-Axis: 0x009CMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFF86MPU> MAG> Y-Axis: 0x0042MPU> MAG> Z-Axis: 0x00A4MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFF86MPU> MAG> Y-Axis: 0x004CMPU> MAG> Z-Axis: 0x00A0MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFF8CMPU> MAG> Y-Axis: 0x0054MPU> MAG> Z-Axis: 0x009CMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFF97MPU> MAG> Y-Axis: 0x0061MPU> MAG> Z-Axis: 0x009DMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFA2MPU> MAG> Y-Axis: 0x0066MPU> MAG> Z-Axis: 0x00A0MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFA7MPU> MAG> Y-Axis: 0x006FMPU> MAG> Z-Axis: 0x009DMPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFAFMPU> MAG> Y-Axis: 0x0073MPU> MAG> Z-Axis: 0x0099MPU> MAG> Status 2: 0x00MPU> MAG> X-Axis: 0xFFC5MPU> MAG> Y-Axis: 0x0077MPU> MAG> Z-Axis: 0x0097I've attached the raw data as signed numbers, and converted (without sensitivity adjustment) to micro Teslas in CSV format.

author: ecat
author_rank: Frequent Contributor
timestamp: April 17, 2013, 02:14:14 am
content: I'm no expert on these things btw.Looking at your data I guess you rotated the board about the z axis.Your min X value is -124 while your max X value is only 27.Your min Y value is only -27 while your max Y value is 126.Not looking good to my untrained eyes.I was going to waffle on about circles and distortions but this guy knows his stuff, so...http://www.sensorsmag.com/sensors/motion-velocity-displacement/compensating-tilt-hard-iron-and-soft-iron-effects-6475Edit.Out of interest, if you turn the magnetometer so X is pointing down and rotate about X, what are your Y, Z values. It's worth repeating the same test with Y pointing down. As the link says, you are looking for symmetries and offsets, for sure the IMU filters I've looked at all assume perfect zero offset circles. With good luck you can compensate for any distortions, with bad luck one or more axis is so far off that your compensation looses so much resolution as to make it worthless.

author: ryann
author_rank: Contributor
timestamp: April 17, 2013, 02:55:43 am
content: I've attached the X and Y axis.Would the offset calibrations be something that we can rely on for every run, or would we need to recalibrate for each run?Totally didn't see the link. I'll get back after I read/think through it.

author: ecat
author_rank: Frequent Contributor
timestamp: April 17, 2013, 03:19:42 am
content: tehe re: linkCheck out this two part link too and let the SW do the work:http://sailboatinstruments.blogspot.co.uk/2011/08/improved-magnetometer-calibration.htmlI'm sure I have some different offset compensation SW somewhere but the above looks good.A quick look at your data gives the impression that the X, Y and Z values have a similar pattern, you're not working next door to the LHC are you? Big loud speakers? Try a different room or a different corner of the same room.

author: ryann
author_rank: Contributor
timestamp: April 17, 2013, 03:21:09 am
content: I saw the plots of what calibrated data looks like. I plotted our current data on a LabVIEW XY graph.Honestly, plotted out like this, it doesn't look too bad. Using offsets will help immensely. I'll check out that second link as well.X-Y Plot:X-Z Plot:Y-Z Plot:

author: ecat
author_rank: Frequent Contributor
timestamp: April 17, 2013, 03:36:21 am
content: Yep, two perfect circles and something that reminds me of an ex-girlfriend - that's what you get for dating amoeba. Looks good.

author: i_like_sparks
author_rank: Contributor
timestamp: October 08, 2013, 12:48:16 am
content: Reviving this thread as I'm currently working on something similar. I got the MPU-9150 to work with all the bells and whistles (FIFO, magnetometer) but I'm a bit underwhelmed by the accuracy of the magnetometer and was wondering what your experiences were.The magnetometer readings are quite noisy, I'd say the average noise level is around +/- 4-5 degrees. Also there is a systematic error, when I turn the unit by exactly 90 degrees the delta in the readings is 70-100 degrees, depending on the previous orientation. This is after calibration and tilt compensation.So the total accuracy is less than 10 degrees, which seems very high. I was wondering if anyone had similar experiences?