The GY-521 module is a breakout board for the MPU-6050 MEMS (Microelectromechanical systems) that features a 3-axis gyroscope, a 3-axis accelerometer, a digital motion processor (DMP), and a temperature sensor. The digital motion processor can be used to process complex algorithms directly on the board. Usually, the DMP processes algorithms that turn the raw values from the sensors into stable position data. This tutorial gives only a brief introduction to the GY-521/MPU-6050. In particular, it is shown how to retrieve the raw sensor values. The sensor values are retrieved by using the I2C serial data bus, which requires only two wires (SCL and SDA). If you plan to use the full range of features or require reliable and stable position data, then I recommend to have also a look at ready-to-use libraries. Please follow this link to find an excellent library with many examples: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050.
List of materials:
GY-521 Pin Layout
The GY-521 breakout has eight pins:
- VCC (The breakout board has a voltage regulator. Therefore, you can connect the board to 3.3V and 5V sources.)
- GND
- SCL (Serial Clock Line of the I2C protocol.)
- SDA (Serial Data Line of the I2C protocol.)
- XDA (Auxiliary data => I2C master serial data for connecting the module to external sensors.)
- XCL (Auxiliary clock => I2C master serial clock for connecting the module to external sensors.)
- AD0 (If this pin is LOW, the I2C address of the board will be 0x68. Otherwise, if the pin is HIGH, the address will be 0x69.)
- INT (Interrupt digital output)
Wiring layout of GY-521 Example
In this tutorial we will make use only of the first four pins: VCC, GND, SDA, and SCL. First, we connect the module’s VCC to the Arduino’s 5V pin. Then, the module’s GND is connected to one of the Arduino’s GND pins.
Next, we have to set up the I2C connection between the module and the Arduino. Most Arduino Uno variants have an SCL and SDA pin. If you have such an Arduino Uno, just connect SCL to SCL and SDA to SDA.
If you can’t find an SCL and SDA pin on your Arduino, you have to use other pins. Unfortunately, you cannot use just any pin. For each type of Arduino, SCL and SDA are tied to different pins:
- Arduino Uno, Arduino Ethernet, Arduino Nano: A4 (SDA), A5 (SCL)
- Arduino Mega2560: 20 (SDA), 21 (SCL)
- Arduino Leonardo: 2 (SDA), 3 (SCL)
- Arduino Due: 20 (SDA), 21 (SCL)
So, if you have an Arduino Uno without SCL and SDL pins, then connect the Arduino’s A4 pin to the module’s SDA pin. Next, connect the Arduino’s A5 pin to the module’s SCL pin.
Source code of GY-521 Example
We make use of the Arduino platform’s in-built library (Wire) to establish an I2C connection between the Arduino Uno and the GY-521 sensor. At the beginning of our source code, the Wire library’s header file is included. Next, we define and declare some variables.
Then, a convert-function is defined. The convert-function makes sure that all sensor values have the same width when they are printed out to the serial monitor later.
In the setup function, a serial connection is established. Moreover, we start our first I2C transmission to the GY-521 board to wake it up from sleep mode.
In the loop function, seven sensor values (3x accelerometer, 1x temperature, and 3x gyro) are requested from the GY-521 module. The MPU-6050 has many registers which can be read. Fourteen of these registers contain the sensor values that we need. As a first step, we tell the GY-521 module where we are going to start reading (“Wire.write(0x3B);”). Then, we request to read 14 registers (“Wire.requestFrom(MPU_ADDR, 7*2, true);”). If you are wondering, why 14 registers are read instead of 7 registers, the reason is quite simple: Each sensor value has a size of 2 byte. As each register has a size of one byte, a single sensor value must be retrieved by accessing two registers. The first register contains the so-called “high byte” and the second register contains the “low byte”. Next, all values are retrieved and printed out to the serial connection. At the end of the loop function, a delay of one second is added in order to avoid flooding the serial monitor with messages.
// (c) Michael Schoeffler 2017, http://www.mschoeffler.de #include "Wire.h" // This library allows you to communicate with I2C devices. const int MPU_ADDR = 0x68; // I2C address of the MPU-6050. If AD0 pin is set to HIGH, the I2C address will be 0x69. int16_t accelerometer_x, accelerometer_y, accelerometer_z; // variables for accelerometer raw data int16_t gyro_x, gyro_y, gyro_z; // variables for gyro raw data int16_t temperature; // variables for temperature data char tmp_str[7]; // temporary variable used in convert function char* convert_int16_to_str(int16_t i) { // converts int16 to string. Moreover, resulting strings will have the same length in the debug monitor. sprintf(tmp_str, "%6d", i); return tmp_str; } void setup() { Serial.begin(9600); Wire.begin(); Wire.beginTransmission(MPU_ADDR); // Begins a transmission to the I2C slave (GY-521 board) Wire.write(0x6B); // PWR_MGMT_1 register Wire.write(0); // set to zero (wakes up the MPU-6050) Wire.endTransmission(true); } void loop() { Wire.beginTransmission(MPU_ADDR); Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) [MPU-6000 and MPU-6050 Register Map and Descriptions Revision 4.2, p.40] Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. As a result, the connection is kept active. Wire.requestFrom(MPU_ADDR, 7*2, true); // request a total of 7*2=14 registers // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable accelerometer_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L) accelerometer_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L) accelerometer_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L) temperature = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L) gyro_x = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L) gyro_y = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L) gyro_z = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L) // print out data Serial.print("aX = "); Serial.print(convert_int16_to_str(accelerometer_x)); Serial.print(" | aY = "); Serial.print(convert_int16_to_str(accelerometer_y)); Serial.print(" | aZ = "); Serial.print(convert_int16_to_str(accelerometer_z)); // the following equation was taken from the documentation [MPU-6000/MPU-6050 Register Map and Description, p.30] Serial.print(" | tmp = "); Serial.print(temperature/340.00+36.53); Serial.print(" | gX = "); Serial.print(convert_int16_to_str(gyro_x)); Serial.print(" | gY = "); Serial.print(convert_int16_to_str(gyro_y)); Serial.print(" | gZ = "); Serial.print(convert_int16_to_str(gyro_z)); Serial.println(); // delay delay(1000); }
If the code is compiled and transferred to the Arduino Uno, you should see the sensor values in the serial monitor of the Arduino IDE. Moreover, when the GY-521 board is rotated or moved, the sensor values should change according to the movement.
As mentioned before, this is basically a “hello world program” for the GY-521. if you plan to use the board more seriously, I highly recommend to dig deeper into the possibilities of the MPU-6050 MEMS.
Hi – Thank you for this tutorial. Could you give me your recommended method for getting the accelerometer to talk to music software on a MAC so that it will control patches through gesture. I use Ableton Live with MAX for Live . Will in talk to the software via midi and OSC – using a bridge such as Osculator or similar ? Thanks
Hi Tony, that’s a tough one ;) What about using an Arduino in-between the accelerometer and the MAC? I’ve seen some projects in which an Arduino is used as MIDI device (e.g., this might be a good start => https://www.arduino.cc/en/Reference/MIDIUSB). In the end, the setup would look like this: GY-521 <= I2C => Arduino <= MIDI => MAC/Ableton.
[…] a previous blog post, I wrote a short tutorial about the GY-521 module (MPU-6050 breakout board). In addition to the […]
Nicely explained! everything is clear.. Gonna try it!
just beginning with this!!
Thanks in advance.
how can i make its model instead of showing values the monitor will show its position like left right or flat
Please how do I determine the angle of the three axis of gyro as fall and Normal movement?
Hi.I tested the code but i got 0 as values and 36.53 for temperature
HELLO
I HAVE TOO TESTED AND I GOT THEVALUES AS -1 AND TEMP AS 36.53
WHY ?
ARGH ME TOO!
Very Helpful Tutorial Thank you
Hi Michael,
Thanks for our demo code for I2C transmission, however, if I modified your delay into lets say 10ms, the serial monitor port stop refreshing. I guess it’s like what you said a “flooding the serial monitor with messages”. How to avoid that, and what’s the cause of that.
Best Regards!
you need to put the delay(1000) in end of program
After uploading the code, no terminal is opening where i can see the output? How to resolve this?
Look at the top-right corner of the sketch, there is an icon for “Serial Monitor”. Click on that.
Hallo Michael, I would use the GY-521 to build a simply shoot training sistem: one point on the screen (using Processing software) that moves in all directions using the GY-521 installed under a gun and the data X,Y,Z read from board. Do you think is it possibile ? How ?
Thanks for your reply
Hallo Michael,
Ich habe das Programm mal abgeschrieben und in zwei Arduino geladen.
( meine Programmierkenntnisse sind eher mangelhaft)
An den Arduino ( chin. Nano / chin. ProMini ) sind jeweils ein MPU6050 (GY521)
angedockt.
Der Nano werkelt einwandfrei, Daten kommen am Serial-monitor an, und ändern sich bei bewegung.
Der ProMini zeigt auf allen Achsen nur -1 und sonst macht er….. nichts?
– beschaltung beide Arduino ist gleich, GND, Vcc, INT, scl,sda
Wo beginnt die Fehlersuche?
Mfg Corian
Hello
Can you please tell me what algorithm is responsible for the interfacing of IMU sensor with Arduino.
I have used MPU 6050 with Arduino for fault detection; I am searching for the relevant algorithm to validate my experimentation of detecting fault by connecting multiple sensors with Arduino and recording result.
I have used Arduino interfaced with MPU6050 for fault detection. (Introduced fault and recorded the results). I want some help in identifying the algorithm for this fault detection for validation purpose.
Have you used any algorithm (on which you based your fault detection methodology)?
Hello, thank you for your tutorial. I followed the instructions in the video and on this page, but when I run the application and view the monitor the values do not change.
aX = -1 | aY = -1 | aZ = -1 | tmp = 36.53 | gX = -1 | gY = -1 | gZ = -1
Any idea what could be wrong? Ive triple checked the connections, not sure what else could be the issue.
Thanks!
change the address of the MPU6050 from 0x68 to 0x69, or the other way around to fix this.
With either 0x68 or 0x69 setting I get same
aX = -1 | aY = -1 | aZ = -1 | tmp = 36.53 | gX = -1 | gY = -1 | gZ = -1
the current doesn’t arrive to the module. Is the led on ?
I have the same exact problem, the light is on and I’m using a MU6050 SEN-11028, idk if that’s different from GY-521 though.
Hey Michael,
Experiencing the same issue with -1 values at all variables with the exact same 36.53 temp. I’ve been trying to troubleshoot for a while now (including attempting to calibrate the GY521). Was wondering if you had any insight?
I have the same issue, using the gy521 with nodeMCU esp8266
Hi, thank you for this tutorial!
I have a question and I hope you have the answer,
I have to use this sensor for a project and I was wondering myself what is the unit of the figures given by arduino,
I guess that the temperature is in Celsius but what about the gyro and the accelerometer? Are they hexadecimals value?
Thanks in advance
Hi,
I would like to measure distance. I will press button first time and then move it and press button second time and than it would measure made distance betwen these two points. Is it posible to made this and how? Thanks
GY-521/MPU6050 measures rotational movements. I guess what you need is something that is able to measure translational movements (e.g. ultrasonic, GPS, camera-based,…)
equations of motion
x = x0 + v0*Ax + 0.5*Ax*t^2
x0 initial location
v0 initial velocity (normally 0)
Ax is acceleration in x dimension.
x=x0+v0*t+0.5*Ax*t^2
I really thank you for your help. you made my day. now i can complete my project with your help. it was one of the best videos on earth because it was so clear.
This expression: “accelerometer_x = Wire.read()<<8 | Wire.read();" (and all other similar in the code sample above) is not well-formed because you cannot assume the first read() occurs before the second. Remember, in C(++) the expression terms can be evaluated in any order (the only exceptions are the logical ||, && and the ternary ?:), and the order can change between the versions of the same compiler, as well as depending on whether or not the compilation is optimized (even for the same version of the compiler!). As a result, there's no guarantee in the above expression that the bytes will be placed in the right order into the accelerometer_x variable. A well-formed program would use a series of sequential assignments, something like that:
accelerometer_x = Wire.read();
accelerometer_x <<= 8;
accelerometer_x |=Wire.read();
(the first two can be combined into one "Wire.read() << 8", but IMO three-statement looks more clear and uniform).
Many thanks for this. i am capable of having done similar myself but your code has saved me a lot of time.
I am impressed that you did this without a bunch of 3rd party libraries. having found your site I shall view your other projects with good expectations.
Hi can this be used to also measure from 3 MPU6050 sensors? Another question, where can you set if the sensors will measure in +-2g or +-4g and+-8g?
Regarding your first question: Two sensors should work smoothly since you are able to change the SPI address with the A0 input (0x68/0x69). To be honest, I don’t have the perfect solution for a third sensor in mind right now. I would start by looking into how to change the third sensor to another address (which is not 0x68 or 0x69).
How do you change the scale of the accelerometer reading in the code? It seems to be stuck on the +/-2g setting despite the datasheet saying it can be adjusted
I know I’m super late on this, and I’m a beginner (so leaving it to better knowledged people to check my work), but I’m sure someone in my position might need this now.
I found a function in the Arduino examples that sets the scale found here: https://www.hotmcu.com/gy521-mpu6050-3axis-acceleration-gyroscope-6dof-module-p-83.html
void MPU6050::setFullScaleAccelRange(uint8_t range) {
I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG, MPU6050_ACONFIG_AFS_SEL_BIT, MPU6050_ACONFIG_AFS_SEL_LENGTH, range);
where:
#define MPU6050_RA_ACCEL_CONFIG 0x1C
#define MPU6050_ACONFIG_AFS_SEL_LENGTH 2
#define MPU6050_ACONFIG_AFS_SEL_BIT 4
Putting this in the setup loop might work? Perhaps something like…
Wire.beginTransmission(0x68); //Address of Device
Wire.write(0x1C); //Accel Config Register
/*
#define MPU6050_ACCEL_FS_2 0x00
#define MPU6050_ACCEL_FS_4 0x01
#define MPU6050_ACCEL_FS_8 0x02
#define MPU6050_ACCEL_FS_16 0x03
*/
Wire.write(0x01); // for ± 4g
Wire.endTransmission();
Hello, could please share the code with led included at end of you video please.
Regards
Here you go: https://www.mschoeffler.de/2017/12/09/example-application-gy-521-module-mpu-6050-breakout-board-and-arduino-uno/
Can I have the code for that four LED that you showed in video
Due to the many requests I received, I made a separate blog article about the example –> https://www.mschoeffler.de/2017/12/09/example-application-gy-521-module-mpu-6050-breakout-board-and-arduino-uno/
Hi, I want to use the MPU9250 in combination with Arduino nano. Does this setting change something in the code?
Imho you can use the same code for the Arduino Nano. In case you run into any problems, my first look would be at the pin configuration for I2C.
hi!
what is the benefit of using the i2cdevlib?
Hello,
I have the GY-521 Hiletgo Gyro/Acc hooked up to the Raspberry Pi.
I am not getting Accelerometer data at all. Do you have any idea what could be wrong ?
Great thanks. It worked first time. It’s my first board to connect and get running on Arduino and Its great that I get some output. Any recommendations for using the other features on board would be appreciated.
I’ll take a look at the manual and see what I can do next.
The English language manual is not yet released, not so good!
[…] If you started with a basic kit and are asking for more now, or want to start more ambitious direct from the beginning, I recommend to just go for more sensors and actuators. In many cases, it is not possible to wire a sensor directly to an Arduino since additional hardware is required. Luckily, there exist tons of breakout boards which contain the sensor/actuator and the required hardware components as well. Often, breakout boards are also referred to as “name of sensor/actuator”-module, especially when searching them up on online shops. There are a lot of breakout boards available that can directly wired to an Arduino. If you look up my tutorials you can find many of them: For example, KMR-1.8 SPI (TFT Display), RDM630/RDM6300 (RFID Reader), GY-521/MPU-6050 (gyroscope+accelerometer). […]
hi, do you have any recommendations on how I can use these valued to detect when an accident has occurred ?
A thought: high standard deviation within a specific time-frame (e.g. 5sec) might indicate that an accident has occurred.
Hi Michael
Thanks for an awesome tutorial. Would you have any idea on how to communicate with multiple MPU6050 with a single Arduino?
I am a masters student at a local university and would like some assistance if you can help me.
Some thoughts:
– The second MPU need another address (you can change the address with pin A0)
–> const int MPU_ADDR = 0x68; // I2C address of the MPU-6050. If AD0 pin is set to HIGH, the I2C address will be 0x69.
– You need to start two transmissions, where the second transmission has another address
–> Wire.beginTransmission(MPU_ADDR);
Could you please provide code to write this data to an SD card. It works great on the serial monitor but there is not much I can do with that. I apologize if this is an amateur question but I am! Thank you for all your time.
Some thoughts:
– You can combine it with code that I wrote in another tutorial -> https://www.mschoeffler.de/2017/02/22/how-to-use-the-microsd-card-adapter-with-the-arduino-uno/
– Another example on writing on SD cards
Very nice tutorial and well worded I was thinking on integrating this into project of mine. For the sample code I was wondering what type of license are you using? Is the license MIT? or other type of copyright license. Also, thanks for the tutorial.
Adding a license text to all my examples is on my bucket list for 2020 –> probably MIT.
Hi Michael,
Great tutorial! Do you know if it is possible to add two accelerometers to one Arduino and compare the accelerations? If yes, how would you do it?
Kind regards
Troels
Yes that should be possible. Some thoughts:
– Second accelerometer must have a different address (see MPU_ADDR, AD0 pin)
– You have to start two transmissions –> Wire.beginTransmission(MPU_ADDR); One transmission goes to the first accelerometer, and the other one to the second accelerometer.
Will all this fit into an ATtiny85 or 13?
How do we write the registers to measure 4g, 8g or 16g?
Hello, I tried using your code however it prints this out over and over no matter the orientation:
aX = -1 | aY = -1 | aZ = -1 | tmp = 36.53 | gX = -1 | gY = -1 | gZ = -1
Could you please help me out?
i have this same problem
did you mange to get it Peter B?
I added the following
#define SDA1 4
#define SCL1 15
#define SDA2 21
#define SCL2 22
TwoWire I2Ctwo = TwoWire(1);
void setup(){
…
….
I2Ctwo.begin(SDA2,SCL2,400000); // SDA2 pin 17, SCL2 pin 16
}
Did it work for u bro? that extra code
where do you define TwoWire?
my problem was a faulty arduino nano and a faulty connection
Very nice tutorial?. But what is the unit of the values that are returned??
Exciting article. Thanks for sharing it.
Hello! Thank you for the tutorial – really helped with setting up!
I too am having the same problem where my code is producing a print of :
aX = -1 | aY = -1 | aZ = -1 | tmp = 36.53 | gX = -1 | gY = -1 | gZ = -1
Does anyone have any idea what is causing the problem? Thank you!
hi , i am also having this same problem , does anyone have a solution??
Maybe u don’t have a good conection (this was my problesm )
I had the same results. I solder it and now it’s working
I got the same problem after running this code :
aX = -1 | aY = -1 | aZ = -1 | tmp = 36.53 | gX = -1 | gY = -1 | gZ = -1
the connection and WhoAmI returns correct.
did you find a solution to this problem? because i’m facing the same thing
Hi,
thank you for the project. I’ve tried, I’ve checked the program and the wiring but it doesn’t work.
Could you help me please?
Tanks
Hello,
I’ve solved the problem (aX = -1 | aY = -1 | aZ = -1 | tmp = 36.53 | gX = -1 | gY = -1 | gZ = -1)
I solder it ( the mpu and the )
So I spouse that you guys didn’t have a good connection (how I solve it).
Thanks and see u
thank you , you are the best
Thank you so much, Michael, for sharing this very useful explantation and code !
Have great Holidays.
Hi, I have no problem with this at all except that you do not have a circuit diagram. I would be very much so happy that you include circuit diagrams with all of your future projects
Hi, very well described tutoria, but I use a module HW-662, that it is said is similar to MPU6050.
If I compile in a Wemos Mini all results are fixed except temp that is 36.53.
With Arduino Uno I don’t get any result.
Can you help me? Thanks
Thanks for the helpful article. I’d like to point out one aspect of the code that could cause problems with some compilers.
In the expression Wire.read()<<8 | Wire.read() there's no guarantee that the left side of the bitwise or will be executed first. Putting the calls to Wire.read() on separate lines would eliminate the possibility of the bytes being stored out of order.
Hi, found this really helpful, thank you. However, I am currently having the problem where the code is uploaded to the Arduino Uno and it wakes up the IMU, but I’m not getting any data on the serial monitor. Just wondering if anyone else had the same issue, or if it is faulty connection on my devices.
Thanks
Yeah same here,
I have loaded many varations of MPU6050 code to check I2C location (results = 0x68) and a few that set the PWR_MGMT, both 1 and 2 to 0 (I even added to the code to set it to 1 and then on the next line to 0 again, sorta like flicking a light switch). I do error checking and all errors=0.
No matter what code I use, the results are always the same, there is no sensor data. I tried all 5 that I order and same no-data results.
The last thing I tried is reading the registry directly without any calculations and the results were all 0s, so can the sensors be stuck.
If I need to use an oscillascope, is there a tutorial on this, maybe a video tutorial to help me with this?
This is great! Everything works and is easy to understand. But the GY-521 has other pins not used, what do they do? And how would you use it?
what is the difference between ITG mpu & GY521 MPU6050
HOW CAN I USE THE GY-521 ON ITS OWN WITHOUT THE ARDUINO, IS IT POSSIBLE?
REGARDS
DIRK
Awesome job – really appreciate the comments in the code to explain what they reflect.
Best GY-521 example out there.
Thank you for the really clear tutorial.
I am very happy with what you did. I used the code to see if my MPU6050 still works, because I ordered it online and it came with a missing capacitor. I’ve replaced it and it works. thank you for the code. I will look deeper into it, because I need to know how this works.
Hi Michael,
Thank you for your outstanding Arduino Tutoria. I particularly appreciated the ones on gy521 module and HX711 Load Cell Amplifier.
I also noticed that the one on Micro SD card adapter (https://mschoeffler.com/2017/02/22/how-to-use-the-microsd-card-adapter-with-the-arduino-uno/) does not work and gives the following message “There has been a critical error on this website.”. It will be nice if you could fix this problem.
Thanks again for your help.
My data for the sensor won’t print. The code is exactky the same.
Excellent tutorial. Thanks for breaking it down as you did! This will help tremendously for a project I am working on!