Interface MPU6050 Accelerometer and Gyroscope Sensor with Arduino

When it comes to sensing motion, both the accelerometer and the gyroscope are impressive on their own. An accelerometer measures linear acceleration, which means it can detect when you’re walking forward, jumping, or even falling. A gyroscope, on the other hand, measures angular velocity, which means it detects when you’re turning or twisting.

Each sensor is useful on its own, but when you combine them together, you get incredibly precise data about an object’s position and orientation in 3D space. This is exactly where the MPU6050 comes in.

The MPU6050 is a small but powerful module that packs both a gyroscope and an accelerometer into one chip. This combination allows it to measure rotation along all three axes (X, Y, and Z), static acceleration caused by gravity, and dynamic acceleration caused by motion, impacts, or vibrations.

In this tutorial, you’ll learn everything you need to know about the MPU6050. We’ll cover how the sensor works, walk through the wiring to connect it to an Arduino, write code to read the sensor data, and even display that data visually using the Serial Plotter.

Before we jump straight into the hardware, though, let’s quickly cover the basics of how accelerometers and gyroscopes work. If you’re already familiar with these concepts, feel free to skip ahead to the Hardware Overview section.

How Does an Accelerometer Work?

To understand how accelerometers work, imagine a small, transparent cube with a ball suspended in its center by springs connected to each inner wall — front, back, left, right, top, and bottom.

Accelerometer Working Illustration Ball Inside Cube

When the cube isn’t moving, the ball stays perfectly centered. But as soon as the cube moves or accelerates in any direction, the ball lags slightly behind due to inertia (the tendency of objects to resist changes in motion). This lag stretches some springs more than others, and by measuring how much tension is in each spring, you can figure out the direction and strength of the force being applied.

Accelerometers often express the strength of this force in terms of g-force — like 1g, 2g, or 3g. So before we go further, let’s talk about what exactly “1g” means.

When we say “1g,” we’re referring to the acceleration due to gravity on Earth’s surface — about 9.8 m/s². Even when your phone is just sitting still on a table, it still senses a force of 1g pulling straight down due to gravity. It’s important to know that accelerometers don’t distinguish between gravitational acceleration and acceleration from actual movement — they simply detect the total acceleration in all directions.

Going back to our example, imagine the cube floating in outer space, in zero gravity. The ball would just float motionless in the center. Since there’s no gravity or motion, the springs wouldn’t stretch, and the accelerometer would register 0g on all three axes — X, Y, and Z.

Accelerometer Working Illustration Weightless State

Now, if you suddenly moved the cube quickly to the left, the ball would lag behind and push against the right-side spring. The accelerometer would then sense a force to the right, which means the box is accelerating to the left. In this case, you’d see 1g of acceleration on the X-axis, even though there’s still no gravity — it’s purely from motion.

Accelerometer Working Illustration Sudden Movement

Let’s see what happens when we place that cube on Earth. If you place the cube on a table and leave it there, gravity pulls the ball downward. There’s no motion, but the force of gravity alone causes the sensor to read 1g on the Z-axis. The X and Y axes would still read 0g, because there’s no force acting in those directions.

Accelerometer Working Illustration Gravitation Force

Things get interesting when you tilt the box. Imagine tilting it so it’s leaning at a 45-degree between the Z-axis and the X-axis. Gravity still pulls straight down toward Earth, but because the cube is tilted, that pull is now divided between the Z and X directions. The accelerometer senses this and shows about 0.71g on both axes. The value of 0.71 isn’t random; it’s the cosine of 45 degrees times 1g. The ball is effectively pulling equally on two springs now, so both the X and Z sensors register force.

Accelerometer Working Illustration Tilted Cube

While this box-and-ball model isn’t exactly how real accelerometers are built, it helps us understand why accelerometers measure forces in g’s, why they read 1g in the Z direction when sitting still, and what readings you might see when the device is held at different angles.

In the real world, accelerometers are built using Micro-Electro-Mechanical Systems (MEMS) technology. So, let’s explore how a MEMS accelerometer works.

How Does a MEMS Accelerometer Work?

A MEMS (Micro-Electro-Mechanical System) accelerometer is essentially a microscopic mechanical system fabricated directly onto a silicon chip.

At its core is a small mass, often called the “proof mass.” This mass is suspended between fixed plates by flexible beams or springs. Both the proof mass and the fixed plates are designed to work together as parts of a capacitor.

MEMS Accelerometer Working
Accelerometer Animation Labels

