Simple Arduino code for MPU 9150 (Invensense) Help

Hi, I am a newbie. I need help in writing a simple code for MPU 9150 (Invensense) for use with an Arduino. The current code on github is chaotic and does not work properly. The MPU 9150 is a combination of a 3 axial accelerometer, 3 axial gyroscope and a 3 axial magnetometer.

You should at least post links to the git and to the datasheet of the sensor. (See the how to use this forum post on top)

The data sheet for the sensor is attached with this post. The links to the git are below. The problem for a newbie like me is that its hard to make sense of everything in the github code as well as the data sheet.

PS-MPU-9150A.pdf (3.95 MB)

The problem for a newbie like me is that its hard to make sense of everything in the github code as well as the data sheet.

I understand completely, learning new things can take a fair amount of time and energy, but "making your hands dirty by doing and trying" is most often the only way.
So feel free to ask if you have specific questions, many people have time for that.

I doubt if there are many people want to implement a library which they don't use themselves as most have their own projects. (I do).

Steps to take for such project:

  • learn about the communication protocol used - wikipedia describes most of them quite good -
  • try to understand the (base) physics of the sensor
  • get a good look at the graphics in a datasheet, what do they tell, is there a (non) linear relation between some parameters, is there a optimal area, variable error etc
  • does the device have registers for configuration, what do they do, e.g. the DS18B20 temperature sensor a alarm level register, some RealTimeCLocks have them too

in short learning is doing :wink:

Thank you for your feedback. The github code works. But its very long and big. Takes a lot of space. The whole idea of starting this post was to generate a short and crisp code and discuss ways of improving it. Learning is also part of the process.

I had a quick look at the code and, there is a lot of it, but it is well documented, that makes the code large.
The code makes quite some abstractions, and has a 2-layer architecture (if I am rigth) to hide the communication layer from the abstract class interface for the user.

Furthermore it is quite a complex sensor, with a rich interface.
What you can do is to remove the functions you do not need. // them

Thank you for the quick post. I need all the three functions from the sensor. Accelerometer, Gyroscope and the Magnetometer to function. My plan is to remove all the unnecessary code and make it short so that I get raw Accelerometer, Gyroscope and Magnetometer read out. I am not aiming for the digital motion processor.
Second I would like to modify the code so that it will enable me to set the accelerometer, gyroscope and magnetometer read out to zero when its kept flat on a table.

What you could do as a first exercise is to strip all but the accelerometer, and get that working.

By stripping you have to read the code carefully, so doing this 3 times for every function you become familiar with the code.
As said before it will take time :wink:

Thank you for the quick suggestion. I will start to re write the code for each individual device like accelerometer, Gyroscope and magnetometer so that I can understand the entire process step by step. But before that I wanted to get the code which has been posted on github to work. There is some problem with the code as I get readings for the accelerometer and gyroscope which change when I move my sensor. But I only get zero values for the magnetometer. I donot know why this happens. Please could you help me.

I get the following print out in the serial monitor when I run the github code.

a/g/m: 16032 1600 5080 53 -9 69 0 0 0
a/g/m: 16020 1640 4864 183 -462 -154 0 0 0
a/g/m: 15944 1560 4684 281 -717 -261 0 0 0
a/g/m: 15928 1656 4584 238 -507 -202 0 0 0
a/g/m: 15876 1836 4476 96 -89 -41 0 0 0
a/g/m: 15960 1692 4412 -55 340 176 0 0 0
a/g/m: 15952 1660 4600 -184 587 332 0 0 0
a/g/m: 15948 1656 4652 -208 533 364 0 0 0
a/g/m: 15884 1604 4932 -67 405 207 0 0 0
a/g/m: 16024 1612 4772 83 -37 1 0 0 0

The last three columns are for the magnetometer and they are only zero values. I am moving my device but I donot get any readout.

But I only get zero values for the magnetometer. I do not know why this happens. Please could you help me.

I have no such sensor, so that makes it quite difficult, sorry.

So the step is to isolate all the code for the magnetometer.
you can put Serial.print() statements after every step to trace what happens during execution.
Sometimes you only want conditional prints, like

if (someVar > someVale)
{
Serial.Println(someVar);
}

Hi, I am also kinda new to all this but I also have the MPU9150 on the Uno and was able to get it up and running and working in Unity. You might want to try this git instead of the one you have linked above:

https://github.com/Pansenti/MPU9150Lib

That one has some sketch examples as well...hope this helps!

Thank you for directing me to Pansenti code. It is a good piece of work. But unfortunately if you want to make any changes or request the author for help he asks you to pay up for any assistance.
So I went to write my own code. Its still underdevelopment but the basic problems are solved.

Hi,

I need to sample data at 3 millisecond interval from MPU9150. But currently I am able to sample it at 18 millisecond interval. Please suggest how I can improve the sampling rate. I am not using any delays. The code is below.

/ Include the following Arduino library

#include "Wire.h"

// Include the following libraries for the MPU 6050 IC, I2Cdev and AK8975 (Magnetometer)

#include "I2Cdev.h"
#include "MPU6050.h"
#include "AK8975.h"

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
AK8975 mag(0x0C);
MPU6050 accelgyro;
unsigned long time;

int16_t ax, ay, az;
int16_t gx, gy, gz;
int16_t mx, my, mz;

float heading;

#define LED_PIN 13
bool blinkState = false;

