Gyroscopes and Accelerometers on a Chip

The interior of a 3-D MEMS Gyroscope Sensor is intricate and tiny (the width of this structure is only about 800 micrometers).
The interior of a 3-D MEMS Gyroscope Sensor is intricate and tiny (this structure is only about 0.08 cm wide).

My last two blog entries discussed demonstrations of gyroscopes and angular momentum conservation at our school’s science fair. One of the demonstrations I put together takes a look at how really small gyroscopic sensors, such as those in many smart phones, video game remotes or quad-copters provide information about their changing orientations. This information can be used as feedback for self-balancing (e.g. a two-wheeled scooter), navigation or as input to other applications like video games.

I didn’t want to sacrifice my smart phone for this experiment. Fortunately, chips containing gyroscopic sensors are relatively cheap. In reading up on gyroscopic chips, I found that orientation data from gyroscope sensors is prone to drift significantly over time, so gyroscopic sensors are frequently combined with additional sensors, such as accelerometers or magnetometers to correct for this effect. This combination of sensors is frequently referred to as an IMU, or “Inertial Measurement Unit”, and it is used in  airplanes, spacecraft, GPS navigators (for use when GPS signals are unavailable) and other devices.  The number of of sensor inputs in an IMU are referred to as “DOF” (Degrees of Freedom), so a chip with a 3-axis gyroscope and a 3-axis accelerometer would be a 6-DOF IMU.

The GY-521 is a breakout board containing a 3-axis accelerometer and a 3-axis gyroscope in the tiny chip in the center.
The GY-521 breakout board contains a 3-axis accelerometer and a 3-axis gyroscope in the tiny MPU-6050 chip in the center.

The MPU-6050 is a commonly used chip that combines a MEMS gyroscope and a MEMS accelerometer and uses a standard I2C bus for data transmission. More importantly to me, someone else has already done the hard work of reverse-engineering the MPU-6050 and provided freely available source code to use an Arduino microcontroller to retrieve the MPU-6050 data. There are a number different breakout boards available containing the MPU-6050 chip. You can find an overview of many of them on this page, under the heading “Breakout Boards”. I ordered the GY-521 module from Amazon.

There is a sophisticated library named I2Cdevlib for accessing the MPU-6050 and other I2C devices written by Jeff Rowberg. The specific code is provided in the sub-folder “MPU6050”.  It utilizes a hardware buffer on the chip and Digital Motion Processing capabilities of the MPU-6050 to perform data conversions between different coordinate systems and combines data from multiple sensors to obtain greater accuracy and precision.  Another useful library called FreeIMU, written by Fabio Varesano, is specifically geared towards calculating orientation from multiple-sensor IMUs, and can perform sophisticated data processing as well.  FreeIMU makes use of the I2Cdevlib, but I found that the latest I2Cdevlib included with FreeIMU conflicted with the  Rowberg’s version of I2Cdevlib, so be sure to use the correct version of I2Cdevlib if you use one of these libraries.

I was looking for a quick and dirty demo for our science fair, so I adapted the short code, by an author “Krodal”, at the bottom of this page to read the raw data from the MPU-6050 and do simple (hah!) calculations of rotation angles myself.  After going back to re-try my experiment with the libraries mentioned previously, I realized that it would have been much easier and more accurate to use one of the pre-written libraries instead.  I did, however, learn a great deal in the process of converting the raw sensor data to rotation angles, so it was worthwhile to do it the hard way.

The GY-521 connected to an Arduino UNO. Additional connections are needed to use the I2Clib and FreeIMU libraries.
The GY-521 connected to an Arduino UNO. Additional connections are needed if using the  I2Clib and FreeIMU libraries.

To set up the hardware, I soldered header pins to the GY-521, and connected it to an Arduino UNO via a tiny bread board.  The wiring was trivial – only four jumper cables were needed.  For power connect GND↔GND and VCC↔3.3V (the GY-521 board has a voltage regulator, and can take either 5V or 3.3V). Only two pins were needed to transmit data on the I2C bus: SDA (data)↔A4 and SCL (clock)↔A5.

Getting the raw data was easy.  Krodal’s code worked immediately, and, generated output as shown below.  A harder trick is to convert these raw numbers into meaningful data.

[codebox 1]

I modified Krodal’s code to start with a calibration routine that averages the first 10 readings to compute the default sensor offsets.  The offsets get subtracted from the raw sensor values before the values are converted to angles.

Now the task was figuring out how to compute the rotation angles.  This can get quite complicated.  There’s a pretty good writeup of the mathematics involved here.  For the GY-521 oriented flat as shown, the X and Y axes lie in the horizontal plane and the Z axis is vertical.

To compute orientation from the accelerometer, we rely on the fact that there is a constant gravitational pull of 1g (9.8 m/s^2) downwards.  If no additional forces are acting on the accelerometer (a risky assumption, as we’ll see later), the magnitude of the acceleration detected will always measure 1g, and the sensor’s rotation can be computed from the apparent position of the acceleration vector, as seen below.  If the Z-axis is aligned along the gravitational acceleration vector, then it is impossible to compute rotation around the Z-axis from the accelerometer.

This diagram shows calculations of tilt angles from the measured acceleration vectors.

According to the MPU-6050 datasheet, page 13, you can convert the raw accelerometer data from Krodal’s code into multiples of g (9.8 m/s^2) by dividing by a factor of 16384.  However, since the conversion to angles uses ratios of the acceleration vector components, this factor divides out.  I computed rotation around the X-axis (φ) and Y-axis (-ρ) using the formulas in the image to the left.  Interpreting the diagram at left is a little tricky, since the tilt of the X-axis actually shows rotation around the Y-axis, and the angling of the Y-axis shows (negative) rotation around the X-axis.

It is important to note that the accelerometer results provide accurate orientation angles as long as gravity is the only force acting on the sensor.  However, when moving and rotating the sensor, we are applying forces to it, which causes the measurements to fluctuate.  The net result is that accelerometer data tends to be very noisy, with brief but significant perturbations.  If these can be averaged out, the accelerometer provides accurate results over timescales longer than the perturbations.

Computing orientation from the gyroscope sensor is different, since the gyroscope measures angular velocity (the rate of change in orientation angle), not angular orientation itself.  To compute the orientation, we must first initialize the sensor position with a known value (possibly from the accelerometer), then measure the angular velocity (ω) around the X, Y and Z axes at measured intervals (Δt).   Then ω × Δt = change in angle.  The new orientation angle will be the original angle plus this change.  The problem with this approach is that we are integrating – adding up many small computed intervals – to find orientation.  Repeatedly adding up increments of  ω × Δt will result in small systematic errors becoming magnified over time.  This is the cause of gyroscopic drift, and over long timescales the gyroscope data will become increasingly inaccurate.

The MPU-6050 datasheet shows that dividing the raw gyroscope values by 131 gives angular velocity in degrees per second, which multiplied by the time between sensor readings, gives the change in angular position.  If we save the previous angular position, we simply add the computed change each time to find the new value.

As explained above, both the accelerometer and gyroscope data are prone to systematic errors.  The accelerometer provides accurate data over the long term, but is noisy in the short term.  The gyroscope provides accurate data about changing orientation in the short term, but the necessary integration causes the results to drift over longer time scales.

The solution to these problems is to fuse the accelerometer and gyroscope data together in such a way that the errors cancel out.  The standard method of combining these two inputs is with a Kalman Filter, which is quite a complex methodology.  Fortunately, there is a simpler approximation for combining these two data types, called a Complementary Filter.  Far better explanations than I could ever write are given here (AVRFreaks) and here (the original write-up by Shane Colton disappeared offline, but many thanks to Alexander Göransson for finding a PDF copy!), but the approximate formula to combine the accelerometer and gyroscope data is:

Filtered Angle = α × (Gyroscope Angle) + (1 − α) × (Accelerometer Angle)     where

α = τ/(τ + Δt)   and   (Gyroscope Angle) = (Last Measured Filtered Angle) + ω×Δt

Δt = sampling rate, τ = time constant greater than timescale of typical accelerometer noise

I had a sampling rate of about 0.04 seconds and chose a time constant of about 1 second, giving α ≈ 0.96.

So, now I had gyroscope data, accelerometer data and a filtered combination of the two.  To visualize how these data all compared, I used Processing, an open source programming language and environment (very similar to the Arduino IDE) that is particularly well suited for data visualization.  I modified the Arduino sketch to send the processed sensor and filtered data through the serial port, and wrote a Processing sketch to show the sensor and filter output as applied to three 3-D rectangles.  Note that you must use the 32-bit version of Processing to get serial port access.  For anyone who is interested,

here is the Arduino sketch:

 and here is the Processing sketch (On Jan. 15, 2015, I updated the Processing sketch to fix a display bug that appeared in Processing 2.1.1): .

The video below demonstrates the differences in the accelerometer, gyroscope and filtered data:

