Documentation

MPU6050 Accelerometer 6DOF - Raspberry Pi, Arduino, ESP32 I2C Accelerometer
Documentation / MPU6050 Accelerometer 6DOF - Raspberry Pi, Arduino, ESP32 I2C Accelerometer

MPU6050 Accelerometer 6DOF - Raspberry Pi, Arduino, ESP32 I2C Accelerometer

mpu-6050-pre-soldered-6-dof-accelerometershillehtek

Overview

The MPU6050 is a 6-axis inertial measurement unit (IMU) that combines a 3-axis accelerometer and a 3-axis gyroscope on a single chip. It is the single most popular motion sensor in the maker world — used in drones, self-balancing robots, wearable step counters, gesture-controlled games, head trackers, and anywhere a microcontroller needs to know how it is moving or oriented in space.

Communication is over I2C, so you only need four wires to your microcontroller: VCC, GND, SCL, and SDA. The module runs on 3V-5V through its onboard LDO regulator, making it a drop-in fit for Arduino, ESP32, Raspberry Pi, and Raspberry Pi Pico. Each axis is digitized with a 16-bit ADC and the accelerometer ranges (±2g / ±4g / ±8g / ±16g) and gyro ranges (±250 / ±500 / ±1000 / ±2000 °/s) are all software-selectable.

The MPU6050 also contains an on-chip Digital Motion Processor (DMP) that can do sensor fusion in hardware and deliver clean quaternion data straight to your MCU — perfect for 3D orientation projects without the math headache.

At a Glance

Operating Voltage
3V - 5V (module)
Interface
I2C
I2C Address
0x68 (0x69 if AD0 = HIGH)
Accelerometer Range
±2g / ±4g / ±8g / ±16g
Gyroscope Range
±250 - ±2000 °/s
Pins
VCC, GND, SCL, SDA, XDA, XCL, AD0, INT

Specifications

Parameter Value
IC InvenSense MPU-6050
Module Operating Voltage 3V - 5V (onboard LDO)
IC Supply Voltage 2.375V - 3.46V
Operating Current ~3.9 mA (normal mode)
Accelerometer 3-axis, 16-bit ADC, ±2/4/8/16 g
Gyroscope 3-axis, 16-bit ADC, ±250/500/1000/2000 °/s
Digital Motion Processor On-chip DMP for sensor fusion
Temperature Sensor On-chip, -40 to +85 °C
Communication I2C (up to 400 kHz), 7-bit address 0x68 / 0x69
Auxiliary I2C XDA / XCL for external magnetometer
Interrupt Programmable INT output pin
Operating Temperature -40 to +85 °C
Dimensions 20 x 16 mm (typical breakout)

Pinout Diagram

MPU6050 GY-521 IMU module pinout diagram showing VCC, GND, SCL, SDA, XDA, XCL, AD0, and INT pins

The MPU6050 breakout has 8 pins along one edge. VCC: 3V-5V power in. GND: ground. SCL: I2C serial clock. SDA: I2C serial data. XDA / XCL: auxiliary I2C data and clock for chaining an external magnetometer (not needed for basic motion sensing). AD0: I2C address select — leave low for 0x68, pull HIGH to change the address to 0x69 so two MPU6050s can share one bus. INT: programmable interrupt output that fires when new data is ready, motion is detected, or the FIFO is full. For a basic read you only need the first four pins (VCC, GND, SCL, SDA).

Wiring Guide

Arduino Wiring

On the Arduino Uno and Nano, the hardware I2C pins are A4 (SDA) and A5 (SCL). The MPU6050 module has onboard 3.3V regulation and level-shifting, so you can power it straight from the Arduino's 5V rail.

MPU6050 Pin Arduino Pin
VCC 5V (or 3.3V)
GND GND
SCL A5 (SCL)
SDA A4 (SDA)
INT Digital Pin 2 (optional)
AD0 / XDA / XCL Leave unconnected for basic use
Tip: The MPU6050 module has onboard 4.7k I2C pull-ups to its 3.3V rail, so you don't need to add any. If you chain multiple I2C devices and the bus gets sluggish, remove the pull-ups from one of them.

ESP32 Wiring

The ESP32's default I2C pins are GPIO 21 (SDA) and GPIO 22 (SCL). Because the MPU6050 module runs at 3.3V logic, it pairs perfectly with the ESP32 — no level shifting required.

