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
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
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 |
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) |
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) |
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) |
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 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)
#!/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 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 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
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).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.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.