When the accelerometer moves or experiences acceleration in a certain direction, the proof mass tries to stay in place because of inertia, while the rest of the device moves around it. This movement changes the distance between the proof mass and the fixed plates. Since capacitance depends directly on the distance between plates, the value of the capacitance changes accordingly.

On-chip circuitry detects this change in capacitance and converts it into an electrical signal. The circuitry then calculates exactly how much acceleration has occurred based on the change.

How Does a Gyroscope Work?

While accelerometers measure linear acceleration, gyroscopes measure angular rotation. They do this by detecting a special force known as the Coriolis effect.

Coriolis Effect

The Coriolis Effect describes what happens when something is moving and you try to rotate it at the same time. Imagine you’re on a merry-go-round throwing a ball to your friend. Even though you threw it straight, the ball curves because the merry-go-round is spinning underneath it. That curving force is the “Coriolis Effect”.

In technical terms, when a mass (m) moves in one direction with a certain speed (v), and you rotate the whole system at an angular rate (Ω, shown by the red arrow), the Coriolis Effect creates a force (yellow arrow) that pushes the mass sideways, perpendicular to its original path. The stronger the rotation, the stronger this sideways push.

Coriolis Force On a Mass

In a gyroscope, tiny masses vibrate back and forth in opposite directions at a constant speed. When you rotate this system, the Coriolis Effect pushes each mass in opposite directions. This alters the electrical properties (like capacitance) between them. By measuring these changes, the gyroscope figures out the angular rotation speed.

Coriolis Force On Two Masses

How Does a MEMS Gyroscope Work?

A MEMS gyroscope is a tiny sensor that uses this same principle. Inside, there’s a central part called the “proof mass” made up of four parts (M1, M2, M3, and M4). These parts are kept in a constantly oscillating movement so that they react to the Coriolis effect when you rotate the device. They move inward and outward simultaneously at a certain frequency in the horizontal plane.

MPU6050 Accel Gyro Working Drive Mode Output

When you rotate the device, the Coriolis force acts on these moving masses and changes their vibration from horizontal to vertical.

There are three modes depending on the axis along which the angular rotation is applied.

Roll Mode:

When an angular rotation is applied along the X-axis, M1 and M3 will move up and down out of the plane due to the Coriolis effect.

MPU6050 Accel Gyro Working Roll Mode Output

Pitch Mode:

When an angular rotation is applied along the Y-axis, M2 and M4 will move up and down out of the plane.

MPU6050 Accel Gyro Working Pitch Mode Output

Yaw Mode:

When an angular rotation is applied along the Z-axis, M2 and M4 will move horizontally in opposite directions.

MPU6050 Accel Gyro Working Yaw Mode Output

In each mode, whenever the Coriolis Effect occurs, the continuous motion of the proof masses creates a measurable change in capacitance (∆C). The sensing components inside the gyroscope detect this capacitance change and convert it into an electrical voltage signal. This signal tells your device exactly how much and in what direction it’s rotating.

For reference, here’s what the actual MEMS structure of a 3-axis digital gyroscope looks like under a microscope. Thanks to Adam McCombs for sharing this image of a decapped L3GD20HTR MEMS gyroscope.

Decaped L3GD20HTR MEMS Gyroscope

MPU6050 Module Hardware Overview

At the heart of the module is a low-power, low-cost 6-axis MotionTracking chip called the MPU6050. It combines a 3-axis gyroscope (for measuring rotation), a 3-axis accelerometer (for measuring acceleration), and a Digital Motion Processor (DMP) all in one tiny 4mm by 4mm package.

The module can detect rotation around all three axes and can measure both static acceleration from gravity and dynamic acceleration from motion, shock, or vibration.

MPU6050 Module Hardware Overview

The module comes with a built-in LD3985 voltage regulator, so you can safely connect it to 5V microcontrollers like an Arduino without worrying about damaging the sensor.

One of the best features of the MPU6050 is its low power consumption. During active measurements, it uses less than 3.6mA of current, and when it’s not doing anything (idle mode), it uses only 5μA. This makes it perfect for battery-powered devices like wearables or robots.

Plus, it has a power LED that lights up to show when the module is turned on.

Measuring Acceleration

The MPU6050 can measure acceleration over four programmable full scale ranges of ±2g, ±4g, ±8g, and ±16g. Lower ranges like ±2g give you more precise measurements for small movements, while higher ranges like ±16g let you measure more intense forces.

MPU6050 Module Accelerometer Axis

The MPU6050 has three dedicated 16-bit analog-to-digital converters to measure acceleration along the X, Y, and Z axes simultaneously.

Measuring Rotation