MPU6050 Pin ESP32 Pin
VCC 3.3V (or VIN / 5V)
GND GND
SCL GPIO 22
SDA GPIO 21
INT GPIO 19 (optional)
Tip: If you want to use two MPU6050s on the same ESP32 (e.g. for sensor fusion across two joints), wire AD0 to 3.3V on one of them. That flips its I2C address from 0x68 to 0x69, avoiding a collision.

Raspberry Pi Wiring

The Raspberry Pi exposes its hardware I2C bus on physical pins 3 (SDA) and 5 (SCL). Enable I2C with sudo raspi-config before running any code. The MPU6050 module can be powered from the Pi's 3.3V or 5V rail.

MPU6050 Pin Raspberry Pi Pin
VCC Pin 2 (5V) or Pin 1 (3.3V)
GND Pin 6 (GND)
SCL Pin 5 (GPIO 3 / SCL)
SDA Pin 3 (GPIO 2 / SDA)
INT Pin 7 (GPIO 4) (optional)
Note: Enable I2C first: sudo raspi-config > Interface Options > I2C > Enable > reboot. Then confirm the sensor is on the bus with sudo i2cdetect -y 1 — you should see 68.

Raspberry Pi Pico Wiring

The Pico has two I2C buses. This guide uses I2C0 on GP0 (SDA) and GP1 (SCL). Power the module from the Pico's 3V3 pin.

MPU6050 Pin Pico Pin
VCC 3V3 (Pin 36)
GND GND
SCL GP1 (Pin 2)
SDA GP0 (Pin 1)
INT GP2 (Pin 4) (optional)
Tip: Run an I2C scan first in MicroPython (i2c.scan()) and confirm you see [0x68]. That one check catches 90% of wiring mistakes before you start debugging sensor math.

Code Examples

Arduino

mpu6050_arduino.ino
// MPU6050 IMU - Arduino Example
// Library: "Adafruit MPU6050" (Arduino Library Manager)
// I2C: SDA -> A4, SCL -> A5

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

Adafruit_MPU6050 mpu;

void setup() {
  Serial.begin(115200);
  while (!Serial) delay(10);

  if (!mpu.begin()) {
    Serial.println("MPU6050 not found. Check wiring.");
    while (1) delay(10);
  }
  Serial.println("MPU6050 ready.");

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

void loop() {
  sensors_event_t a, g, t;
  mpu.getEvent(&a, &g, &t);

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

  Serial.print("Gyro  (rad/s)  X="); Serial.print(g.gyro.x);
  Serial.print(" Y="); Serial.print(g.gyro.y);
  Serial.print(" Z="); Serial.println(g.gyro.z);

  Serial.print("Temp  (C)      "); Serial.println(t.temperature);
  Serial.println();
  delay(500);
}

Raspberry Pi (Python)

mpu6050_rpi.py
#!/usr/bin/env python3
# MPU6050 IMU - Raspberry Pi Example
# Install: pip3 install mpu6050-raspberrypi
# Enable I2C: sudo raspi-config -> Interface Options -> I2C

from mpu6050 import mpu6050
import time

sensor = mpu6050(0x68)

print("MPU6050 IMU (Ctrl+C to stop)")

try:
    while True:
        accel = sensor.get_accel_data()     # m/s^2
        gyro  = sensor.get_gyro_data()      # deg/s
        temp  = sensor.get_temp()           # deg C

        print("Accel  X={:+.2f}  Y={:+.2f}  Z={:+.2f}".format(
            accel['x'], accel['y'], accel['z']))
        print("Gyro   X={:+.2f}  Y={:+.2f}  Z={:+.2f}".format(
            gyro['x'],  gyro['y'],  gyro['z']))
        print("Temp   {:.2f} C\n".format(temp))
        time.sleep(0.5)
except KeyboardInterrupt:
    print("\nStopped by user")

Raspberry Pi Pico (MicroPython)

mpu6050_pico.py
# MPU6050 IMU - Pico MicroPython Example
# I2C0: SDA -> GP0, SCL -> GP1

from machine import I2C, Pin
import time, struct

MPU_ADDR  = 0x68
PWR_MGMT  = 0x6B
ACCEL_OUT = 0x3B

i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=400000)

# Wake up the sensor (clears sleep bit)
i2c.writeto_mem(MPU_ADDR, PWR_MGMT, b'\x00')