296 thoughts on “Gyroscopes and Accelerometers on a Chip

  1. I like your blog, but am finding it difficult to use the Gy-521 to do my project. Am new to Arduino, i need this to calculate and tell me the position of a moving ball. Am perplexed and i really need help to get me started. Please i need your help. Thanks and remain blessed

    Best Regards
    Emeka

  2. As regards to my previous post, i have to add that am not using i2c or any freeIMU libraries. Will also need the code for it. Thanks

    1. Hi Emeka,
      I’m not sure exactly where your difficulties are, but a good place to start is with an Arduino sketch to print out the GY-521 sensor readings. I was able to use the code by Krodal at the bottom of this page: http://playground.arduino.cc/Main/MPU-6050 without any modification to read and print out the sensor readings. If you look carefully, this blog post provides links to the i2clib and freeIMU libraries (the terms “i2clib” and “freeIMU” are hyperlinked to the web pages which have downloads for the libraries). I hope this is helpful. If not, perhaps you can explain where you are stuck in a little more detail.
      Debra

  3. Hi there.

    First off this worked first time using my nano v3, thanks.

    I was wondering how you would go about programming the z axes into this sketch, would this be in the processing file or the arduino file, what code would i have to use? I do see references to the z axes the the arduino code so not sure if its just the processing file that need editing.

    Also

    The sensor is set to “Acceleration at 2g” which is i think AFS_SEL=0 (but i dont see that in the code ) so how would i set this to be at the 16g level ie AFS_SEL=0, and would that affect anything in this sketch.

    Thanks for the help and this sketch its a great help,
    Ps only been playing with arduino for a week now so all new to me.

    1. That’s a good question. Just for clarity, I’m differentiating between the Gyro and Accelerometer measurements along the X, Y and Z axes, and the computed rotation of the entire IMU board, which I’ll refer to as Roll, Pitch and Yaw (rotation around the X, Y and Z axes, respectively). In the Processing sketch, what is referred to as the X, Y and Z angles are actually the Roll, Pitch and Yaw. You’re right that you could incorporate Yaw in Processing by simply adding a “rotateZ” function call after the “rotateX” and “rotateY” function calls.

      The tricky part is that you can’t compute Yaw from accelerometer data, because accelerometer computations rely on gravity pointing in the Z direction, and are invariant to rotation around the Z-axis. The Arduino sketch does compute Yaw strictly from the gyroscope, and that Yaw value is sent over to the Processing sketch. I wanted to compare the gyroscope, accelerometer and filtered data to each other, so I omitted displaying Yaw, because the computation isn’t comparable. You can definitely use the Yaw data if you want to – it just doesn’t incorporate data from the accelerometer.

      With respect to changing the accelerometer range from 2g to 16g, the default value is 2g, and I never looked into changing it. I know that if you are using the I2Cdevlib library there is a function call, setFullScaleAccelRange(), which modifies the value of AFS_SEL, and therefore the range. Without using i2cdevlib, I’m not actually sure how you change it.

      Honestly, if you are going to use the data for more complicated calculations, you are better off using the I2Cdevlib or freeIMU libraries (links to both are in this post). They have all kinds of additional functionality above and beyond what you can do in this sketch.

      I hope this is somewhat helpful. Good luck!
      Debra

      1. Thanks you for all the help with this, i will start looking into the I2Cdevlib and freeimu libraries, once again thanks as this was the perfect place to start,

  4. Hi.
    Why the theta is arctan((pow(Ax,2)+Pow(Ay,2))/Az),not arctan(Az/(pow(Ax,2)+Pow(Ay,2))) same phi and rho?. thank you! 🙂

    1. These equations (and the image they are in) come from this paper at the bottom of page 4. In the paper, the picture has the following description:

      In order to define the angles of the accelerometer in three dimensions the pitch, roll and theta are sensed using all three outputs of the accelerometer. Pitch (ρ) is defined as the angle of the X-axis relative to ground. Roll (ϕ) is defined as the angle of the Y-axis relative to the ground. Theta (θ) is the angle of the Z axis relative to gravity

      Note that while rho and phi are pitch and roll, theta is NOT Yaw. Yaw is rotation AROUND the Z-axis. You cannot compute Yaw from accelerometer data. In a system where gravity is the only force on the accelerometer, you know that
      Sqrt(Ax^2 + Ay^2+ Az^2) = g
      And since we have formulas for ρ and ϕ in terms of Ax, Ay, Az, it turns out that θ is redundant and can be defined in terms of ρ and ϕ. So you don’t really need θ.
      As to why θ is calculated differently, according to the paper, the first two angles are defined with respect to the X-Y plane (the ground), but θ is defined relative to the Z-axis, which is 90 degrees (pi/2) from the ground.

      You can use the with the standard trigonometry identity:
      atan(x) + atan(1/x) = pi/2
      to see that if you calculated θ relative to the ground rather than the Z-axis, it would take a similar form to the other two angles.

      I realize the picture can be a little confusing. It makes more sense in the context of the paper it comes from. I added some explanation to the picture caption to make things clearer. I hope this helps.
      Debra

  5. hello Debra!
    Can you tell me how to calibrate MPU6050 (gyro and acc) ?
    I use GUI to see the angel and i find that the angel from the filter is lag than the angel from acc.You have some opinion about that? thank! 🙂

    1. Hi Kim,
      I did a very basic “calibration” – just taking the first few readings of the sensors while keeping the IMU still, and subtracting the average values from subsequent readings. I’m sure that there are much more sophisticated calibration methods that could take into account rate of gyroscope drift, but I’m afraid I can’t refer you to any sources. You might want to check the FreeIMU library for a more sophisticated calibration routine. I don’t know for sure, but it might have one.
      As far as time lag in the filtered angle goes, that occurs because of the low pass filter applied to the accelerometer data in the complementary filter. To eliminate the accelerometer noise, it is effectively averaging the data over time, which results in a delayed response. For a good visualization of how the low pass portion of the complementary filter affects the data, check out the explanation of a low pass filter in this paper: http://web.mit.edu/scolton/www/filter.pdf.
      Hope that helps.
      Debra

  6. Thank you very much for your work with the MPU-6050!
    I buyed that board a couple of weeks ago too and I even thougt it was damaged because I couldn´t solve the drift-problem with the FreeIMU library.

    But then I found your project on Youtube and after downloading your programs I was so glad because now it is working

    So thank you, you really helped me out 😉

    1. The time constant needs to be longer than the typical accelerometer noise, but shorter than the timescale over which the gyroscope displays significant drift. I could see significant gyroscope drift after a couple of seconds. I didn’t do any specific calculations to come up with a time constant of 1 second, I just played around with different values of α until the results looked good. There’s a nice explanation of the time constant in the complementary filter here: http://www.instructables.com/id/Segstick/step10/A-very-flattering-filter/.
      Debra

  7. Hi Admin,
    Can you guide me on how can I add another GY-512 module please? I am planning to use to of them connected to the Arduino. How do I define the second sensor module in the program?

  8. Hi Admin,
    In addition to my earlier question, I would like to tell you my problem. I had difficulty in running the Processing file. I have tried with both Processing version 1.5 and 2.0beta. When I try to run the file, an empty windows pops out and and the Processing IDE highlight this particular line, String portName = Serial.list()[portIndex];.
    May I know what is the problem? I am new to Processing, please help. Thank you.

  9. Hi Admin,
    I have a third question here. How do I recalibrate the sensor module at different angle? I wish to install it vertically.

    1. Hi Robert,
      To address your three questions in order:
      (1) I haven’t tried to add a second IMU to the i2c bus. I’m sure it’s possible. According to a question answered here: http://www.varesano.net/blog/fabio/how-connect-and-test-freeimu-v04-arduino-and-freeimu-library, you can change the i2c address of one of the MPU6050’s on the bus, and then access each MPU6050 with its own i2c address. I do not know how this is done, but you could try looking at the i2cdevlib library written by Jeff Rowberg. There are many useful access functions in there. If you are trying to do anything where you modify the settings on the MPU6050, then you should really use the i2cdevlib or freeIMU libraries.
      (2) The Processing code is crashing where the program is looking for the name of the serial port attached to the Arduino. This will vary from computer to computer. The Serial.list() method returns a list of serial port names on the computer, and it happens that my Arduino is connected to the second port named on the list. If you know the name of the COM port your Arduino is attached to, you could just replace that line of code with portName = “COM5”, or whatever the actual port name is.
      (3) Turning the IMU on its side will result in no difference in the data returned by the MPU6050, you will just have to process it a little differently to find the rotation angles. Assuming you are pointing the GY-521 straight up, the X-axis will be vertical, and the Y and Z axes will lie in the horizontal plane. Gravity then aligns with the X axis instead of the Z axis and the accelerometer data is invariant to rotation around the X axis. You can use the same functions as in the code to get the rotation angles, but just swap the sensor values for the X and Z axes in the computations.
      In general, it is easier to use the code in the i2cdevlib library to do these computations for you, as it does most of the computations on the MPU6050 DMP. In my experience, it provides more accurate rotation angles than the complementary filter. I am working on a blog post demonstrating my experiences with i2cdevlib, but you can see how it works with Jeff Rowberg’s demo Arduino sketch MPU6050_DMP6.ino located here: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050/Examples/MPU6050_DMP6.
      Good luck.
      Debra

      1. Dear Debra,

        Thank you very much for the reply. I have browsed the varesano.net site. I have learned that the blogger, Mr Fabio has passed away. I didn’t get much help there but I am still going through the i2cdevlib hoping to get something. Do you know where can I get help on this?

        As required for my project, I have placed the sensor module on my thigh and it displays a reading of at around 90 degree. As I lift my thigh up while making the first move forward, the reading decreases to around 70 degree. I get about the same value from my another sensor on my left thigh (still on positive quadrant). Here, I have difficulty to to differentiate the two readings. The 360 degree is divided into 2 main quadrant, positive and negative and the maximum angle I am getting is only 90 and not 180. How do I change the settings to 180 degree?

          1. Yes, you will have to modify the code, because your yaw will be rotation around the vertical axis. In this code it is computed as rotation around the Z-axis. You will have to compensate accordingly.,

          2. The modification of the code for the y axis vertical this?

            float accel_angle_y = atan(-1*accel_x/sqrt(pow(accel_y,2) + pow(accel_z,2)))*RADIANS_TO_DEGREES;
            f
            float accel_angle_z = atan(sqrt(pow(accel_x,2) + pow(accel_y,2))/accel_z)*RADIANS_TO_DEGREES;

            float angle_y = gyro_angle_y;

            float angle_z = alpha*gyro_angle_z + (1.0 – alpha)*accel_angle_z; //Accelerometer doesn’t give z-angle

            ok???

  10. Dear Ms. Debra,

    I could run the Processing file by directly setting the portName.
    I aware that you have used the accelerometer, gyroscope and the filtered variables’ reading from the Arduino program to print its data on the Processing application. How do you link the variables from Arduino to Processing? I have noticed that you have defined,
    float x_gyr;
    float y_gyr;
    float z_gyr;
    float x_acc;
    float y_acc;
    float z_acc;
    float x_fil;
    float y_fil;
    float z_fil;

    However, I dont understand how did you link the variables from the Arduino program to the Processing program since the variables in the Arduino are having different names. Can you explain on this please? I have started to feel comfortable on Arduino but just started on Processing.

  11. Hi, I am have been trying to this for a school project and have ran into some issues. This is my first Arduino project, actually first tech project, and I could use some serious help. I am using an Arduino Uno on a freshly imaged Windows 7 32 bit computer (ran into issues running the sketch on a x64 image). I have latest version of Java installed, I have uploaded the Arduino Sketch
    and started the ShowGY521Data processing sketch. It freezes and I get this error. (screenshot) http://s18.postimg.org/9yj9rqgbt/Untitled.png
    I have already tried to update RTXT http://forum.processing.org/topic/how-do-i-install-rxtx-2-2pre1-jar-on-windows-7 with no luck. Can you please help, my project is due on Friday 😉

      1. Hi Ted,
        I am on vacation and unable to get to my computer for any in-depth help, however, for this error, try setting the “portIndex” variable to “0” so that it picks the first port name from the list of available ports, or you can specify the port as COM 3 directly by setting portName = “COM3” (maybe “COM 3”, I forget offhand).
        Hope this helps,
        Debra

        1. Thanks admin, setting the “portIndex” variable to “0″ did the trick. I am not sure if this helped but I also downgraded to the last version of Java 6. Thank you very much you are a life saver. Last question for you 😉 I would like to play around with the shapes of the animation, do you have any tips for me ?

          1. For different shapes, you might try checking out some of the simpler examples that come with the Processing library. I adapted the code from one of the cube examples to make the rectangles. Good luck!
            Debra

  12. Hi Debra,

    I am successfully reading raw data, and trying to use the trig functions you have shown to calculate position from the accelerometers. The position in the X and Y direction looks correct until I rotate past +-90 degrees on X or Y. Doing more research on arctan, the only possible outputs of the function are between +-90 degrees so that makes sense to me. Have you done anything to make it so you can rotate in the X or Y direction and get readings between +-180 degrees? My application needs to know position over 360 degrees, not 180. Right now when I continue rotating past +90 degrees, the values start decreasing back to 0 degrees (0 reached when the IMU is upside down). Does you application do that also?
    Thanks so much in advance for your help, this page has really helped me a lot.

    -Chris

    1. Hi Chris,
      The range of the inverse Arctangent function is (-Pi/2,Pi/2), which is why this method won’t work easily for ranges greater than that. See my more recent post on using the i2cdevlib library with the DMP (digital motion processor) in the MPU6050 which addresses this issue specifically.
      Debra

  13. This is awesome it clearded up most of things for me .I can use acc.But ı did not understant that how did yo find your dt(sampling rate) I can take value from gyro and divide it with 131 but ı couldn’t figure out what dt is ?.I tried to mulpt. it with 0.013 because my floop cycle is 13 ms but it is still drifftting .is it fixed value that comes from mpu6050 conf registers or dlpcfg resgisters or it can change according to my program ?

    1. Hi. Dt is not fixed. I measured the clock time at each gyro reading and subtracted the previous time reading to find dt.

      1. I’m so glad that you answered.İt was so important for me.But ı have 2 another question

        1) İf dt is not fixed by register what does DLPF_CFG for ? and sample rate for gyroscope can be 8khz or 1 khz is that change anything for gyro ?

        2) ı tried data ready interrupt and couldn’T really control it did you try to do it when ı do it cycles between interrupts was like 0.8 ms how am ı supposed define dt while it is like that fast ?
        y

        1. The data sampling rate is fixed, but I didn’t use that value. If you look at the sample code I provide (gy_521_send_serial), every time I do a reading of the GY-521 sensors using the function call, “read_gyro_accel_vals”, it is immediately followed by a call to the arduino function “millis”, which measures the current time in milliseconds. Subtracting the previous value of the call to “millis” gives the elapsed time since the last reading, which defines “dt”.
          Debra

  14. Hi. The code you post is not exactly the same you use in the video. Both works, but I don’t know how you calculate the filtered data. I will need to rewrite it… Can you send the exact code you did? This will make easier test it.

    1. As far as the motion of the three rectangles goes, I believe that the video and code are the same. What differences are you noticing? I don’t have another version.

      1. Hi. Thanks for reply. The fist thing: The data that Arduino send to Serial Port is different from the data that Processing read. You need to rewrite this part of code. I am newbie in Arduino and it take a long time to discovery 🙂

        I didn’t find where you calculate the filtered data. (But I need to read more). Anyway this is not an easy thing.

        But two of tree data worked and for me was a good way to start. But if you can find the exactly code you did, it will be easier to me. 🙂

        1. I haven’t had the problems you mention with different data leaving the Arduino and being received by the Processing code. I think you might want to check your setup again. I have not heard about these problems from anyone else, but when I find the time, I’ll go back and check for errors. And the code is commented, so if you take the time to read it, you should be able to find where the filtered data is computed. All the code I added to Krodal’s existing program is towards the bottom of the file. Start by looking there and reading the comments. It may help you.

    1. If you read previous comments (it’s also mentioned in the article), you’ll see that you can’t compute the yaw (Z axis rotation) from accelerometer values. So while we have values for pitch and roll from both the accelerometer and gyroscope, we only have values for yaw from the gyroscope. Therefore we can’t apply the complementary filter to yaw.

  15. hi Debra,
    I tried your code but it produces very jittery orientation & acceleration. However, when i tried Rowberg’s code, it works perfectly. But, the drawback is his code is so complicated to read. Your code or more accurately, Krodal’s code, is much simpler to understand.

    Krodal’s code produces raw data, where do you process those signals and filters them because i dont’ find it in the code that you provide here at the bottom of your page.

    thanks

  16. Thank you so much! Thanks to your great job i was able to make it work in an hour. It would have probably taking me days otherwise.

    Thank you again,
    Ricardo

  17. Sir ,
    I m building a self balancing bot,and im in the stage of tuning PID parameters,I really need to know the sampling period of the sensor you used in your arduino program.As the loop time needs to be matched with the sampling rate!!

  18. Thank you so much. I am very grateful for your blog. This put an end to hours and hours of trouble shooting how to grab the value from the gyro in a form that can be use further the sketch and not just in a form that can only be displayed on a LCD display or the serial monitor.

  19. Hello,

    I see all of the helpful information here and I have having issues with my MPU 6050 for several weeks now and have yet to find any answers yet. So I thought I’d give this a shot….

    I wired everything as shown above as well as what is posted by Jeff R. and uploaded the sample programs. When I check the serial monitor I get the following:

    InvenSense MPU-6050
    June 2012
    WHO_AM_I : 11, error = 2
    PWR_MGMT_2 : 11, error = 2

    MPU-6050
    Read accel, temp and gyro, error = 2
    accel x,y,z: -5374, 2, 305
    temperature: 37.212 degrees Celsius
    gyro x,y,z : 2050, -13039, -29695,

    MPU-6050
    Read accel, temp and gyro, error = 2
    accel x,y,z: 747, 512, 12545
    temperature: 24.459 degrees Celsius
    gyro x,y,z : 520, 4557, 396,

    I haven’t found anything about what the error means or how I can resolve this. Have you seen this or know how I can get rid of the error?

    Any help would be awesomely appreciated. Thank you, emerjer

      1. So I’ve done some research and found that the error = 2 is because of insufficient power to the GY 521. Once I soldered the pins to the board and secured it to a wired bread board everything worked fine.

        Now off to troubleshooting my Processing complications.

        Thanks!!!!!

  20. Hi there.

    First of all thank you, this post was really helpful.

    But I have a problem with it.

    When I run the code it shows me something like that:

    “M*Z­­­i@8ŽˆÈ
    H‚N•) ªÊ JÖÈL ŽˆÊ ĽM*º¥L@8ŽŠÊJ H‚Nu) ˆÊ JÖÈL ŽŠÊ ĽM*Z¥L@8ŽŒÊ
    H‚N•) ˆÊ JÖÈL ŽˆÊ ĽM*Z­­­H@8ŽŠÊH H‚N•) ˆÊ JÖÈL ŽˆÊ ĽM*Z¥Lp8ŽŠÊˆ H‚N•) ˆª JÖÈ ŽŠÊ ĽM*Z­­­H@8ŽŠÊ H‚N•© ˆÊ JÖÈL ŽŒÊ ĽM*Z¥L@8ŽŒÊJ HvN•! ˆÊ JÖÈL Žˆª ĽM*Z­­­H@8NˆÊª H‚N•! ˆÊ JÖÈ, ŽˆÊ ĽM*Z­­­H@¸ŠÈŒ H‚N•! ˆÊ JÖÈL ŽŠÊ ĽM*Z¥L@8ŒÊH H‚N•! ˆÊ JÖÈ ŽŠÊ ĽMæZ­­­H@8ŒÈŒ H‚æ•! ˆÊ JÖÈ ŽŠÊlĽM*Z¥L@8ŽˆÊ
    ,H‚N•! ŽŒÊ JÖÈ ìŽˆÊ Ä½M*Z­­­H@8ΌÊ
    H‚N•! ŽŒÊLJÖÈ ŽŠÊLĽM*Z­­­h@8ŽŠÊH H‚N•! Ž¨ÊLJÖÈ ŽŒÊLĽM*š¥L@8ŠÈL H‚Nu! ŽŒÊLJÖȊ ŽŒÊLĽM*Z­­­H@8ŒÊ H‚N•! ŽŒÊLJÖȊ ŽŒÊLĽM*ZŒŒŒH@8ŽŠÊ
    H‚N•­ ˆÊLJÖ©ŠLˆÊLĽM*Z­­­H`8ŽŠÊ”

    Do you know how do I fix that?

    Regards,
    Vinícius Oliveira

  21. Hi Debra,
    First of all, thank you very much for such an effort. I’ve problem on processing tool and couldn’t find any clear comment either here or in forum of processing.org.
    I followed your steps and it seems everything is ok. But when I try to play the processing sketch, I will face with 2 problems:
    1) There is not any cubes like 3D objects. I can see only lines.
    2) There is only 2 simple lines one is yellow for Gyro and the other one is green for filtered data. There is not appeared any blue line for accelerometer. Eventhough, when I moved the MPU6050, those lines are also moving. So it means I can receive information but I have some 3D processing problems. Have you faced any problem like that?
    *My computer is very new, it has 4GBytes ram with 2.7GHz microprocessor. It is 64bit but I used 32bit version of processing as you mentioned. (Also tried 54 version). Please share your comments, thanks a lot again.

  22. Hi Nikko,

    I’m afraid I haven’t experienced any problems like you describe in Processing. The only thing I could suggest is running some of the demos that come with Processing to see if they look correct. That could at least tell you if there’s something odd about the way this specific program runs on your computer or if your entire Processing set-up is funny.

    The hardest part of the Processing code is unpacking the information from the IDE, which you said appears to be working. Maybe you can try re-writing the code for drawing the rectangles by copying the code a simple shape from one of the Processing demos and rotating that object instead of the rectangular shape.

    Sorry I can’t offer more concrete help. Good luck.
    Debra

  23. Thank you for reply. By the way I’ve solved the problem with using old version of processing.
    (v2.0.3 instead of v2.1)

  24. So I was able to get the Example Ardruino Sketch to work as shown above once I had a good power connection. But lately I have been having trouble with the example ShowGY521 Processing Sketch.

    I have tried running the program and after changing the portIndex = 0; instead of the default 1 in the example the window pops up with all three Gyroscope, Accel., and Combo titles come up but show (0,0) in all three. The rectangle shapes are there. But neither the rectangles or the (0,0) changes with motion/rotation of the GY521.

    Any thoughts on this?

    Thank you very much for all of your help. This is a great resource for those with GY521.

  25. Hi guy , I have had ths same problem few week ago. It’s works now


    // Default I2C address for the MPU-6050 is 0x68.
    // But only if the AD0 pin is low.
    // Some sensor boards have AD0 high, and the
    // I2C address thus becomes 0x69.
    #define MPU6050_I2C_ADDRESS 0x69

    before : 0x68
    after : 0x69.
    It’s works good,
    let me know.
    by the way,
    what is your project?
    I’m trying to build a quadcoptere (4 brusless motor) with an arduino and a mpu6050.
    I’m not successul yet, that why I’m read this topic… but i now have trouble with processing…
    Bye

  26. Hi. I have a problem with the Processing sketch. It is unbelievably laggy. I have to wait a few seconds after rotating the board for the rectangles to update. Also they’re not 3D:
    https://dl.dropboxusercontent.com/u/41928260/Screenshot%202013-12-16%2021.17.37.png

    I have never used Processing and have no clue what could be wrong.

    Windows 8.1 64bit, recent install, didn’t even have java installed, thaught that’s the problem, installed 7.45, didn’t help.
    Tired Processing 2.0.3 and 2.1 64bit, Arduino Duemilanove, Nano and Pro mini, all with ATmega328’s.

    Would appreciate any help!

  27. Hi Debra !
    congratulations for your work. I approached the environment Processing 2.1 just to try a project quite similar to yours.
    My microcontroller board is working properly (even though it has yet to be completely developed), and provides the correct data to the PC, in fact I can view them with a simple terminal program.
    I would like to use the sketch that you’ve written to see those simple rectangular and give a visual aspect to the data transmitted from the microcontroller plate.
    The problem is that Processing 2.1 doesn’t run the code you’ve shown on this page, it simply displays the error that you can see below.
    I don’t want to shift the focus of my project to the study of Processing 2.1 and certainly I’m not an expert in computer graphics (it could take me a lot of time…).
    I know that’s not so polite, but I would like to ask you a little help interpreting the error.
    Would you ? 😉

    thanks

    The issue:
    Framebuffer error (framebuffer unsupported), rendering will probably not work as expected Read http://wiki.processing.org/w/OpenGL_Issues for help.
    OpenGL error 1280 at bot beginDraw(): invalid enumerant
    java.lang.NullPointerException
    at processing.mode.java.runner.Runner.findException(Runner.java:926)
    at processing.mode.java.runner.Runner.reportException(Runner.java:871)
    at processing.mode.java.runner.Runner.exceptionEvent(Runner.java:797)
    at processing.mode.java.runner.Runner$2.run(Runner.java:686)

  28. Hi ! Sorry for the request, I’ve solved the problem. 🙂
    Simply use not the last one but one of the previous releases of Processing, i.e. the 1.5.1, it works fine ! 🙂

  29. Hi,
    first, could you please let me know what is that graphic program you are using?
    is it possible to get its code?
    Also, do you have any exprience with using external magnetometers or MPU9150.
    I mean how we can covert raw data to angle when we have 9 DOF?
    Tnx

    1. The graphics are generated using the Processing software (available for free), and the processing code is available from a link in the article. Note that a previous user had trouble getting the Processing code working with the current version of Processing, and had to revert to an earlier version to get it to work.
      I’m afraid I have no experience with magenetometers, so I’m afraid I can’t be very helpful there.
      Debra

  30. Amigo este problema sucede por que no tienes bien conectada tu mpu6050… verifica bien los pines, tenia el mismo problema…

  31. In Processing it says:
    I don’t know, what to do 🙁

    Exception in thread “AWT-EventQueue-0” java.lang.ArrayIndexOutOfBoundsException: 1
    at ShowGY521Data.setup(ShowGY521Data.java:57)
    at processing.core.PApplet.handleDraw(PApplet.java:2281)
    at processing.opengl.PJOGL$PGLListener.display(PJOGL.java:862)
    at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:652)
    at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:636)
    at javax.media.opengl.awt.GLCanvas$10.run(GLCanvas.java:1284)
    at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1106)
    at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:981)
    at javax.media.opengl.awt.GLCanvas$11.run(GLCanvas.java:1295)
    at javax.media.opengl.Threading.invoke(Threading.java:193)
    at javax.media.opengl.awt.GLCanvas.display(GLCanvas.java:541)
    at javax.media.opengl.awt.GLCanvas.paint(GLCanvas.java:595)
    at sun.awt.RepaintArea.paintComponent(Unknown Source)
    at sun.awt.RepaintArea.paint(Unknown Source)
    at sun.awt.windows.WComponentPeer.handleEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
    java.lang.NullPointerException
    at processing.mode.java.runner.Runner.findException(Runner.java:926)
    at processing.mode.java.runner.Runner.reportException(Runner.java:871)
    at processing.mode.java.runner.Runner.exceptionEvent(Runner.java:797)
    at processing.mode.java.runner.Runner$2.run(Runner.java:686)
    Could not run the sketch (Target VM failed to initialize).
    For more information, read revisions.txt and Help ? Troubleshooting.

    1. It’s probably a mistake in the part of the code that looks for the serial port to communicate with Arduino. On my computer that was the second serial port in the list. I don’t have the code in front of me, but try changing the serial port index variable from 1 to 0.

  32. Thank you for sharing this modification of Krodal’s code. When I run the code (without visualising it through Processing) and switch on the Serial Monitor to see the raw values (like in Krodal’s code) I get this on the serial monitor:

    ÊJÖ̌LÊ
    Lˆø½M*ˆŒŒ H@8NŒLŽŠÈJç
    ŠHŒÊJJÖ̈LʈLNŠø½M*ˆŒŒ H@8Š NŠÈJç
    ŠHNˆÊJJÖÌLÈHLNŠø½M*ˆŒŒ H@8NŒLNˆÈJç
    ŒHNˆÊJJÖÌ LÈLNŠø½M*ˆŒŒ H@8ŒLŽŠÈJç
    ŒHŽˆÊJJÖÌ
    ̈LNŠø½M*ˆŒŒ H@8ŽŠLNŠÈJç
    ŠHŽŒÊJJÖÊ ÌJLNŠø½M*ˆŒŒ H@8ŽŒLŽŠÈJç
    NˆHŠÊ
    JÖÊ
    ÊJLNˆø½M*ˆŒŒ H@8ŒLŽˆÈJç
    ŠHŠÊ
    JÖÊ Ê LNˆø½M*ˆŒŒ H@8NŠLŠÈJç
    ŠHˆÊJJÖÊ ÊHLNŠø½M*ˆŒŒ H@8ŽŠLNˆÈJç
    ŒHŽŠÊŠJÖÊ È
    LNŒø½M*ˆŒŒ H@8NŠLŽŒÈJç
    ŒHŽˆÊ JÖÊH È
    LŽˆø½M*ˆŒŒ H@8ŽŠLŽŠÈJç
    ŒHNŒÊ JÖÊJ ÊHLŽˆø
    .
    .
    .

    Do you have any idea how I can fix this in order to display normal letters and numbers. I am a newbie with Arduino so I would appreciate an easy to digest solution, please. Cheers.

    1. It looks like the baud rate of the serial port (set in the Arduino sketch) doesn’t match that of your terminal window. Try changing the rate displayed in the window and see if that helps.

      1. Yes the baud rate in the arduino sketch is set to 19200 while in the processing one is 38400.
        I have problems whit the part that finds the port name and manually set it to “0”.
        Then some other problems are related to incompatible video card and opengl drivers.

        I know it is old but i think it will help someone.
        Good code, but i am looking for a simple tilt sensor to attach to a bottle and the sy521 seem to complex for that simple task… any help?

  33. If this is what I am suppose to see then it’s fixed:

    DEL:0.0020000002#ACC:0.76,-4.29,0.00#GYR:-0.00,-0.00,-0.00#FIL:0.03,-0.17,-0.00
    DEL:0.5109999656#ACC:1.01,-4.35,0.00#GYR:0.01,0.03,0.06#FIL:0.08,-0.31,0.06
    DEL:0.5090000152#ACC:0.87,-4.11,0.00#GYR:-0.05,0.04,0.09#FIL:0.06,-0.45,0.09

    Thank you very much for the support and quick reply !

  34. hello! congratulations, you’re really a myth! very good! and thank you very much!

    Sorry, but I have a problem with processing, it is the first time I use it and I could not understand why he says: “OpenGL error 1282 at bot endDraw (): invalid operation”
    and do not open the drawing animated in 3D.

    Can you help me please?
    thanks and congratulations again!

    1. Hi Federico, what release of Processing are you using ?
      Take a look to my message above. I solved my issues using a previous release of the environment.

  35. Hi, thanks for your time, I had read that it was better to use version 1.5.1 for windows and I’m using this.

    My procedure:
    Load the sketch on Arduino, connected to the sensor, and data are visibles on the serial monitor … Perfect…
    Then I use processing, with his sketch, and I click on Run.

    and … window opens with the three parallelograms, but each parenthesis shows the value “0” and the figures remain motionless.

    thanks

  36. Hi Federico, I’m wondering if everything is working well on the USB/com communication (maybe not…), if I was in your shoes I would check the USB in the System’s devices properties of windows.

  37. Hi Mauro;
    it is ok; Arduino Uno is on COM11; and it communicate correctly, because the values are correctly printed in the Serial Monitor.

  38. Hello
    Thanks a lot for uploading the Processing Sketch. It really helped me to clear some concepts. I have been trying to write a quadcopter stabilization code for sometime now but after reading a lot of articles blogs and finally seeing your processing sketch in action I now know that I need 10DOF IMU instead of the 6DOF that I currently posses.
    One thing that I saw is that you have used complementary angle to do the final calculation. If you got time why don’t you use the Kalman Linear Quadratic Equation or Kalman filter. You can get a lot more accuracy and will be able to correct the drifting that the gyro experiences. It was clearly seen that after a minute or two the raw gyro values became biased in one direction.

    Thanks again for the great upload and the very informative posts

  39. Hi.

    Great blog.

    I downloaded the sketch onto the arduino, and I was able to run the processing code as well.

    But, after the code was loaded, the 3D objects on the screen were not stable. Also, the blue box for the accelerometer was not visible.

    What could I have done wrong?

  40. Thanks so much for making this available. I never expected to progress from a blinking LED, to making a simple gimbal with a couple of servos, in just a few hours after unboxing my first arduino!!

  41. Just wanted to let you know that I’ve been pouring over this page for about a week and I’ve been angry/confused/sad/crazy trying to work this all out. i just finally got my prototype working for a product I’m designing. THANK YOU SO MUCH!!!

  42. Thank you so much for posting this code! It helped me a lot with a project. I’m having some problems with the processing sketch. Whenever I run the sketch, it tells me that the port is busy. I already have the arduino sketch running and outputing data to the serial monitor. Here is the error message:
    java.lang.RuntimeException: java.lang.RuntimeException: Error opening serial port /dev/tty.usbmodem411: Port busy

    1. I don’t know what specifically is causing the error. I’m running under Windows 7 and found that sometimes when I’d quit the Arduino sketch, it wouldn’t always free up the port, and I’d have to reboot the computer. You should also check to make sure that it’s trying to access the correct port. The code opens the second port in the list of ports, however that may not be the port you’re using on your computer.

  43. Hi! first of all thanks for sharing article! very helpful!
    In arduino the code is working great, but when i try to run on processing this error appears and on my viewport the cube doesn’t move.
    The error:

    Error, disabling serialEvent() for COM4
    null

    I’m using an arduino leonardo board with gy-521
    Thanks in advance!

  44. Hi Debra,
    It is the first time i am using this chip. I am controlling two wheeled mobile robot, i.e position control using arduino. The idea i have is to use this chip to determine the position of the mobile robot which i will then feed back to the reference position for comparision. Can i use the quaterion values (w x y z) as my measured position or i need to integrate the x,y,z acceleration to determine them? Please tell me how i can determine xy position of my mobile robot using this chip.
    Thanks in advance and looking forward to hearing from you.

    1. If you use the IMU values from the Digital Motion Processor, aka the “DMP” (for more info, see the post http://www.geekmomprojects.com/mpu-6050-dmp-data-from-i2cdevlib/), the DMP takes care of the integration and calibration of the MPU6050 chip for you. Otherwise, if you are going to compute the quaternions yourself, you will have to do the angle integration yourself as well. I’m not sure what you mean by xy position of the robot. The IMU will help you determine angular orientation of your two wheeled robot, but it is very difficult to use it to get an accurate position. For a two-wheeled robot, you should really only have one degree of freedom anyhow, as it will only tip forwards or backwards. And since your robot can’t presumably tip more than 90 degrees in either direction, using quaternions may be overkill for your application. A complementary (or Kalman if you feel like a challenge) filter should work just fine. I’m actually working on a two-wheeled self-balancing scooter myself right now, and the complementary filter is doing an ok job.
      Edit: I just realized that you may want to use the IMU to measure rotation about the vertical axis for turning purposes, as well as using it to balance the robot. If that’s what you mean, it’s very hard to get accurate rotation about a vertical axis using a complementary filter, since the accelerometer does not give rotation information about the Z(vertical)-axis. In this case you should definitely check out the article I linked to above for using the DMP to compute rotation about all 3 axis, as whatever (unknown) algorithm the MPU6050 uses to compute angular rotation appears to handle the Z-axis rotation resasonably well.

      1. Thanks admin for your quick reply. The reason i need xy position measurement is because am doing trajectory control where i need to feedback x, y, theta in order to track the position of my my mobile robot. Theta being the angle of rotation or heading angle. Hence i need these three parameter s but as mentioned earlier i dont know which values from the dmp to use. Otherwise again thanks and am taking a look at the link. You are highly welcome to elighten me more if you understand my problem

        1. The MPU6050 will give you angular velocity and angular orientation data but not position data. Even with a 6DOF IMU, it’s not so easy to get accurate information about rotation around the vertical axis (what I assume you mean by theta). The complementary filter won’t work for theta. You will need to use the data from the DMP to get that. An IMU isn’t really the right tool to use to get position data. It’s theoretically possible, but you’d have to take the accelerometer data directly, and integrate twice to get position. Errors will accumulate very rapidly. If your robot won’t be slipping, you’re probably better off using encoders on the wheels to give you distance travelled combined with theta to get the overall position.

  45. Hello. Thanks for the cool article.
    I want to use your source code for my project,
    so can I use your source code freely? (modification, redistribution or commercial etc…)

    1. Hi, I’m sorry I don’t fully understand the question. The Arduino pin assignments are set in the code. If I’m not understanding, please clarify the question.

  46. Admin,
    In this article you connect:
    VCC -> 3.3V
    GND -> GND
    SCL -> A0
    SDA -> A1

    So I wanna change:
    SCL -> A2
    SDA -> A1

    How I can do that?
    I’m new at this and couldn’t find anything but everything is working perfect and I just want to change SCL and SDA pin number.

    Thank you so much 😉

    1. Actually you’re correct, they’re not set in the code, however A4 and A5 are the default pins for the i2c bus, which is the communication protocol used to send data back and forth between Arduino and the GY-521. The pins are set in the Arduino “wire” library. You can attach multiple devices in parallel to the i2c bus, so you shouldn’t have to free up those pins if you want to add another device. If you really want to swap in different pins, you could try this link to todbot’s blog, where he’s rewritten the wire library to use different pins: http://todbot.com/blog/2010/09/25/softi2cmaster-add-i2c-to-any-arduino-pins/. I’ve never tried it, though.

  47. Try changing “portIndex” variable to a different number.
    mine worked on:
    short portIndex = 5;

  48. Congratulations for the blog, it clarified a lot about how to use a gyroscope and accelerometer in microcontrollers! Thank you!!

  49. Mr admin.
    the codes on ardiuno and processing are running fine. but i don’t see any data. the rectangles don’t move and the accelerometer rectangle doesn’t even show. how can i see weather the data is making it to processing? the ardiuno is connected to com9 if it helps. I’d be very glad if you could help

    1. Hi Ebrahim,
      I know others have had a similar problem. I’m afraid I don’t know what causes it. Are you sure that processing sketch is finding the correct port? The sketch I wrote just pulls the 2nd port from the list of ports, but that might not be the correct port to connect to on your computer. I think a few other people had better luck using an earlier version of Processing. You might also check to make sure you’re using the 32 bit version of Processing, as that’s the only one that works with Serial Port access. Good luck, and sorry I can’t offer more help.
      Debra

      1. Thanks for the reply Debra. I got it to work by changing portIndex from 1 to 3, and the bits per second to 9600.

  50. Hi Debra
    Thanks for a wonderful article on displaying the output from an IMU. I am having a problem with the processing sketch same as Andrew Bishop where the com port is busy. The arduino sketch is working perfectly and sensor data is being transmitted to the serial monitor. I am running win 7 and downloaded processing win 32 bit. I then tried the very early version of processing 1.5.1. The 2.2.1 version of processing gives the port busy error. The 1.5.1 version gives “error inside serial. ”
    I then tries using a different arduino board. First board is the UNO. Second board is the duemilanovue. UNO uses com7, Due uses com8.
    I would really like to get the graphic’s working, but am having no luck. Any suggestions would be welcome.
    Does it matter what sequence you start up the processing software? Should you start the arduino first and then run the processing or vice verse?

    1. I’m afraid I’m not sure what the source of those errors is. I’ve only run this program with Processing 1.5.1, which worked well for me. In that version of Processing, serial communication only works in the 32 bit version, not the 64 bit version. Are you using the 32 bit version of Processing 1.5.1? That’s the only thought I have right now. It shouldn’t matter what order you run the Arduino or Processing sketches in.

  51. Hi~
    I need your help

    It was good at using program in my computer but happened error in another computer.
    although same source file..

    I don’t know what to do

    Exception in thread “AWT-EventQueue-0” java.lang.ArrayIndexOutOfBoundsException: 1
    at ShowGY521Data.setup(ShowGY521Data.java:47)
    at processing.core.PApplet.handleDraw(PApplet.java:2361)
    at processing.opengl.PJOGL$PGLListener.display(PJOGL.java:862)
    at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:665)
    at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:649)
    at javax.media.opengl.awt.GLCanvas$10.run(GLCanvas.java:1289)
    at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1119)
    at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:994)
    at javax.media.opengl.awt.GLCanvas$11.run(GLCanvas.java:1300)
    at javax.media.opengl.Threading.invoke(Threading.java:193)
    at javax.media.opengl.awt.GLCanvas.display(GLCanvas.java:541)
    at javax.media.opengl.awt.GLCanvas.paint(GLCanvas.java:595)
    at sun.awt.RepaintArea.paintComponent(Unknown Source)
    at sun.awt.RepaintArea.paint(Unknown Source)
    at sun.awt.windows.WComponentPeer.handleEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
    java.lang.RuntimeException: java.lang.ArrayIndexOutOfBoundsException: 1
    at com.jogamp.common.util.awt.AWTEDTExecutor.invoke(AWTEDTExecutor.java:58)
    at jogamp.opengl.awt.AWTThreadingPlugin.invokeOnOpenGLThread(AWTThreadingPlugin.java:103)
    at jogamp.opengl.ThreadingImpl.invokeOnOpenGLThread(ThreadingImpl.java:206)
    at javax.media.opengl.Threading.invokeOnOpenGLThread(Threading.java:172)
    at javax.media.opengl.Threading.invoke(Threading.java:191)
    at javax.media.opengl.awt.GLCanvas.display(GLCanvas.java:541)
    at processing.opengl.PJOGL.requestDraw(PJOGL.java:688)
    at processing.opengl.PGraphicsOpenGL.requestDraw(PGraphicsOpenGL.java:1651)
    at processing.core.PApplet.run(PApplet.java:2256)
    at java.lang.Thread.run(Unknown Source)
    Caused by: java.lang.ArrayIndexOutOfBoundsException: 1
    at ShowGY521Data.setup(ShowGY521Data.java:47)
    at processing.core.PApplet.handleDraw(PApplet.java:2361)
    at processing.opengl.PJOGL$PGLListener.display(PJOGL.java:862)
    at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:665)
    at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:649)
    at javax.media.opengl.awt.GLCanvas$10.run(GLCanvas.java:1289)
    at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1119)
    at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:994)
    at javax.media.opengl.awt.GLCanvas$11.run(GLCanvas.java:1300)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
    Could not run the sketch (Target VM failed to initialize).
    For more information, read revisions.txt and Help → Troubleshooting.

    Help me~

    1. Hi Jason,
      It looks like your processing sketch is not connecting to the correct serial port to get the Arduino data. The Processing sketch I wrote defaults to picking the second value from a list of serial ports on the host computer. You may only have one serial port in the list, so trying to access the second element is giving you an out of bounds exception. Try changing the index into the array to [0] instead of [1] and see if that helps. Offhand, I believe the variable you need to change is called portIndex. The value of the serial port you need to run the Processing sketch depends on the setup of the computer you are using. Hope this helps.
      Debra

  52. Salut ,
    je rencontre le meme problème que Fiderico fenêtre s’ouvre avec les trois parallélogrammes, mais chaque parenthèse indique la valeur “0” et les chiffres restent immobiles.
    s’il vous aidez moi c’est très urgent !! et merci d’avance .

    1. Think it’s better you write in English, if your issue is really urgent, as well as this site is written in English…

    2. It sounds like the data is not getting across the serial port from the Arduino to the Processing sketch. Other people have had difficulties with this. When I wrote this sketch, only the 32 bit version of Processing supported serial data. That may be something to check. Also make sure the serial baud rate is the same between Arduino and Processing, and that your Processing sketch is accessing the same port number that your Arduino is writing to. If none of that helps, you might try using an earlier version of Processing – some people in earlier comments found that helpful.

  53. Hey, i just wanted to thank you for sharing your projects!

    After hours and hours using 2 different arduinos on 4 different pcs with 3 different OSes (and destroying some MOSFETs) I finally got to work what i wanted and I learned a lot 😀

    Without your post (and the one about i2cdevlib) it would have taken a lot more longer!

    Initially I wanted to build some 20 gramm micro quadrocopter. I’m just not sure if i manage to build the motor control pcb that easy because smd soldering and bad eyes/uncalm hand are not the best combination. But when i finish I will open up some blog and share it.

  54. hi,
    Is that we can calculate the position from MPU6050??
    normally when we have a linear acceleration we can deduce the position but in our case is the angular acceleration so what is the solution?

    1. If you want to know the physical position in space of your object, you could theoretically integrate the data from the accelerometer in the MPU-6050 twice to get position, however it wouldn’t be very accurate for two reasons. First, you would gain a lot of noise in the integration process, and secondly, the accelerometer readings themselves are very noisy, which is why we combine them with the gyroscope readings in the complementary filter.

    1. Sorry, that question is a little to vague for me to know what the problem is. I recommend reading previous comments where people had problems to see if any of their problems were the same as yours.

    1. It probably wouldn’t work directly. You’d have to adapt it. The wire library that the I2C communication depends on was developed for the Arduino architecture.

    1. I’m afraid I never got around to quantitatively comparing the data to another source, so I don’t have an answer for that.

  55. but galileo got wire library as well, it works for accelerometer but cant work for gyroscope, i got a zero for my gyroscope result

  56. Hi,
    Thanks for the wonderful tutorial.
    However, I have a question to ask. I found that the serial communication seems to get slower and slower over time, if the board is connected and the code is running for a long time. It is smooth at first, but tends to start lagging in around 1 minute. This happens for both Arduino serial monitor and Processing sketch. Is this normal? If not, what could be the cause? Is it caused by the code or the board itself?
    Thanks

    1. Sorry, I’ve never noticed that effect, and I’ve let the sketches run for long periods of time in a demonstration. Have you tried setting the baud rate higher in both the Arduino and Processing sketches?

  57. It seems like changing the baud rate doesn’t help. Serial communication still getting slower and slower over time, and there is no difference between different baud rate.
    One thing to mention, I am using Galileo board. Is it possible that it is due to the incompatibility of libraries?

  58. May i know your gyro, when you turn about x-axis, the value is it limited to only 90 degree?do yours face this problem?

    1. The range of the inverse Arctangent function is (-Pi/2,Pi/2), which is why this method won’t work easily for ranges greater than that. See my more recent post on using the i2cdevlib library with the DMP (digital motion processor) in the MPU6050 which addresses this issue specifically.

    1. The time constant needs to be longer than the typical accelerometer noise, but shorter than the timescale over which the gyroscope displays significant drift. I could see significant gyroscope drift after a couple of seconds. I didn’t do any specific calculations to come up with a time constant of 1 second, I just played around with different values of α until the results looked good. There’s a nice explanation of the time constant in the complementary filter here: http://www.instructables.com/id/Segstick/step10/A-very-flattering-filter/.
      Debra

  59. Hi Admin,
    I have tried using your both the sketches.I am having some issues related to processing.When I run the processing sketch I see all the three rectangles.But on moving the MPU6050 the rectangles won’t rotate.Seeing the above posts I used Processing 1.5 instead of higher versions and changed the portIndex no to 0 also.Still it doesn’t work.Is it that no data is being received???

    1. It sounds like the data isn’t getting across to the processing sketch. Make sure your baud rates match in Arduino and Processing, and it might help to put a few “print” statements in the Processing sketch to see what kind of data you are receiving, if any. Also, depending on your computer’s configuration, your portIndex value is whatever index into the list of ports matches the serial port that the Arduino is connected to.

  60. It might be possible to build a calibration curve. But I see you are more concerened with calibration at start-up, so that the program has a reference point.

  61. Thanks so much to post this.
    My arduino is running (COM 15) and the sketch in processing tell me:

    java.lang.RuntimeException: Error opening serial port COM 15: Port busy.

    I change this line:
    short portIndex = 2;
    Please help me…

  62. I use MPU6050 to command my robot for different direction so it’s work normally but one problem that paused it’s stop working (blocked ) I don’t know were is exactly the problem .
    please help me…

  63. Hi, please can you put a code using just l2cdevlib and arduino?
    I am really fashinating by your work but I really apreciate if you can put a code showing XYZ angle without using of external processing but just using arduino serial monitor.
    this could be really useful for who, like me, is in a very low knowledge level.

    Thank you in advance!

  64. When you say someone has already reverse-engineered the MPU-6050, isnt the datasheet / product spec freely available?

    I understand you opted to start with Krodal’s driver, but can you elaborate the conflict you found between the latest FreeIMU (Fabio Varesano) build and I2Cdevlib (Rowberg) ?

    Not sure how a magnetometer fits in all this, but if a given accelerometer can measure 10khz max movements, would a gyro even be needed? Or is it ‘noisy’ even if used under its rated capacity?

    Finally, regarding the 32-bit Processing2.0b8 sketch (ShowGY521Data) is it possible to rotate an actual 3d representation of the board? Or even a 3d object from grabcad, yobi3d, tf3dm, etc?

    1. Hi Ben,
      * At the time I wrote this, the firmware function calls had not been released to the general public by Invensense. I believe they have since been made available.
      * When I wrote this I found that the version of I2Cdevlib which was used by FreeIMU was older than the current version of I2Cdevlib. I2Cdevlib has been updated much more recently than FreeIMU
      * Without gyroscope or other complementary data, the accelerometer noise cannot be reduced by a higher sampling rate, only by averaging the accelerometer readings over timescales longer than the noise “spikes”. The longer the time period you average over, the greater lag you get in responsiveness of your data to the actual orientation of the IMU, which is generally undesirable. Also a longer averaging period may end up smoothing out some of the shorter timescale features of your data. Even the complementary filter has a slight time lag which you can see if you read my post titled “MPU6050 Redux”
      * You can rotate any shape you want in the Processing sketch – instead of drawing the rectangles, draw any shape you want and apply the appropriate rotation computed by the IMU to your coordinate system.
      I’d recommend you look into retrieving MPU-6050 data directly from the DMP. It seems to be more responsive and accurate (as well as easier to implement, as long as you avoid buffer overflow) than any other method I’ve seen.
      Debra

  65. Hi Debra, why the shapes in processing look like broken. not smooth,and just has the top and bottom surface?

    1. I think it has to do with the version of Processing you are using. I wrote the code with an older version, and have never gotten around to upgrading it. I believe that one or more of the function calls does not work correctly in the latest version.

  66. Hi Debra,
    Thanks for sharing your project work online. I’ve found it useful as I work on my own projects. Your kids are lucky to have a geek mum 🙂

    May I suggest you use Git to version control your code and push it up to Github.com. This will allow others to add and improve the code while maintaining a reference to each other as it evolves.

    Thanks again.

    Cheers,
    Janaka

    1. Hi Janaka,
      Thank you for the suggestion. You are right, of course, about using version control to maintain the code. I admit I haven’t been that organized about it, but will look into it. It is a good idea.
      Debra

  67. Hi,

    I copied the code but the rectangle doesn’t appear solid.. Only the top/bottom are shown, with the thickness planes not drawn, Any idea what could cause this?

    http://imgur.com/ABWpCI9

    I don’t see any errors in the Processing 2.2.1 panel, and the video card is good, so not sure what it could be.

    1. Hi,
      Yes, that problem appeared when Processing moved to version 2.1.1. In the setup() function of the Processing sketch, there’s a line:
      stroke(0,0,0);
      Try changing it to:
      noStroke();
      and see if that fixes your problem. I’m taking a closer look at the issue, and will hopefully post an updated (fixed) version of the Processing code within the next few days.
      Debra

      1. Also, in the draw(), function, just under the statement:
        background(0);
        add the line:
        lights();
        That fixes it. I’m uploading a fixed version of the Processing code now.

  68. Could you please help me get your Processing sketch working?

    I’ve downloaded Processing 2.0 (for a Mac) and when I try running your code, I get errors. I’ve downloaded the toxiclibs library as I saw was necessary based off of another YouTube video.

    Any help would be greatly appreciated!

    1. I’m not sure what kind of errors you’re seeing. I’ve just fixed an error in the Processing code that showed up in Processing 2.1.1, which made the rectangles display funny. You can see if that helps. Otherwise, I’d need to know more specifics.

  69. Sorry I didn’t include my errors initially. I downloaded Processing 2.2.1, but am still getting the following error when I upload the Arduino sketch and run the Processing sketch:
    java.lang.RuntimeException: java.lang.RuntimeException: Error opening serial port /dev/cu.Bluetooth-Modem: Port busy

    Please let me know if you have any ideas how to fix this.

    1. Sounds like a problem a with port access. Make sure you are accessing the correct port from the Processing sketch. The sketch uses an index into the list of ports to access the serial port. On my computer the serial port is second in the list, so I set portIndex = 1. This can vary by computer, so you might try a different value for portIndex, or you can try specifiying the name of the port explicitly (e.g. “COM24”). If you modify the Processing sketch to print out the names of the ports, that may be helpful.

  70. Welcome colleagues. I use the library Jeff Rovberg angle Z yaw (ypr [0] = atan2 (2 * q [1] * q [2] – 2 * q [0] * q [3], 2 * q [0] * q [0] + 2 * q [1] * q [1] – 1)) will change from the influence of the slopes along the axes X Y, how to avoid it? Requires that the course was not dependent on the slopes, it is possible. Sorry for my english, I’m from Russia.

  71. I changed my portIndex to equal 0, and I’m no longer getting the “Port busy” error. However, all of my rectangles are stationary and don’t react when I move my GY-521. Just to be sure, I need to have the Arduino sketch uploaded when I press Run in the Processing sketch, correct?

    1. It shouldn’t matter which sketch starts first. It sounds like the data is either not getting through to the Processing sketch or not getting through in a readable format. You should make sure the serial baud rates match in Arduino and Processing, and add some “print” statements to the Processing sketch to see if anything is coming through.

  72. Hi admin.

    I have a question about time constant of about 1seconds. in advance I apologize for my english. It is not good but i can do my best in order to tell my question. So, How do you decide the time constant as 1 seconds and Δt ? Could you please tell me ?

    1. Hi Hakan,
      Δt was my approximate sampling rate – I was getting updated angle data just about every 0.04 seconds. I know this because I printed out a time stamp with each data set, and viewed it in the Arduino serial window. The time constant of 1 second was more or less eyeballing the fluctuations in the acceleration to see how long they lasted, and picking a reasonable timescale just longer than that. I also saw that most other people who had used the complementary filter has values of α = τ/(τ + Δt) of 0.96 or 0.98, and worked backwards somewhat. α is a measure of the relative importance of the contribution of the gyroscope to the accelerometer. Shane Colton does a very good job in his paper (http://web.mit.edu/~jinstone/Public/filter.pdf) of explaining how the complementary filter is really a high pass filter on the gyroscope data plus a low-pass filter on the accelerometer data. You should probably look there for more detail.
      Debra

  73. Thanks, that works perfectly!

    The ‘noStroke()’ added the coloring to the other sides, and the lights() made the shading look right!

  74. Thanks, so is the basic idea of the dmp,
    http://www.geekmomprojects.com/mpu-6050-dmp-data-from-i2cdevlib/

    that it outputs data in ‘quaternions’ format, which doesn’t suffer from gimbal lock.. with the potential downside that the data isn’t in a as readily usable format, like angle x,y,z?

    Interestingly, the Processing code for this non-dmp version, doesn’t have any (atan) math in it… it uses the angles directly from the Krodal code that sends it. But looking a the Krodal code it’s not there either! Is the chip in a non-quaternions mode that sends angles directly? And is therefore susceptible to Gimbal Lock?

    Also, the processing code has a comment ‘It gives the z-orientation data as given by the gyroscope’, but I don’t see z_gyr used anywhere. Is the z-axis angle computed using the gyro data?

    1. The DMP does the rotation angle calculations for you, which can save your program from having to do them. It is able to compute rotations of more than 180 degrees, and can return the rotation angle information in many different formats, including quaternions, euler angles and yaw-pitch-roll among others. You can use the functions in the I2CDevLib library to access the angles in all these different formats. Since orientation angles come from the DMP which presumably uses quaternions or something similar in its calculations, you don’t have to worry about gimbal-lock. You can look at the examples in the I2CDevLib library to see how to call these functions.

      With respect to Z-axis rotation (yaw) – it is not shown in the comparison of gyroscope, accelerometer and complimentary filter data. Only pitch and roll are shown in this example.

  75. In regards to converting the raw accelerometer and gyroscope data into units of [g] and [deg/sec], the data sheet says to divide by 16384 and 131 (as you mentioned). Do you have any idea why these are the numbers we’re supposed to use to convert everything to meaningful data? For instance, why aren’t the numbers 37 and 1000, or 4 and 598349?

    1. The factors used to convert gyroscope and accelerometer data from the MPU-6050 are determined by the factors FS_SEL (gyroscope) and AFS_SEL (accelerometer) which set the sensitivity and range of angles which can be detected by these sensors. The defaults for both FS_SEL and AFS_SEL are 0, which results in conversion factors of 131 and 16384, however setting different values of FS_SEL and AFS_SEL will require different conversion factors. These are listed in the datasheet here: http://www.invensense.com/mems/gyro/documents/PS-MPU-6000A-00v3.4.pdf, on pages 12 and 13.

  76. Hi Debra, I found your blog very fun and useful! I am working on this project and I have followed all the steps required. However, each time I press the play button on processing, the “showgy521data” always freezes and does not display anything for me.

    Please advice

  77. Hi Debra, Thanks a lot for your blog , the whole blog :))
    I only have one question, shouldn’t the sampling rate be calculated by the equation provided in the data sheet
    Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV)
    where Gyroscope Output Rate = 8kHz when the DLPF is disabled (DLPF_CFG = 0 or 7), and 1kHz
    when the DLPF is enabled
    how can that get the 0.96 which you’ve explained to be an empirical number that you got by serial printing the time before and after every sample … how is that ?

    1. You’re mixing up Δt = sampling rate and τ = time constant greater than timescale of typical accelerometer noise. It is τ that is used in the computation of the complementary filter parameter. See page 13 of Shane Colton’s writeup at http://web.mit.edu/~jinstone/Public/filter.pdf for the meaning of τ used for the complementary filter computation.

  78. Hi there, I just want to say thank you very much for your thorough explanation and awesome job on the coding. I am doing my Final Year Project and your posting help me a LOT!!!! Thanks!!!! Can’t be more grateful ^^

  79. Hi there,
    I’ve used your arduino code and dowloaded 32 bit processing, when trying to access the 3D rectangle blocks it throws up error codes, any idea why?

    I’m using a arduino uno & MPU 6050

    many thanks

    Ben

    1. Not really enough information there, but it sounds like you’re having an error on the Processing side not the Arduino side. Did you download the toxiclibs for Processing?

    2. It’s an array out of bounds error at line 58 of the Processing code. I can’t see the code where I am right now, but I’m guessing it’s in the serial port access where the program obtains a list of serial ports, and indexes into the list with variable portIndex. Try setting portIndex = 0 (instead of 1). If that’s not correct look for whatever array is referenced at line 58 of the code.

  80. Its comes up with could not run sketch, arduino side is processing data as can see it withing the sketch monitor.

    error code from processing is,

    Exception in thread “AWT-EventQueue-0” java.lang.ArrayIndexOutOfBoundsException: 1
    at ShowGY521Data.setup(ShowGY521Data.java:58)
    at processing.core.PApplet.handleDraw(PApplet.java:2361)
    at processing.opengl.PJOGL$PGLListener.display(PJOGL.java:862)
    at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:665)
    at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:649)
    at javax.media.opengl.awt.GLCanvas$10.run(GLCanvas.java:1289)
    at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1119)
    at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:994)
    at javax.media.opengl.awt.GLCanvas$11.run(GLCanvas.java:1300)
    at javax.media.opengl.Threading.invoke(Threading.java:193)
    at javax.media.opengl.awt.GLCanvas.display(GLCanvas.java:541)
    at javax.media.opengl.awt.GLCanvas.paint(GLCanvas.java:595)
    at sun.awt.RepaintArea.paintComponent(Unknown Source)
    at sun.awt.RepaintArea.paint(Unknown Source)
    at sun.awt.windows.WComponentPeer.handleEvent(Unknown Source)
    at java.awt.Component.dispatchEventImpl(Unknown Source)
    at java.awt.Component.dispatchEvent(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.awt.EventQueue$4.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
    java.lang.RuntimeException: java.lang.ArrayIndexOutOfBoundsException: 1
    at com.jogamp.common.util.awt.AWTEDTExecutor.invoke(AWTEDTExecutor.java:58)
    at jogamp.opengl.awt.AWTThreadingPlugin.invokeOnOpenGLThread(AWTThreadingPlugin.java:103)
    at jogamp.opengl.ThreadingImpl.invokeOnOpenGLThread(ThreadingImpl.java:206)
    at javax.media.opengl.Threading.invokeOnOpenGLThread(Threading.java:172)
    at javax.media.opengl.Threading.invoke(Threading.java:191)
    at javax.media.opengl.awt.GLCanvas.display(GLCanvas.java:541)
    at processing.opengl.PJOGL.requestDraw(PJOGL.java:688)
    at processing.opengl.PGraphicsOpenGL.requestDraw(PGraphicsOpenGL.java:1651)
    at processing.core.PApplet.run(PApplet.java:2256)
    at java.lang.Thread.run(Unknown Source)
    Caused by: java.lang.ArrayIndexOutOfBoundsException: 1
    at ShowGY521Data.setup(ShowGY521Data.java:58)
    at processing.core.PApplet.handleDraw(PApplet.java:2361)
    at processing.opengl.PJOGL$PGLListener.display(PJOGL.java:862)
    at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:665)
    at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:649)
    at javax.media.opengl.awt.GLCanvas$10.run(GLCanvas.java:1289)
    at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1119)
    at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:994)
    at javax.media.opengl.awt.GLCanvas$11.run(GLCanvas.java:1300)
    at java.awt.event.InvocationEvent.dispatch(Unknown Source)
    at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
    at java.awt.EventQueue.access$200(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.awt.EventQueue$3.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
    at java.awt.EventQueue.dispatchEvent(Unknown Source)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
    at java.awt.EventDispatchThread.run(Unknown Source)
    Could not run the sketch (Target VM failed to initialize).
    For more information, read revisions.txt and Help ? Troubleshooting.

    thanks again

  81. Hi

    I am learning this for a school project and am unable to get the IMU data to processing software. There are no errors that I encounter, just that there is no change in the positions with change in the IMU orientation. I would really appreciate some help on this.

    Thank you.

    Sambhav

    1. Try the same fix I just replied to the previous poster. It sounds like the data isn’t making it into the Processing sketch, most likely because it’s not accessing the same serial port the Arduino is writing to.

      1. Oops, I just realized my previous reply was on a different post. Here’s the gist of what I said: Most likely the Processing sketch is not reading the correct serial port to obtain the Arduino data. If you look at the setup function in the Processing sketch, it obtains a list of available ports and uses the variable “portIndex” to index into the list of ports. Try changing the “portIndex” variable to a different value (like 0) to get the sketch to read from a different port.

        1. Thank you for taking out the time to address my issue. I have already done that. My arduino is connected to port 4, COM11, which is what I’m using as my port index. I did try to read the values by observing the serial monitor in the arduino IDE and the accelerometer values don’t change and the gyro values keep changing. Can you please help me figure out what might be wrong?

          1. If your MPU-6050 is lying still, then it makes sense that the accelerometer doesn’t change and the gyro values change from drift. If that’s happening even when the IMU is moving, then there may be a problem with your IMU.

  82. Hi

    Considering that, I had the problem I earlier stated, I have got an new IMU and the problem still persists. Please guide through what else I could be doing wrong. As you’ve stated in the article above, I am using the 32 bit version of processing, will it make a difference if my Wondows is 64 bit? Also, the values in the serial monitor are more or less constant. I would really appreciate your help on this.

    1. If you think that your values from the IMU are not coming through correctly, then changing the Processing sketch won’t help at all. 32 bit Processing on 64 bit Windows is not a problem. Can you capture some of the values coming in over the Arduino serial port and post them? Try a set with the IMU lying still, and a set with the IMU in motion.

      As for libraries, if your code is compiling correctly, that implies that you’re not missing any libraries. I suppose you could have old versions. You should be sure you have a recent version of i2cdevlib. Updating i2cdevlib solved a different commenter’s problem. You do need the Arduino “Wire” library for the i2c bus. I really can’t visualize what the problem might be if I can’t see any of the output you’re getting, however, so you should look more closely at the output in the Arduino Serial window.

  83. Also, do I need to add a particular library before this? Anything for the I2C communication? I’d like to know the stepwise approach from scratch as I’ve just simply downloaded your code on to the arduino and connected it to the IMU.

    Thanks a ton

  84. I did update the i2cdevlib from https://github.com/jrowberg/i2cdevlib. I already have the wire library installed.

    These are the set of values while its laying still:
    DEL:0.0000000000#ACC:44.31,-44.99,0.00#GYR:0.00,0.00,0.00#FIL:1.77,-1.80,0.00
    Read accel, temp and gyro, error = 2
    accel x,y,z: 527, -11250, 22530
    DEL:0.0480000019#ACC:-26.53,-1.20,0.00#GYR:-3.32,7.70,-7.56#FIL:-2.54,5.62,-7.56
    Read accel, temp and gyro, error = 2
    accel x,y,z: 3842, 3796, 600
    DEL:0.0790000009#ACC:44.31,-44.99,0.00#GYR:-17.54,10.84,-31.69#FIL:-14.33,6.60,-31.69
    Read accel, temp and gyro, error = 2
    accel x,y,z: 527, -11250, 22530
    DEL:0.0810000038#ACC:-26.53,-1.20,0.00#GYR:-23.14,23.83,-44.45#FIL:-20.19,18.76,-44.45
    Read accel, temp and gyro, error = 2
    accel x,y,z: 3842, 3796, 600
    DEL:0.0830000019#ACC:44.31,-44.99,0.00#GYR:-38.08,27.12,-69.81#FIL:-31.95,19.38,-69.81
    Read accel, temp and gyro, error = 2
    accel x,y,z: 527, -11250, 22530
    DEL:0.0810000038#ACC:-26.53,-1.20,0.00#GYR:-43.68,40.12,-82.57#FIL:-37.11,31.03,-82.57
    Read accel, temp and gyro, error = 2
    accel x,y,z: 3842, 3796, 600

    And these while its moving:
    DEL:0.0000000000#ACC:44.31,-44.99,0.00#GYR:0.00,0.00,0.00#FIL:1.77,-1.80,0.00
    Read accel, temp and gyro, error = 2
    accel x,y,z: 527, -11250, 22530
    DEL:0.0480000019#ACC:-26.53,-1.20,0.00#GYR:-12.79,1.91,-14.66#FIL:-11.63,0.05,-14.66
    Read accel, temp and gyro, error = 2
    accel x,y,z: 3842, 3796, 600
    DEL:0.0810000038#ACC:44.31,-44.99,0.00#GYR:-25.38,14.90,-27.42#FIL:-21.48,10.72,-27.42
    Read accel, temp and gyro, error = 2
    accel x,y,z: 527, -11250, 22530
    DEL:0.0820000076#ACC:-26.53,-1.20,0.00#GYR:-47.22,18.15,-52.47#FIL:-42.65,13.37,-52.47
    Read accel, temp and gyro, error = 2
    accel x,y,z: 3842, 3796, 600
    DEL:0.0820000076#ACC:44.31,-44.99,0.00#GYR:-59.96,31.31,-65.39#FIL:-51.41,23.67,-65.39
    Read accel, temp and gyro, error = 2
    accel x,y,z: 527, -11250, 22530
    DEL:0.0820000076#ACC:-26.53,-1.20,0.00#GYR:-81.81,34.56,-90.44#FIL:-71.38,25.80,-90.44
    Read accel, temp and gyro, error = 2
    accel x,y,z: 3842, 3796, 600
    DEL:0.0820000076#ACC:44.31,-44.99,0.00#GYR:-94.55,47.72,-103.36#FIL:-78.99,35.59,-103.36
    Read accel, temp and gyro, error = 2
    accel x,y,z: 527, -11250, 22530

    I can see that though gyro seems to be responding, the accelerometer values are alternating.

    I’d love to know whats going wrong.

    1. I can’t see the exact problem, but you should be getting “error = 0” if everything is working correctly. You might start by Googling the problems that cause the MPU6050 to produce “error = 2”. I’ll let you know if I find out more.

    2. Here is a link to a post where they discuss the error codes: http://forum.arduino.cc/index.php/topic,139378.0.html. Additionally, an earlier poster on this page got the same error code, and said

      “So I’ve done some research and found that the error = 2 is because of insufficient power to the GY 521. Once I soldered the pins to the board and secured it to a wired bread board everything worked fine.”

      Maybe that will be helpful.

  85. For anyone having exception error 2 like I was, remove any mention of “Serial.list()[portIndex])” and put in your COM port directly –

    String portName = “COM2”;
    myPort = new Serial(this, portName, 19200);

  86. Hi,
    first of all , a big tnx for sharing the code.
    I have tested your code and it is more understandable rather than other libraries available in net.
    I have faced an issue andI dont understand why it happens ,
    when keep the sensor on flat surface, all three parameters of filter show 0 and that is so good, and when I rotate the sensor to +90 or -90 on either axes , it works fine.

    the problem: is that when i rotate the sensor to more than + 90 ( let say 130 degrees) , the filter do NOT goes beyond and it drops to + 60 or +50 . this happens for CCW direction as the filter should show value more than – 90 , it drops to -60 and it is not accurate.

    as i saw the video above, also you did Not rotate the imu sensor to more than 90 ib eider direction and axes,
    i appreciate if you help me out.

    1. This is because calculation of the tilt angle from the accelerometer uses the atan function, which has a range from -pi/2 to pi/2. If you want a larger range of angles from the MPU6050, you should use the direct measurements from the onboard DMP (digital motion processor). See the other two articles I wrote about the MPU6050. They go into more detail about DMP data vs. complementary filter calculations.

  87. Thanks a lot ,
    i’m using 3ms as time simulation in simulink , i have use the arduino library to build a mex file so that it will be supported by simulink
    so when i get the raw value from the gyro i multiplie it with (0.003/131 ) so when i change the angle 90degree it must give me 90degree but i don’t get this value i’m getiing about +0.6 in change
    for the accelrometer when i divide by 16384 i get a change of +1g when i move the sensor 90 degree in the corresponding orientation so it’s ok whith the accelro i think ??
    but the probleme is with the gyro …
    for the complementary filter have you any idea of how can i implement it using simulink ?
    thanks a lot
    (please email me your response if it’s possible)

    1. Hi,
      I’m afraid I don’t know anything about simulink. Looking at your data, it’s not clear to me how you measured the total change in your gyroscope angle data. You’ve presented a single data point over a .003 ms time increment. However to get the total rotation from gyroscope data, you have to integrate – add up multiple time increments. The gyroscope angular velocity measurements will probably change with time, so you have to add multiple increments of 0.003 seconds multiplied by the angular velocity for each interval.
      I hope that’s helpful.
      Debra

      1. thanks , yes i have integrated the output of the gyroscope to get the change in the position but i don’t get the right values ..
        for the accelerometer we can just mesure the tilt angle by the rotation of the sensor ?
        if i move the sensor in a corresponding axe (exp X ) in a table i don’t get any change , i got the change only when i rotate the sensor ..
        so how can i be able to detect the mouvement of a person walking and his direction with the accelerometre since it detect only rotation
        thank you :=)

  88. Nice writeup! And equally impressive that you’ve kept up with comments this long. I stumbled across this immediately after browsing through the thread krodark was participating in.

    I’ve ordered a gy-521 for a small project (actually, it’s the more expensive model that also contains a magnetometer, but I’m not looking to use that right now). I’m looking to use it to make some motion-reactive wearable lighting to complement a performance.

    However, all the material I can find revolves around finding the orientation, which I’m not directly interested in. I’m hoping to begin by simply dimming the lighting with the absolute magnitude of the acceleration vector, so that sudden flourishes will cause flashes. I’m wondering what the impact of gravity’s constantly changing axis is going to be – if this turns out to be excessively noisy, will it be feasible to filter down?

    1. Hi Sam,
      Thanks for the nice words. I’m a bit spotty keeping up with the comments, because after all this time I often forget the details of the program! I do know that you can obtain accelerometer data with the gravity vector subtracted out by using i2cdevlib, so that may be helpful. Read my post on i2cdevlib for information on how to use the library to get processed accelerometer data from the gy-521. It’s easier to use than getting the raw data and manipulating it yourself. I don’t remember the details offhand, but if you look into it and can’t figure it out, let me know and I might be able to point you in the right direction. I would imagine that you will want to do some sort of time averaging of the accelerometer data because it can be very jumpy.
      Good luck,
      Debra

  89. wonderful writeup GeekMom!! You avoided diving into the hairy math side of things and kept this very accessible – kudos!!!

    Thanks for distilling this info and linking to other work in this area, you created a big fan in Virginia!
    tim

  90. Hello Geekmom

    thanks for the great stuff. I like it a lot.

    It all seemed to worked great with my gy521. Once I got to the processing however it returned the following error :

    java.lang.RuntimeException: java.lang.RuntimeException: Error opening serial port /dev/cu.Bluetooth-Modem: Port busy
    at com.jogamp.common.util.awt.AWTEDTExecutor.invoke(AWTEDTExecutor.java:58)
    at jogamp.opengl.awt.AWTThreadingPlugin.invokeOnOpenGLThread(AWTThreadingPlugin.java:103)
    at jogamp.opengl.ThreadingImpl.invokeOnOpenGLThread(ThreadingImpl.java:206)
    at javax.media.opengl.Threading.invokeOnOpenGLThread(Threading.java:172)
    at javax.media.opengl.Threading.invoke(Threading.java:191)
    at javax.media.opengl.awt.GLCanvas.display(GLCanvas.java:541)
    at processing.opengl.PJOGL.requestDraw(PJOGL.java:688)
    at processing.opengl.PGraphicsOpenGL.requestDraw(PGraphicsOpenGL.java:1651)
    at processing.core.PApplet.run(PApplet.java:2256)
    at java.lang.Thread.run(Thread.java:745)
    Caused by: java.lang.RuntimeException: Error opening serial port /dev/cu.Bluetooth-Modem: Port busy
    at processing.serial.Serial.(Unknown Source)
    at processing.serial.Serial.(Unknown Source)
    at ShowGY521Data.setup(ShowGY521Data.java:60)
    at processing.core.PApplet.handleDraw(PApplet.java:2361)
    at processing.opengl.PJOGL$PGLListener.display(PJOGL.java:862)
    at jogamp.opengl.GLDrawableHelper.displayImpl(GLDrawableHelper.java:665)
    at jogamp.opengl.GLDrawableHelper.display(GLDrawableHelper.java:649)
    at javax.media.opengl.awt.GLCanvas$10.run(GLCanvas.java:1289)
    at jogamp.opengl.GLDrawableHelper.invokeGLImpl(GLDrawableHelper.java:1119)
    at jogamp.opengl.GLDrawableHelper.invokeGL(GLDrawableHelper.java:994)
    at javax.media.opengl.awt.GLCanvas$11.run(GLCanvas.java:1300)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:302)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:733)
    at java.awt.EventQueue.access$200(EventQueue.java:103)
    at java.awt.EventQueue$3.run(EventQueue.java:694)
    at java.awt.EventQueue$3.run(EventQueue.java:692)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:703)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:242)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:161)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:150)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:138)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

    Any suggestion what I coudl do?

    Thakn you very much already
    p

    1. It looks like a problem accessing the COM port on your computer. You should check to make sure you are accessing the correct one. The processing code accesses the COM ports by getting a list of all COM ports and just choosing the second one from the list, because that’s what works on my laptop. You can try specifying the name of yourCOM port directly, or using a different index into the COM port list. Some of the previous comments on this article address the same problem. Good luck.

      1. Dear admin

        got th eport to work and my excuses for the doubel ask.

        Now however I face the same problem as some others. I get the readings on the adruino serial… but the processing sketch wont move a thing. But I also dont get the error from before so it seems I m on the right port.

        Other users have had this problem also but I didnt find a solution to it. Any suggestions. The data does indeed not seem to be coming through.

        I m working on a mac and I believe all libraries are up to date.

        Thank you so much

        1. It sounds like the Processing program is either not receiving the data at all, or not interpreting it correctly. There could be a number of causes for this. You should try adding “print” statements into the Processing code to see what, if anything, is actually getting through. One thing to check is that the baud rate specified by the Processing code matches the baud rate used by the Arduino to send the data through the port. That’s all I have off the top of my head.

  91. Hello Geekmom,
    First of all I want to say that I used this stuff to explore and begin with the MPU6050. I wanted to compute as correctly as possible the attitude without using Kalman Filter.
    The second point is probably less pleasant because there are errors in this stuff. You have to keep in mind that 3D rotations are not as simple as presented here.
    When you speak of a drift in your video, in fact it’s not a drift. It’s a computing error and more accurately a calculus error. Integrating a 3D rotation about axis with your code :

    // Compute the drifting gyro angles
    float unfiltered_gyro_angle_x = gyro_x*dt + get_last_gyro_x_angle();
    float unfiltered_gyro_angle_y = gyro_y*dt + get_last_gyro_y_angle();
    float unfiltered_gyro_angle_z = gyro_z*dt + get_last_gyro_z_angle();

    never gives the total angles about the x, y and z axis that you need to send to processing… because axis are moving. You can keep your code and try to turn your gyro the most accurately as possible about an axis and then about an other axis and you will never see what you call a drift. It’s only because your formula is only working with 2D rotations.

    To put it an other way, if you read processing code you see 3D rotations :

    rotateX(radians(-x_gyr – x_rotation));
    rotateY(radians(-y_gyr));

    As everybody know rotations are non commutative. That mean you cannot inverse this code, beginning with rotateY and after operating rotateX (only if angles are greater than 15°). But where is this non commutative law in the computing of gyro integration code.

    Sorry, but at the moment I have no correction to publish … but perhaps later in the French Wikiverity :
    https://fr.wikiversity.org/wiki/Micro_contr%C3%B4leurs_AVR/Travail_pratique/Utilisation_d'un_Acc%C3%A9l%C3%A9rom%C3%A8tre_MPU6050

    Thank you so much for your work

    1. Thank you for your feedback. I think there is a bit of a misunderstanding here. Firstly, with respect to “drift”, I believe we are referring to the same thing. If you read the following paragraph from this post:

      Computing orientation from the gyroscope sensor is different, since the gyroscope measures angular velocity (the rate of change in orientation angle), not angular orientation itself. To compute the orientation, we must first initialize the sensor position with a known value (possibly from the accelerometer), then measure the angular velocity (ω) around the X, Y and Z axes at measured intervals (Δt). Then ω × Δt = change in angle. The new orientation angle will be the original angle plus this change. The problem with this approach is that we are integrating – adding up many small computed intervals – to find orientation. Repeatedly adding up increments of ω × Δt will result in small systematic errors becoming magnified over time. This is the cause of gyroscopic drift, and over long timescales the gyroscope data will become increasingly inaccurate.

      the “drift” is clearly defined as an accumulation of small errors due to the (calculus) integration of the change in angular velocity. I think that we are actually saying the same thing here – there is just some confusion of terms. If that is not the case, then I am not understanding what you are saying.

      — OK – follow up here – I understand that you are saying that “drift” occurs because we are rotating in 3 dimensions. You claim that “drift” as I am measuring it would not occur if I could rotate around a single dimension at a time. I believe this to be false, because I see “drift” occur in the gyroscopic measurements when the IMU is held completely stationary. Only the incorporation of the accelerometer data into the complementary filter stops this “drift”.

      With respect to rotations, I think that there may be some confusion of coordinate systems. All measurements read from the IMU are with respect to a fixed coordinate system (Z-axis aligned with gravity). The rotations are not given with respect to a moving coordinate system. I am not applying successive rotations about different axes – the net rotation about each axis is computed independently, based on the data received from the GY-521. The rotations are only applied in the Processing code – and we are not applying the incremental rotations, only the net computed rotation about each axis.

      Perhaps I am not understanding you correctly, and if so, please elaborate. It would help to see what you consider to be the correct mathematics for this situation. These computations have worked well for me in a number of applications, so I’m having a hard time believing that they are incorrect. Can you point out a specific experiment I could perform in which these calculations will fail? That would help me understand the problem you are describing more clearly.

      Thanks for your feedback, and I appreciate your attention to this post.
      Debra

      1. We have effectively probably not the same vocabulary. What I call a drift is effectively a calculus error and the best mean to see it is to keep the gyro quiet (not moving) and you will see that your corresponding figure in Processing is still rotating. It’s while the unit is °/h (a rotation velocity)
        According to the video, it seems for me that what you call drift is :
        – I make different rotations and after them I see a difference between my gyro figure in Processing and my real gyro. If that, the unit has to be °

        But it’s not really the most important point. When you write “The rotations are not given with respect to a moving coordinate system” I have to say that it’s true but has to be completed. To explain that without mathematics I think it’s better to begin with acceleration.

        As usual, I use the words “ground” for the inertial frame of reference and “body” for your moving accelerometer. What is measuring the accelerometer ? Of course not the acceleration of the body in the body frame because it would be 0. It’s effectively measuring the acceleration of the body relative to ground but not in the ground frame of reference ! The measure is done relatively to the body frame of reference. I mean the acceleration relative to ground is projected in body frame of reference (it takes me months to understand that). Things would be easier (for trajectory reconstruction) if it was not the case (only double integration with no gyros). The point here is the projection operation which is possible because acceleration is a vector.

        Now let’s return to the rotation problem. Angular velocity is also a vector and angle is not. This is a fact and personally I have no intuitive view of this fact. But I know it’s true. And because Angular velocity is also a vector what your gyro is measuring is the rotation velocity of your body relative to the ground but projected in your body frame of reference. You probably forgot the projection. The consequences of that is that your integrations equations are false in your code.
        In fact, because angles are not vectors the integration process for rotations is not a summing one, as it’s generally the case (integration is denoting with a big S as sum). It’s a matrix multiplication (or a vector cross product). You can see it in
        https://gentlenav.googlecode.com/files/DCMDraft2.pdf (Equation 17)

        The beautiful thing is that instead of non commutativity it’s possible to make calculus with rotations.

        As you have seen in the previous post, I am writing around this subject in Wikiversity. For your information the code published at the moment is yours slightly modified… I begin to work with your code in February and after a pose spent hours in the beginning of September. Because I didn’t obtain the results expected I realized where the error was. I will publish a correction later.

        Thank you
        Serge

  92. Hi Serge,

    I’m afraid I don’t completely follow your logic. Seeing the actual mathematics would probably be helpful.

    One of the reasons I believe that the algorithm I’ve used works well is that I compared it to the data as computed by the MPU-6050 DMP (see the post http://www.geekmomprojects.com/mpu-6050-redux-dmp-data-fusion-vs-complementary-filter/). The complementary filter data tracks the DMP data, but with a slight time lag, which is to be expected with time averaging. So if this Complementary filter algorithm doesn’t work, then the DMP data must be wrong as well. Otherwise I’m missing something. Another successful (and similar) implementation of the Complementary filter can be seen here (http://www.pieter-jan.com/node/11) as well.

    I’ll be interested to see the final results of your computation in action.

    Debra

    1. Hello Geekmom,

      I cannot explain why your different results are the same. Perhaps tilt sensing with accelerometer is very important in your balanced filter.

      At the moment I try to find out a correction of the integration of the gyros data… and then I have not worked with balanced filter.

      I am also really interested with the other stuff you publish here…

      But enough speaking, it’s time to give code as soon as possible.

      Serge

      1. First try :
        Here is the code snippet :
        // Debra intégration
        unfiltered_gyro_angle_x += ((float) (GyX – base_x_gyro))*dT/FS_SEL;
        unfiltered_gyro_angle_y += ((float) (GyY – base_y_gyro))*dT/FS_SEL;
        unfiltered_gyro_angle_z += ((float) (GyZ – base_z_gyro))*dT/FS_SEL;
        //New rotations matrix calculation
        w[0] = ((float) (GyX – base_x_gyro))*dT/FS_SEL;
        w[1] = ((float) (GyY – base_y_gyro))*dT/FS_SEL;
        w[2] = ((float) (GyZ – base_z_gyro))*dT/FS_SEL;
        // °/s to radian/s conversion
        w[0]= w[0] * 3.14159/180;
        w[1]= w[1] * 3.14159/180;
        w[2]= w[2] * 3.14159/180;
        dcm_rotate(dcmGyro,w);
        // we have now to transform this dcmGyros matrix in the Euler’s angle as Processing.org expects
        // Euler 321 ???
        euler_y = asin(dcmGyro[2][0]);
        euler_z = asin(-dcmGyro[1][0]/sqrt(1-dcmGyro[2][0]*dcmGyro[2][0]));
        euler_x = asin(-dcmGyro[2][1]/sqrt(1-dcmGyro[2][0]*dcmGyro[2][0]));

        As you can read the way is to calculate dcm and after to compute the corresponding Euler’s angle. I use imu.h and vector3d.h from :
        https://code.google.com/p/picquadcontroller/source/browse/trunk/

        A first try is working but it is difficult to prove experimentally that my way is better than yours. The experience consists to send your data and mine in Processing for two different parallelepipeds and realizing true 3D rotations during 5 s and coming back to the start position. The better has be as near as possible of the start position (in Processing). I suspect my Euler conversion is not good… The limitation of any Euler’s angle to be between -pi/2 and pi/2 is also visible and probably a problem for this try.

        What will give the second try will be published later…

        1. I have put the complete code in my own Website :

          http://moutou.pagesperso-orange.fr/Gyros.zip

          where you can find an Arduino and a Processing code. I have modified the Euler’s angle conversion since yesterday.

          Both are Debra code slightly modified and given to compare two ways to integrate gyros data. With the left parallelepiped you can see the Debra’s code at work and with the right my code at work.

          Frankly speaking, I cannot say which code is better. Or perhaps I haven’t found an experience to answer to the question. When I move quickly my wrist during a little time I suppose mine is better but it’s only a supposition not always reproduced and not a perfect discrimination. If anybody has a good idea or doesn’t agree, you can write something here.

          What I want to say before closing this discussion is :
          Point 1 : I am absolutely sure that gyros are measuring angular velocity of the body in regard to the ground frame of reference but projected in body axis (see what is called figure 8 in this page for g vector) If it’s true for g vector I don’t see why it’s not true for angular velocity vector.
          Point 2 : Point 1 has as consequence that gyro data integration is not as simple as what we think at first.
          Point 3 : we are facing here an experience where mathematics are not discriminant enough, and I don’t understand exactly why. Perhaps the way of integration computing make rapidly big errors ?

          For now, I want to see what Digital Movement Processor gives and then follows the other Debra’s page.

          1. Hi Serge,
            Thanks for the update. I think you’re right that the best way to compare the different algorithms would be to test them against the DMP data. A plot of the angle data vs time would be useful to compare them.

            One thought I have is that you are focusing a lot of your energy on “fixing” the gyroscope data, however a complementary filter only relies on the gyroscope data over short time scales. Over longer time scales the computed angle is weighted towards the average accelerometer data. Perhaps your “fix” isn’t apparent over “longer” time scales. I don’t know if this is correct, but it’s what I’m coming up with off the top of my head.

            Good luck with your project.

            Debra

  93. Hello Geekmom,
    I completly agree with your point of vue : it’s proably better to work with DMP and to give up with gyro data integration.

    But before leaving I wanted to have a look at the accelerometer data. I really wanted to investigate on “Figure 8” of this page even if the code you provide works well.

    This “Figure 8” comes from AN:3461 (Kimberly Tuck’s one : 2007). Enven if it comes from an application note, it can contain flaw. The fact that it is included in this page indicates it gives you inspiration.

    What does explain the up part of the “Figure 8″ ? It’s not clear in fact ! At first I thought it explains the order of the sequence of Euler’s angles. But when you start from the left into the right, the step between the second figure and the third (x return in horizontal plan) means it’s not Euler’s angle sequence. But it stays a sequence (if not, why so many parallelepipeds ?) ! Then I read the corresponding text in AN3461 where it is writen :”Pitch is defined as the angle of the X-axis relative to ground…” The drawings of “Figure 8” and the text are not in correspondance : in the text, Pitch is clearly a projection angle and in the drawing, I have no idea what they want to explain but it’s clearly not a projection (probably a sequence) ?

    One possible problem is : if the text is true your Processing code is false. You clearly use a sequence of angles with rotateX first, and after rotateY. And there is no direct relationship between projection angles and Euler’s angles ! I mean we have to compute something. Because your code is working it is possible that the text of AN3461 is false ! And we come back again and again in the drawing part of “Figure 8” where after hours I am unable to say what is explained !

    What can be said about the bottom part of “Figure 8”, the formulas ? AN3461 text and “Figure 8” don’t explain where formulas come from. There is a new more rigourous AN:3461 (Mark Pedley 2013) where it is shown that formulas are very dependant of the Euler’s angle sequence and where only two Euler’s angles are drawn.

    At the moment I am unable to say if there is a problem or not in your code, or why it works so well. The only thing I have experimented is :
    if I use the third formula of “Figure 8” what happens then in Processing windows is not clear. I have tried with other sequence of Euler’s angles in Processing code without success… And what I see is characteristic of a false Euler’angle sequence. The sudy of second version of AN3461 tends to say it is simply impossible to find out more than two Euler’s angles when sensing with accelerometer.

    Because I have not all the answers of all the questions presented here, I want to spend little time to investigate further. Perhaps you consider it’s a waste of time because DMP does the job… but I don’t use exclusively MPU6050. Sometime I use Nunchuck gamePad (lab with students) where only accelerometers are present… and I want to understand what is the beter tilt sensing I can do with this gamePad.

    Serge MOUTOU

    1. I want to make here a short point on accelerometers.

      – Only the drawing part of Figure 8 is a problem. I have published a more explicative figure in wikipedia (https://commons.wikimedia.org/wiki/File:3DAccelerometer.png) but probably more complex ! Every parallelepiped has its own formula and I show the respective right triangle where the formulas come from.
      – At first glance it is not easy to see the relation between the first angle phi (on the left) and the definition of this angle (angle between Y axis and horizontal plan) but with a little attention you can easily see that both angles have their side perpendicular
      – I eventually demonstrate that Formulas given in Figure 8 are in accordance with the corresponding text in AN:3461 (Kimberly Tuck’s one : 2007).
      – At the moment I am trying to make a true 3D tilt sensing. I make progress but I encounter problems with Euler’s sequence and probably rotation matrix. The only thing I can say : if I find out a solution it will be more complex than what is published here.
      – Last step : to prove that the code published here is effective when only roll and pitch are required.

      1. After a while, it’s time for me to make a conclusion.

        – Nor the Arduino code nor the Processing code of this page are incorrect. They only don’t speak the same language.
        – What is calculated with Arduino code is what is defined in AN:3461 (Kimberly Tuck : 2007)
        – What is needed by processing code is Euler’s angles (you find rotateX and after rotateY and I have checked if axis are rotating during this sequence and they are)
        – If you don’t believe this point, please add the third formula given in Figure 8 and the third corresponding rotation rotateZ…in Processing and see what happens. I have carrefully demonstrated, the formulas given in Figure 8 are correct. Why adding the third rotation gives us a mess (no correlation between my accelerometer and what I see on Processing Windows) ?
        – I have checked what I claim, with SCILAB, and discover that in fact when you make a confusion between the two AN:3461’s first formulas and
        the two first Euler’s angle, only one angle is good. Then I take time to experiment deeper to find rotations of the acceleromers that are not correctly represented by the Processing code and it is possible to find them.
        – Simulations with SCILAB show me that it is not easy as expected to find the 3D rotation : one way was
        1) retrieve the axis of rotation (cross product of both vectors)
        2) find the rotation angle : atan of ratio modulus of the cross product and the dot product
        3) normalization of axis vector
        4) reconstruct the rotation matrix (see wikipedia)
        5) calculate the corresponding Euler’s angle
        BUT it’s impossible to retrieve 3D rotation axis with a cross product as shown in https://commons.wikimedia.org/wiki/File:Accelerometer3.png !

        It’s time for me to have a look at the new Mom’s project : MPU-6050: DMP Data from i2cdevlib

        Thank you for your work

  94. How do i open the ShowGY521Data.pde file and make it run on my PC?
    when i open it with the arduino ide normaly it wasnt to compile it for the arduino and thats wron that should make me a local gui.

    I never used that functionality of the arduino IDE so i dont know what to do

    1. Only the GY521_Send_Serial file is an arudino sketch. You should get that one working first, and check that the data it writes to the serial port looks reasonable.

      The “ShowGY521Data.pde” file is a sketch to be used in Processing to help visualize the data. You will have to download and install the Processing IDE to get it to run. It is available at https://processing.org/.

  95. Hi Debra,
    great article!

    We are working on a head tracking solution based on the following components:

    -Arduino Uno R3/Arduino Micro R3
    – MPU6050 Gyro
    – Bluetooth: DE-HC-06BT

    We use sour script to smoothen the values.

    In the beginning everything works fine. But after a while it comes to a problem. The Yaw value is instable and starts incresing 0.01 degree per second.

    Have you noticed such kind of behaviour, as well?

    Best regards,
    Peter

    1. Hi,
      If you are using a complementary filter to obtain your angles, the yaw will drift because the yaw data comes only from the gyroscope while the pitch and roll data comes from a combination of the gyroscope and accelerometer. The accelerometer values cannot give orientation about the z-axis (yaw). The MPU-6050 DMP (digital motion processor) has a built in algorithm that can compensate pretty well for yaw drift. See the article: http://www.geekmomprojects.com/mpu-6050-dmp-data-from-i2cdevlib/, for how to use data from the DMP. I did a comparison between data from a complementary filter and data from the DMP in the article: http://www.geekmomprojects.com/mpu-6050-redux-dmp-data-fusion-vs-complementary-filter/, and you can see how they compare there.

      I hope this helps answer your question.
      Debra

  96. hi, thanks for the information
    i have a question, how i can calculate theta?
    you can give me the equation, thank you.

    1. If by theta you mean “yaw” (rotation around a vertical axis), you can only get theta from the gyroscope data, since an accelerometer cannot give yaw data. You must know the initial orientation, then you obtain the angular velocity from the MPU-6050 at regular intervals, and multiply the angular velocity by time to get the change in angle (theta= theta_0 + wt) This will give you the angle after a length of time, but it will be likely to “drift” because of the repeated integration over time. If you are looking for a more accurate way to get yaw from the MPU-6050, you should look at this article on how to use the on-board DMP (digital motion processor): http://www.geekmomprojects.com/mpu-6050-dmp-data-from-i2cdevlib/

  97. I’m just starting to look at the 6050. I ordered one but it hasn’t arrived yet. In the mean while I’m starting to read up on it.

    My objective is to create a safety device for aircraft that will let a pilot know when the airplane is starting to drift. The thing is I would need to know the orientation towards the earth even when the plane is banked. This is easy, yes? Well not really. The problem is that in a balanced turn the G forces will be directly in line with the banking angle of the aircraft, not with the Earth itself.

    Do you have any thoughts about whether or not it would be possible to pull this off?

    Thanks,

    Eric

    1. Hi Eric,
      That’s a really interesting question. I started to write an off-the-top-of-my-head answer, but realized I didn’t really know the effects of sustained accelerations on an IMU’s net output. It will obviously screw up the accelerometer readings, which are used for long-term averaging. I wasn’t sure about how the banking would affect the gyroscope, but apparently it does. It seems like you would need to integrate data from another sensor, like a magnetometer or GPS with the accelerometer/gyroscope data to get accurate orientation angle information. I found this interesting article: https://gentlenav.googlecode.com/files/DCMDraft2.pdf
      which has a lot of information about the exact thing you’re working on. Have you seen it? I hope it’s more helpful than I am on this question.
      Good luck,
      Debra

      1. Debra,

        Thanks for the response. I have not seen that doc and I will review it. I think that one of the first things I’m going to have to do once I have the chip working with an Auduino data logger is to take it up in the airplane and see what happens.

        Regards,

        Eric

  98. Hi Debra

    thanks for all your work here and just a quick question if I may. I am using a quadcopter flight control board with a MPU6050 chip on it and and just wondering what the direction of forward movement is in relation to the physical orientation of the chip in situ on the flight control board. This image may explain it better. Thanks again.

    http://imgur.com/hqECb3t

  99. I used:
    float unfiltered_gyro_angle_x = gyro_x*dt + get_last_gyro_x_angle();
    float unfiltered_gyro_angle_y = gyro_y*dt + get_last_gyro_y_angle();
    float unfiltered_gyro_angle_z = gyro_z*dt + get_last_gyro_z_angle();
    to rotate 3D object with open gl command. For example pitch:
    //glrotatef(unfiltered_gyro_angle_x,1.0,0.0,0.0);
    glrotatef(unfiltered_gyro_angle_y,0.0,1.0,0.0);
    //glrotatef(unfiltered_gyro_angle_z,0.0,0.0,1.0);
    But the problems is that when the sensor is turned around (right->left), the 3D object is also turned around(right->left) and the value unfiltered_gyro_angle_y increase. But the sensor is turned around(left->right), the 3D object is not turned same way and the value unfiltered_gyro_angle_y still increase slightly. I don’t know why is that

  100. While going through the code I had difficulty in understanding the following function:
    int read_gyro_accel_vals(uint8_t* accel_t_gyro_ptr)

    If you could explain the purpose and algorithm of this function it would be great.

    1. Hi Saumya,
      I didn’t write the part of the code – that was from the original author, however, all that function does is copy the raw accelerometer, gyroscope and temperature data from the FIFO buffer on the MPU6050 chip into a data structure of type accel_t_gyro_union inside the Arduino code. The bytes are copied over in the wrong order (low byte first, high byte second), so the program reverses the bytes for each of the measurements (x,y,z values for accel and gyro, and temp) so that the values may be accessed directly from the data structure.
      Hope that helps,
      Debra

  101. Hi there,
    Thank you so much for sharing. I have tried your sketch and it did work. But I found there is still some serious interference from the Processing’s combination output:
    https://www.youtube.com/watch?v=AJ0PxTs1ejY
    There are some obvious jumps during the movement of the sensor. But what really bothers me is that even at the still position (0:18~ , 1:14~the end of the video clip), the filtered output has some jerky behavior.
    I wonder if there is any suggestion to improve it? Thank you again.

    1. Hi Eugene,
      Your output looks a little more jumpy than mine did, and I’m not sure why that would be. If your only goal is to decrease the jumpiness, you can adjust alpha – the parameter that weights the inputs from the accelerometer and gyroscope into the complementary filter. Decreasing the dependence on the accelerometer might smooth things out a little, however the trade-off of increasing the weight of the gyroscope will be a greater tendency to drift and a greater time lag in your output. If you are just looking to optimize your output, I’d recommend not using the complementary filter, and getting the data directly from the MPU6050 dmp, as discussed in this post: http://www.geekmomprojects.com/mpu-6050-dmp-data-from-i2cdevlib/
      Debra

  102. Hi Robert,
    I’m working on “AIR MOUSE”(final year project).
    I have a MPU6050 gyro/accelerometer/temperature sensor for mouse control. And “how can I make use of the accelerometer data from your code to position mouse cursor on computer”. I want real co-ordinates of mouse on PC from the tilt of the MPU6050 IMU sensor. How to do that? I am using Arduino UNO R3. Can you please help me out in this. Sorry for my bad English.
    All help is appreciated!
    Thanks,

  103. Hi admin,
    I’m working on “AIR MOUSE”(final year project).
    I have a MPU6050 gyro/accelerometer/temperature sensor for mouse control. And “how can I make use of the accelerometer data from your code to position mouse cursor on computer”. I want real co-ordinates of mouse on PC from the tilt of the MPU6050 IMU sensor. How to do that? I am using Arduino UNO R3. Can you please help me out in this. Sorry for my bad English.
    All help is appreciated!
    Thanks

    1. Hi Abishek,
      I’m not sure I totally understand the question, but If I’m understanding you correctly, you want to use MPU6050 measured tilt angles to make a cursor move on the computer screen. The code here (or the DMP code in http://www.geekmomprojects.com/mpu-6050-dmp-data-from-i2cdevlib/) will provide tilt angle coordinates from the MPU6050. To translate those into screen coordinates for the mouse you need to find a way to map yaw, pitch and roll into x,y coordinates. I would probably disregard yaw, and map pitch directly to the on-screen y-coordinate and map roll directly to the on-screen x-coordinate. That seems like the most straightforward way to me.
      Debra

  104. Good day!
    Have you tried to connect to it magnetometer? I am experiencing difficulty with this! If someone had the experience – please write (magnetometer HMC5883L)

  105. i have an error message. pls help!

    Arduino: 1.6.5 (Windows 7), Board: “Arduino/Genuino Uno”

    new_ss_unbugged:17: error: variable or field ‘serialEvent’ declared void
    new_ss_unbugged:17: error: expected ‘)’ before ‘p’
    new_ss_unbugged:12: error: ‘import’ does not name a type
    new_ss_unbugged:14: error: ‘Serial’ does not name a type
    new_ss_unbugged.ino: In function ‘void setup()’:
    new_ss_unbugged:34: error: ‘P3D’ was not declared in this scope
    new_ss_unbugged:34: error: ‘size’ was not declared in this scope
    new_ss_unbugged:35: error: ‘noStroke’ was not declared in this scope
    new_ss_unbugged:36: error: ‘RGB’ was not declared in this scope
    new_ss_unbugged:36: error: ‘colorMode’ was not declared in this scope
    new_ss_unbugged:39: error: ‘class HardwareSerial’ has no member named ‘list’
    new_ss_unbugged:42: error: ‘myPort’ was not declared in this scope
    new_ss_unbugged:42: error: expected type-specifier before ‘Serial’
    new_ss_unbugged:42: error: expected ‘;’ before ‘Serial’
    new_ss_unbugged.ino: In function ‘void draw_rect_rainbow()’:
    new_ss_unbugged:48: error: ‘scale’ was not declared in this scope
    new_ss_unbugged:49: error: ‘QUADS’ was not declared in this scope
    new_ss_unbugged:49: error: ‘beginShape’ was not declared in this scope
    new_ss_unbugged:51: error: ‘fill’ was not declared in this scope
    new_ss_unbugged:51: error: ‘vertex’ was not declared in this scope
    new_ss_unbugged:81: error: ‘endShape’ was not declared in this scope
    new_ss_unbugged.ino: In function ‘void draw_rect(int, int, int)’:
    new_ss_unbugged:87: error: ‘scale’ was not declared in this scope
    new_ss_unbugged:88: error: ‘QUADS’ was not declared in this scope
    new_ss_unbugged:88: error: ‘beginShape’ was not declared in this scope
    new_ss_unbugged:90: error: ‘fill’ was not declared in this scope
    new_ss_unbugged:91: error: ‘vertex’ was not declared in this scope
    new_ss_unbugged:121: error: ‘endShape’ was not declared in this scope
    new_ss_unbugged.ino: In function ‘void draw()’:
    new_ss_unbugged:128: error: ‘background’ was not declared in this scope
    new_ss_unbugged:129: error: ‘lights’ was not declared in this scope
    new_ss_unbugged:136: error: ‘pushMatrix’ was not declared in this scope
    new_ss_unbugged:137: error: ‘width’ was not declared in this scope
    new_ss_unbugged:137: error: ‘height’ was not declared in this scope
    new_ss_unbugged:137: error: ‘translate’ was not declared in this scope
    new_ss_unbugged:138: error: ‘rotateX’ was not declared in this scope
    new_ss_unbugged:139: error: ‘rotateY’ was not declared in this scope
    new_ss_unbugged:142: error: ‘popMatrix’ was not declared in this scope
    new_ss_unbugged:160: error: ‘textSize’ was not declared in this scope
    new_ss_unbugged:161: error: invalid operands of types ‘const char*’ and ‘const char [3]’ to binary ‘operator+’
    new_ss_unbugged:162: error: invalid operands of types ‘const char*’ and ‘const char [3]’ to binary ‘operator+’
    new_ss_unbugged:163: error: invalid operands of types ‘const char*’ and ‘const char [3]’ to binary ‘operator+’
    new_ss_unbugged:166: error: ‘fill’ was not declared in this scope
    new_ss_unbugged:167: error: ‘text’ was not declared in this scope
    new_ss_unbugged.ino: At global scope:
    new_ss_unbugged:180: error: variable or field ‘serialEvent’ declared void
    new_ss_unbugged:180: error: expected ‘)’ before ‘p’
    variable or field ‘serialEvent’ declared void

    This report would have more information with
    “Show verbose output during compilation”
    enabled in File > Preferences.

  106. Hi!

    I would like to know : accelerometer data are in m / s ^ 2 and gyro data are in degrees or radians ?

    Thank you!

  107. Debra,

    I cannot express to you how much I appreciate it. This post is a kind of treasure. Thanks to you, I can fully understand a whole of knowledge. This blog will exist in my favourite site forever.

    Regards,

    Vincent

  108. could you help me
    im beginner, i want use complementary filter for mpu6050, and i want add between lowpass filter for accelero and highpass filter for gyroscope.

    i have trouble with highpass filter for gyroscope, i have get gyro angle and integral values but when put in highpass filter the values wrong. i feel i have mistaken for choose alpha. so could you help me?

    1. Hi,
      I don’t know if I can be of much help. You want to chose a value of alpha that gives more weight to the gyroscope readings, which are accurate in the short term, but allow the input from the accelerometer readings to contribute over longer time scales. Values that I’ve seen used typically are about 0.96 or 0.98. If you are using only gyroscope readings by themselves, they will become inaccurate over time. You need the combination of the accelerometer data and gyroscope data to balance each other out.
      Debra

  109. hi!
    very useful article..
    but i’m having some trouble with the processing sketch…it opens the window but it remains black..i can’t see the rectangles..could you help me?
    do i have to set something in the sketch?

      1. hi!thank for your interest
        the only error i see is “the parameter p is not used” at line 182,but i don’t think this is important
        trying to do some debug, i decommented the acceleration printing line,so on the bottom of the window i can see that the sketch is able to receive the values…but i still obtain only a black window if i run the sketch
        i’ve already checked that my processing version is a 32-bit one and that the baud rate on the serial is the same with arduino

  110. hi! thank you for the article!
    can you help with my project?

    I have a project in arduino that detect movement of a person by 4 MPU-6050, one on each leg and arm.
    I try to detect when a person croch by integrate twice the acceleration on z axis (I use MPU6050_6Axis_MotionApps20.h library with OUTPUT_READABLE_WORLDACCEL).

    the problem is when a person croching (takes less then second) the stop movement create alot of acceleration to the positive z axis, so much movement that the velocity become positive and it look like the person go up.
    this is happen also when person go up, there is so much negative acceleration that is look like the person go down and not stay up. what can i do, and do you have another solution?

    thank you!

  111. Hello!

    I tested this code and it works great! For my application I need to compute the angle for a range of more than -90,90. What I see is that when the imu goes past 90 or -90, it kind of “drifts” back, and never gets a steady 120º angle for example. So, if I flip the IMU, the rectangle doesn’t flip. Is this a problem that can be fixed in the software? and If so, where should I look?

    Thanks millions!

    1. Hi,
      Sorry for the belated response. The algorithm for finding the angle relies on the ATAN function which has a range from -90 to 90 degrees, so it can’t be used directly to compute flipping. For more accuracy, and a greater range, I’d recommend using the data directly from the MPU6040 DMP which can compute angles of greater than 90 degrees directly. See the blog post here for better detail: http://www.geekmomprojects.com/mpu-6050-dmp-data-from-i2cdevlib/
      Debra

  112. Hi
    I had difficulty in running the processing files. When running, it pops up three objects without moving and highlights these particular lines, The value of the local variable ” distance” is not used and the value of the parameter p is not used.

    1. Hi,
      The “errors” you see are warnings about unused variables that I forgot to remove from the code and can be ignored. It sounds like the data is not making it over from the Arduino to the Processing program. Depending upon how your computers USB ports are configured, you may have to change which USB port the Processing sketch is connecting to. I’ve discussed where that is in the code in some of the previous comments. Also check to make sure that the baud rates are set the same for the Arduino sketch and the Processing program so that they can communicate with each other.
      Debra

  113. Hi!
    I had a problem with Processing. I run code with Arduino, it works and shows me what I need. (like this #GYR:13.42,-3.22,-12.17……)
    Then I run code in Processing, three rectangle pops up in new window, but this objects didn’t move when I was moving my gyro.
    I think problems in Processing version or another (that I don’t know). Also I downloaded Processing 3.1.2 ; 3.1.1; 2.2.1 versions with Win 32-bit version. With 3.1.2 and 3.1.1 version one errors occurred about size (size() cannot be used here, see https://processing.org/reference/size_.html). At 2.2.1 version I run the code, then new window pops up with this rect(gyro, acc, combination), I move my gyro and this objects didn’t change.
    Can you help me. Thank you!

  114. Hi,
    I am using GY521 just like yours. for some purpose, i am displaying the raw data in serial monitor. my problem is the values are incrementing even with module flat and stable on table. any idea?
    i want to make quadcopter flight controller through arduino and this same gyro. need help

  115. Hi all.
    Sorry for bad English and thanks for the google translator. :).

    I’m thinking to building a variometer to measure the clibimg or sink rate using the Z-axis accelerometer . The problem is the noise and depending on the angle plate of the Z axis, changes the reading. It is possible to use complementary filter for this purpose?

    Thanks for all.

  116. Hi. i like your post and was a big help for me to further understand more about MPU-6050.
    i also tried your code..but when i tried showing its output from processing all i got was “caught exception”. can you explain what went wrong?? i check if there is data coming from mpu to arduino ide and it seems that it is recieving data from it. so i guess something went wrong in Processing code.

  117. Hello,

    I am not very knowledgeable about all the hardware, but I was just wondering if the gyroscopes and accelerometers are sensitive enough to detect lane changes or turns in a car, if implemented in a phone. Thank you.

  118. I tried several libraries, sketches everything i could. but i cannot get any data of mpu6050. it gives me all zero values. i2caddress scanner gives me address of 0x68 and it also shows MPU connected successfully. but in DMP6 example of library i get following –
    IniþInitializing I2C devices…
    Testing device connections…
    MPU6050 connection successful

    Send any character to begin DMP programming and demo:
    Initializing DMP…

    —— and it is just stuck there

    /////////////////////////////////////////////////////////////////////////////////////////
    for MPU6050_Raw example it gives following –

    Testing device connections…
    MPU6050 connection successful
    Updating internal sensor offsets…
    0 0 0 220 76 -85
    0 0 0 220 76 -85
    a/g: 0 0 0 0 0 0
    a/g: 0 0 0 0 0 0
    a/g: 0 0 0 0 0 0
    a/g: 0 0 0 0 0 0
    a/g: 0 0 0 0 0 0
    a/g: 0 0 0 0 0 0

    All other sketches either give zero values to all or gets stuck with DMP initialization.
    can you please help … what is going wrong.

    1. Electromania, perhaps try setting the power management register to 0. When powered on, the MPU-6050 is in sleep mode and only responds to I2C requests to set the power management register and reading the WHOAMI register.

  119. Hi there!
    Appreciate your efforts with this project. My question is that if I use raw values from the sensor. Then what would be the conversion factor from Raw value to Acceleration in m/s2 ?? Will it be (Raw_value)*9.8/16384? Or just (Raw_value)/16384? …. for a sensitivity of +/-2g.
    Thankyou

  120. We love you Geekmom!
    Dont know if anybody mentioned this before but it seems possible to run the processing sketch in 64b now.
    I had to adapt the portindex to 0 in my case, other than that it worked just fine for me.
    Kind regards,

    Wim

  121. hello.i want to know can i use your mpu project for creating a wireless mouse? can a mpu6050 detect a motion on the ground ?thank u.

  122. hey great science
    I m planning to make a wind eddie detector…
    I thought your filtered code is exactly what I need , but the only thing I m not sure if the sampling rate is fast enough to capture fast 360 when eddies hit the sensor of if I m gona be able to decode which direction it spins around…
    could I try a faster sampling rate? without any effects on the rest of the sketch?…
    any other sugestions maybe?
    thaaaanx a lot

  123. Hi and thank you,

    I ran the visualization successfully.

    You mentioned that it would have been much easier and more accurate to use one of the pre-written libraries instead

    I tried using the MPU6050 library by Rowberg that seems very popular but despite several attempts could not get it to recognize the MPU6050 module when connected (correctly) to my Arduino Uno R3.

    Have you been successful using this library and do you know of any other libraries that you have managed to get to work?

    Chris

    1. Hi Chris,
      I haven’t done anything with the MPU6050 for a number of years, but I was able to use the library, and in fact I wrote several more blog posts about the results of doing so. If you search for articles on my site with MPU6050, you should find them.
      Best,
      Debra

  124. Hello Debra, I am having problem running your processing file. On Arduino IDE, it runs smooth on the nano that i am using but on Processing, first, it showed the three boxes with but nothing changed when the GY521 was moved. Afterwards, it has started showing following error:

    ArrayIndexOutOfBoundsException: 1 on line 39 i.e. String portName = Serial.list()[portIndex];

    Can you please tell me what is the reason and how can i fix it? It would be really helpful.
    Thank You.

    1. Yes, it’s not finding the correct serial port to getthe data through. Serial.list() returns a list of all the serial ports on your device. portIndex was the index of the particular serial port that works on my computer. Try lowering the value of portIndex until it works.

  125. Hello,
    firstn thank you for this great job
    I ‘ve a proble with GY_521_send_serial
    This code gives the orientation but it drift by the time
    it drift rapidely , Is the problem caused by the gyro drift?
    how can I fix this problem in order to get zéro (0) when the sensor is in no-moving situation
    thank u again

      1. Thank you for your reply,
        Can you give me the link to this post, please ?
        Then , i have another question, how can I read mpu6050 data directly in Matlab usign arduino ?

Leave a Reply

Your email address will not be published. Required fields are marked *