The MPU6050 can measure angular rotation over four programmable full-scale ranges: ±250°/s, ±500°/s, ±1000°/s, and ±2000°/s.

MPU6050 Module Gyroscope Axis

The chip also has three additional 16-bit converters to sample rotation along all three axes at the same time. You can adjust how often the sensor takes measurements—anywhere from 3.9 samples per second to an impressive 8000 samples per second.

Measuring Temperature

The MPU6050 includes a temperature sensor that can measure temperatures from –40°C to 85°C with an accuracy of about ±1°C.

Keep in mind that this temperature sensor measures the temperature of the silicon chip itself, not the ambient temperature. Because the chip’s temperature affects the accuracy of its readings, the MPU6050 uses this information to automatically adjust its calculations and maintain accuracy.

The I2C Interface

The MPU6050 communicates with the Arduino via the I2C interface. It can use one of two different I2C addresses: 0x68 and 0x69. This is helpful if you want to connect two MPU6050 modules on the same I2C bus, or if another sensor is already using one of those addresses.

MPU6050 Module I2C Address Selection Pin

The ADO pin on the module determines which I2C address is used. Pulling this pin LOW sets the address to 0x68, and pulling it HIGH sets it to 0x69. However, because the pin is already connected to ground through an onboard 4.7 kΩ pulldown resistor, leaving it unconnected defaults the address to 0x68. If you want to switch to 0x69, simply pull the ADO pin HIGH.

Auxiliary I2C Interface

The MPU6050 has an auxiliary I2C bus for connecting additional sensors directly to the MPU6050 module. You access this auxiliary bus through two pins labeled XDA and XCL.

MPU6050 Module External I2C Pins

This is often used to add a magnetometer, which measures magnetic fields along three axes. The MPU6050 by itself provides 6 Degrees of Freedom (DOF)—three from the accelerometer and three from the gyroscope. When you add a magnetometer, this increases to 9 DOF, giving your project much more detailed information about its position and orientation in space.

Technical Specifications

Here are the specifications:

Operating Voltage5V (typical)
Accelerometer Range±2g, ±4g, ±8g, ±16g
Gyroscope Range±250°/s, ±500°/s, ±1000°/s, ±2000°/s
Temperature Range-40 to +85°C
Absolute Maximum AccelerationUp to 10,000g

For more information, please refer to the datasheet below.

MPU6050 Module Pinout

The MPU6050 module has eight pins. Here’s what each one does:

MPU6050 3 axis Accelerometer Gyroscope Module Pinout

VCC is the power supply pin. Connect it to the 5V pin on the Arduino.

GND is the ground pin. Connect it to the Arduino’s GND.

SCL is the serial clock pin used for the I2C interface.

SDA is the serial data pin for the I2C interface.

XDA is the serial data pin for an auxiliary I2C interface. You can use it to connect additional sensors, like a magnetometer, directly to the MPU6050.

XCL is the serial clock pin used for an auxiliary I2C interface. It works with XDA to communicate with those extra external sensors.

AD0 pin lets you choose between the two possible I2C addresses the MPU6050 can use: 0x68 or 0x69. This is helpful if you want to connect two MPU6050 modules on the same I2C bus, or if another sensor is already using one of those addresses. When AD0 is pulled LOW, the address becomes 0x68, and when it is pulled HIGH, the address becomes 0x69. Because this pin is connected to ground through a 4.7 kΩ pulldown resistor, leaving it unconnected automatically sets the address to 0x68.

INT is the interrupt output pin. It allows the MPU6050 to trigger an interrupt when it detects specific events such as gestures, tapping, shaking, panning, zooming, or scrolling.

Wiring an MPU6050 Module to an Arduino

Now let’s connect the MPU6050 module to your Arduino.

Start with the power connections. Connect the VCC pin on the MPU6050 to the 5V pin on your Arduino. Then connect the GND pin to one of the ground pins on your Arduino.

Next, you need to connect the I2C communication pins. Remember, different Arduino boards have their I2C pins in different locations, so make sure you connect them correctly for your specific board. If you’re using an Arduino with the R3 layout, you’ll find the SDA and SCL pins on the header near the AREF pin. These same pins are also labeled as A4 (SDA) and A5 (SCL).

Here’s a quick reference table for the pin connections:

MPU6050 ModuleArduino
VCC5V
GNDGND
SCLSCL or A5
SDASDA or A4

This diagram shows you exactly how to connect everything:

Wiring MPU6050 Accel Gyro Module with Arduino

Library Installation

Getting the MPU6050 ready to work with your Arduino is straightforward, especially with helpful libraries that do the heavy lifting. A popular one is the Adafruit MPU6050 Library.

