Preview build — page text is a draft awaiting human review. Code badges come from real compiles. The flasher is real but not yet hardware-tested; the Playground is still a preview.

MPU6050 with Raspberry Pi Pico W — MicroPython accelerometer and gyro

Read an MPU6050 (GY-521) on Pico W I2C0 (GP4/GP5) in MicroPython with no library: wake it, read raw accel and gyro, and work out pitch and roll.

MicroPythonVerified — micropython (mpy-cross v1.29.0), 3 Nov 2026Compile-only

Community draft — report a mistake

The MPU6050 is a 3-axis accelerometer and 3-axis gyro on one I2C chip. MicroPython has no built-in driver, but you don’t need one: wake the chip, read 14 bytes, scale them.

Wire the GY-521 to 3V3 and I2C0 (GP4/GP5). The script prints acceleration in g, rotation in degrees per second, the chip temperature, and pitch/roll worked out from gravity.

Wiring

Raspberry Pi Pico WOnly the pins used are shown · 3.3 V logicMPU6050 (GY-521)GNDGP4GP53V3VCCGNDSCLSDAXDA (not connected)XCL (not connected)AD0 (not connected)INT (not connected)
Every connection
Raspberry Pi Pico WMPU6050 (GY-521)WireNotes
3V3VCCred3V3 is pin 36. The GY-521 also has its own regulator.
GNDGNDblack
GP5SCLyellowGP5 is physical pin 7 (I2C0 SCL).
GP4SDAblueGP4 is physical pin 6 (I2C0 SDA). AD0 left open = address 0x68.

3.3–5 V (on-board 3.3 V regulator) part, 3.3 V board. The GY-521 has a 3.3 V regulator and pulls SDA/SCL up to 3.3 V, so it works on both 3.3 V boards and a 5 V Uno without a level shifter.

Board quirks

  • The MPU6050 boots asleep and returns all zeros until you write 0 to register 0x6B — the first thing the script does.
  • All seven values come from one 14-byte read starting at 0x3B, unpacked with struct.unpack(">7h", …) (big-endian signed 16-bit).
  • Pitch and roll from the accelerometer are only right while the board is still; for a balancing robot you need a complementary filter with the gyro.
  • Many cheap “MPU6050” boards carry an MPU6500 or a clone, and WHO_AM_I reads something other than 0x68 (0x70 for an MPU6500). The accel and gyro registers used here are the same; only the temperature formula differs slightly.

Code

main.pyMicroPython
# MPU6050 (GY-521) accelerometer + gyro on a Raspberry Pi Pico W (MicroPython, no library).
# Wiring: VCC -> 3V3 (pin 36), GND -> GND, SCL -> GP5 (pin 7), SDA -> GP4 (pin 6). I2C0.
# AD0 unconnected = address 0x68.
from machine import Pin, I2C
import struct
import math
import time

ADDR = 0x68
i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400_000)
if ADDR not in i2c.scan():
    raise SystemExit("No MPU6050 at 0x68 - found {}".format([hex(a) for a in i2c.scan()]))

who = i2c.readfrom_mem(ADDR, 0x75, 1)[0]  # WHO_AM_I: 0x68 on a genuine MPU6050
print("MPU6050 found, WHO_AM_I = 0x%02X" % who)
i2c.writeto_mem(ADDR, 0x6B, b"\x00")  # PWR_MGMT_1: wake up (it boots in sleep mode)
i2c.writeto_mem(ADDR, 0x1C, b"\x00")  # accel range +-2 g  -> 16384 LSB/g
i2c.writeto_mem(ADDR, 0x1B, b"\x00")  # gyro range +-250 dps -> 131 LSB/(deg/s)
time.sleep_ms(100)


def read():
    ax, ay, az, t, gx, gy, gz = struct.unpack(">7h", i2c.readfrom_mem(ADDR, 0x3B, 14))
    return (ax / 16384, ay / 16384, az / 16384, t / 340 + 36.53, gx / 131, gy / 131, gz / 131)


while True:
    ax, ay, az, temp, gx, gy, gz = read()
    pitch = math.degrees(math.atan2(-ax, math.sqrt(ay * ay + az * az)))
    roll = math.degrees(math.atan2(ay, az))
    print("Accel g: {:+.2f} {:+.2f} {:+.2f} | Gyro dps: {:+6.1f} {:+6.1f} {:+6.1f} | Pitch {:+5.1f} Roll {:+5.1f} | {:.1f} C".format(
        ax, ay, az, gx, gy, gz, pitch, roll, temp))
    time.sleep_ms(250)

Expected serial output

REPL / Thonny shellOutput
MPU6050 found, WHO_AM_I = 0x68
Accel g: +0.01 -0.02 +1.00 | Gyro dps:   -1.2   +0.8   -0.4 | Pitch  -0.6 Roll  -1.1 | 29.4 C
Accel g: +0.48 -0.03 +0.87 | Gyro dps:  +12.6   -3.1   +0.9 | Pitch -28.9 Roll  -2.0 | 29.4 C

Common errors

No MPU6050 at 0x68 - found ['0x69']

AD0 is pulled HIGH on your board. Change ADDR to 0x69.

Gyro never reads exactly zero when still

Every MEMS gyro has an offset. Average 200 readings at start-up while the board is still and subtract them.

OSError: [Errno 5] EIO

SDA and SCL are swapped, or the wires are on a pair that is not I2C0. GP4 = SDA (pin 6), GP5 = SCL (pin 7).

↑↓ to move · Enter to open