void setup() {
// join I2C bus (I2Cdev library doesn't do this automatically)
Wire.begin();

// Set baud rate to 115200 (figure out ways to double it)
Serial.begin(115200);

// initialize device
Serial.println("Initializing I2C devices...");

accelgyro.initialize();
accelgyro.setI2CBypassEnabled(true);
mag.initialize();

// verify connection
Serial.println("Testing device connections...");
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
Serial.println(mag.testConnection() ? "AK8975 connection successful" : "AK8975 connection failed");

accelgyro.setFullScaleAccelRange(0);

// configure Arduino LED for
pinMode(LED_PIN, OUTPUT);
}

void loop() {

time = millis();
//prints time since program started

// read raw accel/gyro measurements from device
accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
mag.getHeading(&mx, &my, &mz);

// these methods (and a few others) are also available
// accelgyro.getAcceleration(&ax, &ay, &az);
// accelgyro.getRotation(&gx, &gy, &gz);
// mag.getHeading(&mx, &my, &mz);

// display tab-separated accel/gyro x/y/z values
// Serial.print("a/g/m/Time:\t");
Serial.print(ax); Serial.print("\t");
Serial.print(ay); Serial.print("\t");
Serial.print(az); Serial.print("\t");
Serial.print(gx); Serial.print("\t");
Serial.print(gy); Serial.print("\t");
Serial.print(gz); Serial.print("\t");
Serial.print(mx); Serial.print("\t");
Serial.print(my); Serial.print("\t");
Serial.print(mz); Serial.print("\t");
Serial.println(time);

// blink LED to indicate activity
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
//delay(10); // run at ~100 Hz
}

your sensore ARE running faster than you need, BUT serial communication is killing your speed.

Try to just count the number of reading for seconds, and write it to PC only every second.

also you can try to increase Serial communication speed, i've managet to use a baudrate of ~1.000.000 without modification on the arduino and with a custom serial monitor (try putty or hyperterminal)

also use the tag [code ][ /code] (without space, use the # button near the smiles) to post code, thanks.

lookinf forward to see your new and speedy code. :grin:

I did that. Without the sensor connected the processor (Arduino pro mini 328P 3.3V 8 MHz) is sampling at 16 millisecond interval. With the sensor connected it samples at 14 millisecond interval. Arduino pro mini 328P 5V (with logic level converters) 15 MHz or Arduino Uno SMD version 16 MHz samples at 14 millisecond interval with the sensor connected and at 12 millisecond interval without the sensor connected. I have tried higher baud rates. The whole system crashed. I am using Real Term and Tera Term to monitor the serial output for baud rates higher than 115200 because Arduino IDE serial monitor does not support higher baud rates. I only get gibberish at higher baud rates for the baud rate of 115200 in case of Arduino pro mini 3.3V 8 MHz and baud rate of 230400 for Arduino pro mini 5V 16 Mhz. Anything higher in case of either cases the system crashes and I only get garbage on the serial monitor and I cannot decipher it.
The only conclusion I draw is that if I use a faster processor I will be able to read data at higher sample rate. So I am now trying Arduino Due (84MHz). But the Arduino IDE for Arduino Due does not work. There are some basic problems in getting the system to work. The IDE is in beta version and the libraries are not fully functional.
So I have ordered a new Teensy 3.0 board whose processor is 48 MHz. Since the Due and Teensy use a different processor so I am not sure how far the IDE will work. If I am successful in loading the sketch I will post the results.

did you change the i2c's clock speed into twi.h from 100.000 to 400.000?? (that means yuor sensor will talk with arduino at 4x speed)

also don't try to read all sensor in the loop, as for example, magnetometer will slow you down: infact if you can go to 14ms taht mean 70 read at seconds: (1000ms / 14ms = 71Hz), the speed of the magnetometer!

try to leave the magnetometer reading (and count the reading for seconds) and you should see faster reading, then if this will work read the magne every 14ms, with a code like BlinkWithoutDelay.

The only conclusion I draw is that if I use a faster processor I will be able to read data at higher sample rate

WRONG! the slighy faster reading are due to faster processor executing Serial code; the i2c speed clock is 400.000Hz (400kHz) way slower than an 8MHz arduino, AND the communication is done with Hardware support, so it is indipendent to your code.
Sorry but here the Teensy won't help... but maybe will help you later, if you will do some calculation on-board.

[edit]
PLAYNG WITH SERIAL:
you are writing 1 int and 1 char '\t' for 9 times, that means 9*3 =27byte
plus 4byte of "time" and 1byte on \n(pritnLN) for a total of 34 byte
@ 115200 you can write 115200/10=11.520 byte/s, so tecnically your limit is (11520/34)=338read/s, that means 2.3 ms for read.

I have already changed the twi.h from 100.000 to 400.000. But that did not make any big difference. The sampling rate is still at 18 milliseconds using an Arduino pro mini 3.3 V 8 MHz. No significant improvement was observed. I need the magnetometer to operate at the same speed as the rest of the sensors. Rather magnetometer on the MPU 9150 is designed to operate at 400 Hz (Please refer to the data sheet). Same as the rest of the sensors. But unfortunately the magnetometer is sampling at 12 milliseconds when run alone and does not run in fast mode. I am not able to fix this problem.

It works with Free IMU. But I am not able to access the magnetometer. I am able to sample at every four milliseconds. I need help in accessing the data from the magnetometer on the MPU9150.

I read the magnetometer without the Acc and Gyro and I was able to sample upto 12 milliseconds. Similarly the Acc and Gyro alone sample at 4 milliseconds. But the AK8975 has fast sampling. But I donot know how to fix this problem. I also checked out the data sheet for AK8975. The link is below.

http://www.akm.com/akm/en/file/datasheet/AK8975.pdf

But there is no useful information regarding the fast mode operation of AK8975. Please help.