Self-balancing Part 2

In this part of the tutorial I will cover how to get the most performance out of the MPU-6050 Accelerometer and Gyroscope module, using the Motion Apps library. This library is really amazing as the author reverse engineered the MPU-6050 so that most of the processing is done through the DMP on the module itself, instead of by the micro-controller! I have found that reading the sensor through the Motion Apps Library is faster than doing the calculations manually, and the readings tend to be significantly more accurate.

Analysing the Output

Here is the code that I used to get the yaw, pitch and roll sensor data. It is based on the “Teapot” demonstration program which comes with the MPU-6050 Motion Apps library. Once again, you need to have the “MPU6050” and the “I2Cdev” libraries installed to use this code.

From a number of trials, I noticed that the accelerometer-gyroscope module and the Motion Apps library seem to have some type of auto-calibration feature, which requires a couple of seconds to complete. Here is a graph of the output I got directly after initiating the sensor:

Output from the MPU-6050, using Motion Apps
Output from the MPU-6050, using Motion Apps

All of the values float a large amount at the start, especially the yaw data. This then stops after around 13 seconds, probably due to the completion of some auto-calibration process. I repeated this test a number of times and it seems that the sensor can take up to 40 seconds to complete its calibration, on some occasions. Therefore we should take this delay into account in our program. The robot should wait for around 40 seconds, before beginning to use the sensor and starting the main program.

Calibrating the Sensor

Just like any sensor, the MPU-6050 needs to be calibrated before it is used for the first time. What we want to do is remove the zero-error; this is where the sensor is totally level, but it thinks that it is angled slightly. Therefore we need to adjust the offsets in order to counteract this error. Fortunately I found a program that can calibrate the MPU-6050 for us! In order to use the program, all you have to do is to upload the sketch and then place the accel-gyro module in a flat and level position. The program will make an average of a few hundred readings and display the offsets required to remove zero error.

The sketch outputs the required accelerometer and gyroscope offsets through the serial monitor. All you have to do is plug them into the initialisation code at the start of your program, and you are good to go! Please note that the required offsets vary significantly from sensor to sensor, so you have to repeat the calibration program above for each MPU-6050 sensor you are using.

That concludes the basic calibration of the MPU-6050; the sensor should now be more than accurate enough for most applications, such as self-balancing robots and quad-copters.

In Part 4: The PID Controller View Part 4

Please leave a comment below if you have any questions or suggestions. You could consider subscribing if you want to be notified the moment I post the next part of this series!