def read_all():
    raw = i2c.readfrom_mem(MPU_ADDR, ACCEL_OUT, 14)
    ax, ay, az, t, gx, gy, gz = struct.unpack('>hhhhhhh', raw)
    # Scale to physical units (default ranges: ±2g, ±250 deg/s)
    return {
        'ax': ax / 16384.0, 'ay': ay / 16384.0, 'az': az / 16384.0,
        'gx': gx / 131.0,   'gy': gy / 131.0,   'gz': gz / 131.0,
        'temp_c': t / 340.0 + 36.53
    }

print("MPU6050 IMU")
while True:
    d = read_all()
    print("Accel g: {ax:+.2f} {ay:+.2f} {az:+.2f}   Gyro d/s: {gx:+.1f} {gy:+.1f} {gz:+.1f}   T={temp_c:.1f}C"
          .format(**d))
    time.sleep_ms(500)

ESP32 (MicroPython)

mpu6050_esp32.py
# MPU6050 IMU - ESP32 MicroPython Example
# I2C: SDA -> GPIO 21, SCL -> GPIO 22

from machine import I2C, Pin
import time, struct

MPU_ADDR  = 0x68
PWR_MGMT  = 0x6B
ACCEL_OUT = 0x3B

i2c = I2C(0, sda=Pin(21), scl=Pin(22), freq=400000)

print("I2C devices:", [hex(d) for d in i2c.scan()])

# Wake up the sensor
i2c.writeto_mem(MPU_ADDR, PWR_MGMT, b'\x00')

while True:
    raw = i2c.readfrom_mem(MPU_ADDR, ACCEL_OUT, 14)
    ax, ay, az, t, gx, gy, gz = struct.unpack('>hhhhhhh', raw)
    print("Accel g: {:+.2f} {:+.2f} {:+.2f}   Gyro d/s: {:+.1f} {:+.1f} {:+.1f}".format(
        ax/16384.0, ay/16384.0, az/16384.0,
        gx/131.0,   gy/131.0,   gz/131.0))
    time.sleep_ms(500)

Frequently Asked Questions

How do I wire the MPU6050 to an Arduino?
Connect VCC to 5V (or 3.3V), GND to GND, SCL to A5, and SDA to A4 on an Arduino Uno. The module's onboard regulator and level shifters accept either 3.3V or 5V on VCC, so either rail is safe. You can leave INT, AD0, XDA, and XCL unconnected for basic motion reading.
What is the I2C address of the MPU6050?
The default address is 0x68. If you pull the AD0 pin HIGH to 3.3V, the address switches to 0x69. That lets you run two MPU6050 modules on the same I2C bus — one at each address — which is useful for projects with two sensor nodes (e.g. wrist + elbow tracking).
Can I use the MPU6050 with a 3.3V board like the ESP32 or Pico?
Yes. The module runs happily at 3.3V and the I2C lines are pulled up to 3.3V on-board. There is no need for level shifters when you power VCC from a 3.3V rail — ESP32, Pico, and Raspberry Pi all work out of the box.
Why do my gyro readings drift even when the sensor isn't moving?
All MEMS gyros drift — that's physics, not a defect. The fix is calibration: average a few hundred readings while the sensor is stationary, then subtract that bias from every live reading. For long-term orientation, combine the gyro with the accelerometer using a complementary or Kalman filter, or let the MPU6050's built-in DMP do the fusion for you.
What libraries should I use?
For Arduino, the Adafruit MPU6050 library is the easiest — install it via the Library Manager. For Raspberry Pi, use the mpu6050-raspberrypi Python package. For MicroPython on Pico or ESP32, you can either use a community driver or talk to the registers directly as shown in the code examples above.
What are the XDA and XCL pins for?
They are the MPU6050's auxiliary I2C master bus. You can connect an external magnetometer (like an HMC5883L) to XDA/XCL and let the MPU6050 read it for you, then forward the data over its own I2C slave interface. Most beginners leave XDA and XCL disconnected — they are only needed for 9-DOF sensor fusion setups.
The sensor doesn't show up on an I2C scan — what went wrong?
Check the basics first: SDA and SCL aren't swapped, VCC is 3-5V, and GND is shared with your MCU. On Raspberry Pi, make sure I2C is enabled in raspi-config. If you powered VCC but nothing responds, the chip may be stuck in sleep — write 0x00 to register 0x6B (PWR_MGMT_1) to wake it.

Related Tutorials