To install the library,

  1. First open your Arduino IDE program. Then click on the Library Manager icon on the left sidebar.
  2. Type “mpu6050” in the search box to filter your results.
  3. Look for the Adafruit MPU6050 Library by Adafruit.
  4. Click the Install button to add it to your Arduino IDE.
adafruit mpu6050 library installation

Since the Adafruit MPU6050 Library relies on other libraries to function, you will be prompted to install its dependencies, which include the Adafruit Unified Sensor Driver and the Adafruit Bus IO Library.

When this message appears, simply click INSTALL ALL to ensure everything is set up correctly.

adafruit mpu6050 library dependencies

Arduino Example Code

This example program shows how to use an MPU6050 sensor with an Arduino to read linear acceleration, angular rotation, and temperature.

#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Adafruit_MPU6050 mpu;

void setup(void) {
  Serial.begin(115200);

  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");

  // set accelerometer range to +-8G
  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);

  // set gyro range to +- 500 deg/s
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);

  // set filter bandwidth to 21 Hz
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);

  delay(100);
}

void loop() {
  /* Get new sensor events with the readings */
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  /* Print out the values */
  Serial.print("Acceleration X: ");
  Serial.print(a.acceleration.x);
  Serial.print(", Y: ");
  Serial.print(a.acceleration.y);
  Serial.print(", Z: ");
  Serial.print(a.acceleration.z);
  Serial.println(" m/s^2");

  Serial.print("Rotation X: ");
  Serial.print(g.gyro.x);
  Serial.print(", Y: ");
  Serial.print(g.gyro.y);
  Serial.print(", Z: ");
  Serial.print(g.gyro.z);
  Serial.println(" rad/s");

  Serial.print("Temperature: ");
  Serial.print(temp.temperature);
  Serial.println(" degC");

  Serial.println("");
  delay(500);
}

Once the code is uploaded to your Arduino, open the serial monitor and set the baud rate to 115200 bps. You’ll see information about linear acceleration, angular rotation, and temperature scrolling on your screen. Try moving the sensor around and watch how the numbers change in response.

mpu6050 arduino code acceleration gyro temperature output

Code Explanation:

At the start of the sketch, we include all the necessary libraries.

#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Next, we create an object called “mpu” that represents our sensor. This object gives us access to all the functions we need to control and read from the MPU6050.

Adafruit_MPU6050 mpu;

In the setup section, we first begin serial communication so we can see the output on the Serial Monitor.

Then we call the begin() function to start up the MPU6050 sensor. If the sensor isn’t connected properly or something goes wrong, we print a message saying the chip wasn’t found, and the program stops right there in an endless loop. But if everything works, we print “MPU6050 Found!” so we know it’s ready.

Serial.begin(115200);

// Try to initialize!
if (!mpu.begin()) {
        Serial.println("Failed to find MPU6050 chip");
        while (1) {
          delay(10);
        }
}

After that, we configure how sensitive we want our measurements to be. We use three different functions for this:

setAccelerometerRange(mpu6050_accel_range_t)

The setAccelerometerRange() function determines how much acceleration the sensor can measure. This function can take following values:

  • MPU6050_RANGE_2_G – for ±2g range (default)
  • MPU6050_RANGE_4_G – for ±4g range
  • MPU6050_RANGE_8_G – for ±8g range
  • MPU6050_RANGE_16_G – for ±16g range

setGyroRange(mpu6050_gyro_range_t)

The setGyroRange() function sets the maximum rotation speed the sensor can detect. This function can take following values:

  • MPU6050_RANGE_250_DEG – for 250 degrees-per-second range (default)
  • MPU6050_RANGE_500_DEG – for 500 degrees-per-second range
  • MPU6050_RANGE_1000_DEG – for 1000 degrees-per-second range
  • MPU6050_RANGE_2000_DEG – for 2000 degrees-per-second range

setFilterBandwidth(mpu6050_bandwidth_t)

The setFilterBandwidth() function sets the bandwidth of the Digital Low-Pass Filter, which helps smooth out the signal by getting rid of high-frequency noise. This function accepts the following values:

  • MPU6050_BAND_260_HZ – for 260 Hz bandwidth (According to the documentation, this disables the filter)
  • MPU6050_BAND_184_HZ – for 184 Hz bandwidth
  • MPU6050_BAND_94_HZ – for 94 Hz bandwidth
  • MPU6050_BAND_44_HZ – for 44 Hz bandwidth
  • MPU6050_BAND_21_HZ – for 21 Hz bandwidth
  • MPU6050_BAND_10_HZ – for 10 Hz bandwidth
  • MPU6050_BAND_5_HZ – for 5 Hz bandwidth