This Post Has 46 Comments

  1. Hi,
    great tuto. Unfortunatly I’ve got the same error as Amit. I am also using NodeMCU esp8266 12E and GY 521 in arduino IDE end get an error message. The sensor work when I try to get RAW value readings using the scripts provided on the Arduino website. It seemed to me that the problem is a matter of the interrupt pin. I don’t know which pin to use at the NodeMCU for interrupt.

    Soft WDT reset
    ctx: cont
    sp: 3ffffde0 end: 3fffffc0 offset: 01b0
    3fffff90: feefeffe feefeffe feefeffe 3ffeef00
    3fffffa0: 3fffdad0 00000000 3ffeeed0 40204d7c
    3fffffb0: feefeffe feefeffe 3ffe8520 4010150d
    ets Jan 8 2013,rst cause:2, boot mode:(3,6)
    load 0x4010f000, len 1384, room 16
    tail 8
    chksum 0x2d
    csum 0x2d

  2. Hi, Simon! My serial monitor displays
    Calculating Offsets

    … for more than a minute. My connections were correct, my MPU6050 is placed horizontally and I’m not touching it. Can you help me solve this problem? Thank you.

    1. Have you tested the sensor with the test program which simply outputs the raw sensor data [link]? The values should remain relatively constant when the sensor isn’t moving.

      If everything else seems right but it still isn’t converging, then increase the giro- and accel- deadzone values on lines 43 and 44. This will decrease the accuracy, but should speed up the calibration.

    2. Hi I am completely new in this field. In my project I have to calibrate the reading of the accelerometer and I am using NodeMCU esp8266 12E and GY 521 in arduino IDE but when I am running this code then I am getting error message. Can u suggest me what kind of necessary change are required in order to get offset values to get more accurate reading?

    3. What is the error you are getting? Does the sensor work when you try to get RAW value readings using the scripts provided on the Arduino website?

  3. Hi! The website that has the calibration for MPU5060 is not opening; can you post/send me the zip file please? I have read multiple sources that mentions this website, but nobody has the actual file posted 🙁

    1. Yeah it looks as if that website is down at the moment; I did write this post 4 years ago, so these things happen. The code is the same as the one which I included in the post. You can just hover over it and press the ‘copy’ button in the top right to use it.

  4. Hi Simom!

    I am working on a project related to gait measurement,
    is there an way to automatically adjust the calibration point every time the external power is applied?

    1. The MPU6050 does not have any integrated feature to support this, but you could program the microcontroller to do this for you. The calibration of the sensor does not change between power cycles, so there may not be a need to repeat this process each time…


  5. What coding language are you using in this tutorial?
    By the way, this tutorial was super helpful. Thank you!

    1. I am using C++, which is the standard programming language for the Arduino micro-controller.

  6. Hi, was looking exactly for this. Thanks a bunch.
    Facing problems with the calibration though.
    All I’ve been getting is three dots(…) and I’ve been waiting for like 10 minutes straight.
    Could this be due to the fact that I’m using a Nano board instead of a UNO ?
    P.S. i changed the address from 0x68 to 0x6B since the latter seems to be the address for my Nano.
    Thanks !

    1. The i2c address should be the one of the sensor; but I guess as long as it says “Connection Successful”, the communication is working correctly. It shouldn’t matter which type of micro-controller you are using.

      If the “…” keeps going for a long time, it means that the sensor values are not converging. This can occur if the sensor is not orientated totally level (x and y axis flat, z axis pointing up), or if the sensor keeps moving during calibration.

  7. Thank you so much for this – I was pulling my hair out trying to get some sense out of my 6050 DMP -Roll/Pitch/Yaw – and was going to throw the chip away but I tried your calibration routine and now it is really accurate.

  8. Hi,

    I have success with running the code however, all it prints is “send any character to start sketch”. I’m not sure what this means, nor how to do it haha. Any help is appreciated, thanks. (Trying to calibrate for my self-balancing robot using Arduino Uno)

    1. Type any letter or character in the comment bar at the top of the serial monitor and press enter, the sketch will then start.

  9. Is the calibration persistent across power cycles of the 6050? In other words, do the set___offset commands write to flash memory on the 6050 or does the calibration need to be performed each time it is power cycled?

    My guess is that it’s persistent, but wanted to double check.

    1. [Updated Comment] I’ve just had a look through the i2cdevlib code, and the offsets are sent directly to the MPU6050 where they presumably are saved. To test whether the offsets are persistent, you could set the offset using: void MPU6050::setXAccelOffset(int16_t offset) and then check to see what the offset is after you’ve cycled the power: int16_t MPU6050::getXAccelOffset()

  10. Hello, i’m working with this IMU and checking out your calibration code, I didn’t understand why you divid by 8 and by 4…

    ax_offset = -mean_ax / 8;
    ay_offset = -mean_ay / 8;
    az_offset = (16384 – mean_az) / 8;

    gx_offset = -mean_gx / 4;
    gy_offset = -mean_gy / 4;
    gz_offset = -mean_gz / 4;

    Could you please explain that??

    Thank you very much and than you for this piece of art! 🙂

  11. Hello while i am connecting my gyro mpu 6050 with arduino and then calibrate error is displayed during callibration is gyro is failed but that time green light is there in my gyro can anyone plss suggest what is the problem

    1. From your very vague description, a lot of things could be causing the issue. How did you connect the pins? What code are you using? What exactly was displayed on the serial monitor when you tried to run the code. Have you tested the sensor with the sample code in the MPU6050 library?

    2. The connection which I have made is right and code is also right because first when I have used with made my drone it is working good but the problem in my drone is motor stops running after 1st spin so I think to remove bread board connection and to make a new soldiered connection but after soldiering when I have done whole connection I used to callibrate while callibrateing any error is displayed gyro mpu 6050 is failed can it be the reason than my gyro get bursted while soldiering but I have soldiered very carefully

    3. It sounds as if you got a ‘brownout’ when the motors turned on. This means that the motors used up most of the power supplied by the battery, causing the Arduino to reset. You can look this up online to see the best way to fix it.

      You may also have a second problem if the serial monitor says: “MPU6050 connection failed”. Usually this happens if the connections are wrong, or if the sensor is broken. Often the sensor board works at 3.3v, so a common way that people fry it is by supplying 5v by accident. You should check the schematics for your sensor to see what voltage it expects, and if there is an integrated voltage converter.

  12. I have been trying to run this script to calibrate my sensor. I see it has been stuck on it for approx 20 mins. It just says calculating offsets and then 3X …

    Am I doing something wrong here or is this the expected behavior ?

    1. The code shouldn’t take more than a minute to calculate the offsets. There must be something going wrong. Make sure that the sensor is held flat, and is kept completely still while calibrating. Are you able to read the raw accelerometer and gyroscope values from the sensor using the example sketch in the MPU6050 library? What board are you using?

      If you still have issues, you can post a question to the person who wrote the calibration sketch here .

  13. Hello, is there some way that it shows the angle of degrees on Processing for the teapot demo? When I use the calibration code, I want it to start at zero and I want that value to show on Processing. What would be the code to obtain such degree on Processing ? thank you

  14. I don’t know how to use the numbers from Serial. Ex, from this code I got 49.85 1.85 0.06. How can I put them to code?

    1. Hi, from the calibration sketch you should get six numbers. You can then plug these numbers into the offsets in the “setup” method of your code.

      For example:

  15. Hey Simon, i used your code to calculate the offset values but i don’t know why these values are fluctuating and as much as i know offset values are quite stable values!!
    Do u have any suggestions why this is happening?

    Thanks in advance

    1. You’re right, the offsets should be stable as long as you keep the IMU in the same orientation while completing the calibration.

      Try running the calibration twice in a row without touching the sensor. How big is the difference between the two sets of values?

    2. The fluctuation seems to be of +/-20 …
      The sensor has been untouched in the whole calibration process so i don’t think this is because of that.
      How should i smoothen out this fluctuation to get a stable offset value and also will these value(if calculated correctly) would give me 2 values close to zero when substracted from raw adc values (for x and y axis) and for z axis closer to 16380(for 2g range)??

  16. Hi Simon,
    I am also a Irish Electronic Engineering Student (GMIT represent!), using a Galileo for a quadcopter for my 3rd year project! I noticed in your code you dont use the interrupt method of reading the MPU6050 because it is incompatible with the Galileo! Do you have a better understanding of why this is? I’m porting my code from a working arduino quadcopter and I’ve encountered this interrupt problem and I can’t get my head around it! I’d like to find a way of making it work because the loop way my cause timing issues with the more code I add! Any info would be much apprieciated!

    1. Hi Liam! Interrupts were not yet implemented on the Galileo when I was doing my project, but I think that they are now supported on pins 2 and 3. The Galileo supports edge triggers, so RISING, FALLING and CHANGE should work.

      By the way, I’d be interested to hear how you get on with your quadcopter! That is a project I’ve been thinking of building for a while.

    2. Thanks for the reply!
      I’ve tried implementing them but seems like the interrupt pulse is too quick for the Galileo! Why that is I have no idea! I’m just reading the MPU in loop for now, trying to keep the FIFO from overflowing! The Galileo is proving to be incredibly NOT-compatible with Arduino! Also, did you have any issues with the I2C bus on the Galileo? Seems to crash randomly when the I2C bus is busy! Can’t really find a conclusive answer anywhere on the interweb!

    3. Yeah, I agree that the Galileo isn’t great if you just want to use the Arduino features. The porting isn’t great and it no longer is properly supported, as Intel is putting more emphasis on the Arduino 101.

      I had similar problems with the I2C connection; the Galileo seems to crash if it receives unexpected garbage data. The only way to really prevent that is to use a short cable and shield it with some grounded foil… :L

      I’ve just tested the MPU-6050 with interrupts on my Galileo, and it does work. I can send you the source code if you want.

  17. I didn’t know about the extra long self-calibration that the Motion App does. Do you know how to make it short or stop it? Or perhaps load previous calibrations?

    Have you tried saving the offset registers after the calibrations, and then applying them before starting Motion App? I am hoping doing this would speed up the calibration.

    1. I haven’t yet tried any of the solutions that you mentioned. The time taken for calibration in my post above is a worst case scenario; I found that usually it takes less than 15 seconds. For the purposes of my project, trying to mess with the Motion Apps library would probably have taken a lot longer than the amount of time I had to wait while the calibration was occurring!

      If you do find a solution, I would still be interested to hear it!

  18. Why mean_ax,mean_ay,mean_az is divided by 8 ???
    Why mean_gx,mean_gy,mean_gz is divided by 4 ???


    1. Hi! I didn’t write this auto-calibration program myself, but I assume it is related to the standard scaling factor of the accel and gyro being used. There are actually a number of people asking this same question on the original thread, but I don’t see any definite answer.

      I guess the best way to find out what the division does is to change the number and see how the program runs! I’ll have a closer look at it later this week.

    2. Thanks!! 🙂

  19. Hi Simon,
    Let me start off by saying You Did An Amazing Job!!!!!….. with this build. I have been researching this type of design for some number of months now(since beginning of last year) and the way you tackled and designed your project from the ground up has provided a priceless level of education for me. My hat go’s off to you….in many words, Thank You!!!!!
    If you have the means I would like contribute a donation for all you superior efforts.

    Dave Pina

    1. Thanks for the kind words! It’s good to know that people do benefit from my posts! Don’t worry about donations, I don’t run this blog to make any money.

      Simon B.

  20. Is 49N*cm enough motor torque for this project?

    1. I’m sorry for the delayed reply; for some reason your comment landed in the spam folder! I think that 49N*cm should work, but it might be better to have a slightly higher torque (eg. between 55-60N*cm).

    1. Probably the 12v, 280rpm motor would be alright for a self-balancing robot.

      Simon B.

Leave a Reply

one × 5 =