In this example, we set the accelerometer range to ±8G, the gyro range to ±500°/s, and the filter bandwidth to 21 Hz.

mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
mpu.setGyroRange(MPU6050_RANGE_500_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);

The measurement range is the maximum acceleration or angular velocity that your MPU6050 can read. Think about what you’re trying to measure and choose limits based on that. For example, do you need to measure the rotational speed of something slow like a record player, or something fast like a spinning wheel?

In the loop section, we collect data from the sensor and print it to the Serial Monitor. To do this, we create three variables—a, g, and temp—to store the data from the accelerometer, gyroscope, and temperature sensor. These variables are created using a special structure type called sensors_event_t, which is designed to hold many kinds of sensor data in one place. If you’re interested, you can find more details about this structure on GitHub.

sensors_event_t a, g, temp;

Then we call the getEvent() function. This function reads a new set of values from the sensor, converts them into proper units, and stores everything in our variables.

mpu.getEvent(&a, &g, &temp);

Finally, we print all of this data to the Serial Monitor.

Serial.print("Acceleration X: ");
Serial.print(a.acceleration.x);
Serial.print(", Y: ");
Serial.print(a.acceleration.y);
Serial.print(", Z: ");
Serial.print(a.acceleration.z);
Serial.println(" m/s^2");

Serial.print("Rotation X: ");
Serial.print(g.gyro.x);
Serial.print(", Y: ");
Serial.print(g.gyro.y);
Serial.print(", Z: ");
Serial.print(g.gyro.z);
Serial.println(" rad/s");

Serial.print("Temperature: ");
Serial.print(temp.temperature);
Serial.println(" degC");

Arduino Example Code 2 – Plotting MPU6050 data

Just looking at numbers printed from the MPU6050 might not be very helpful when trying to understand how the sensor responds to movement. That’s why it’s a great idea to use the Serial Plotter—a built-in tool in the Arduino IDE that helps you see the data visually in real-time as waveforms.

To try this out, use the updated code shown below. First, compile and upload the sketch to your Arduino board. Once that’s done, go to the top menu and select Tools > Serial Plotter. Make sure the baud rate in the serial plotter is set to 115200.

#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Adafruit_MPU6050 mpu;

void setup(void) {
  Serial.begin(115200);

  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }

  // set accelerometer range to +-8G
  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);

  // set gyro range to +- 500 deg/s
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);

  // set filter bandwidth to 21 Hz
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);

  delay(100);
}

void loop() {
  /* Get new sensor events with the readings */
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  /* Print out the values */
  Serial.print(a.acceleration.x);
  Serial.print(",");
  Serial.print(a.acceleration.y);
  Serial.print(",");
  Serial.print(a.acceleration.z);
  Serial.print(", ");
  Serial.print(g.gyro.x);
  Serial.print(",");
  Serial.print(g.gyro.y);
  Serial.print(",");
  Serial.print(g.gyro.z);
  Serial.println("");

  delay(10);
}

You should see a waveform similar to the one shown below when you move the module up and down along the Z-axis.

mpu6050 arduino plotter output

Code Explanation:

Most of this sketch works exactly like the previous example we looked at. We still include the same libraries, create our sensor object, initialize everything in the setup, and read sensor data in the loop. However, there are a few key differences that make this version work with the Serial Plotter.

  1. We don’t print the temperature readings this time. We’re focusing just on the acceleration and rotation data.
  2. Instead of printing labels like “Acceleration X:” before each number, we just print the raw values separated by commas. This creates what’s called a comma-separated list. The Serial Plotter needs the data formatted this way so it knows how to draw each value as a separate line on the graph.
  3. We take readings much more frequently. Instead of waiting 500 milliseconds between readings like before, we only wait 10 milliseconds. This faster sampling rate makes the graph look much smoother and lets you see changes in real time as you move the sensor around.

So in the loop, we grab our sensor readings, print all six values (three for acceleration and three for rotation) with commas between them, and then wait just 10 milliseconds before doing it all again.

Amrit Prabhu

Amrit Prabhu

Amrit is an Electronics Engineer who loves making complex programming and hardware concepts accessible. He has more than 15 years of experience, having worked as a Senior Programmer Analyst at Mindtree Ltd. and Symantec on major projects like Windows 8, Wolters Kluwer CCH and NSE. Since 2018, he has authored hundreds of tutorials and guides for Last Minute Engineers, helping readers master everything from basic circuits to IoT. You can find him on LinkedIn