ESP32 · MPU6050

ESP32 MPU6050 Simulator: Wiring, Code and a Live Circuit

This is an MPU6050 accelerometer and gyroscope on a GY-521 board, wired to an ESP32 DevKit over I2C and read live: the sketch wakes the chip and prints the three acceleration axes four times a second. In the editor, drag the pitch and roll sliders and watch gravity move between them.

Four wires: 3V3, GND, SDA to GPIO 21 (D21) and SCL to GPIO 22 (D22). The sketch talks to the registers with Wire, so nothing is hidden behind a library.

  • 3.3 V logic
  • Library: Wire.h only
  • I2C address 0x68
  • SDA 21, SCL 22
ESP32 · MPU6050live0.000 s 0.00x
Click to open it in the editor
The circuit itself, running on the simulator with the sketch below. Press what can be pressed; click anything else to open it in the editor.

Wiring the MPU6050 to the ESP32

Every connection in the circuit above, with the board’s own pin names.

MPU6050 pinESP32 pinWhy
VCC3V3The GY-521 board has a 3.3 V regulator, so it takes 3.3 or 5 V.
GNDGNDCommon ground.
SCLGPIO 22 (D22)I2C clock.
SDAGPIO 21 (D21)I2C data.
AD0not connectedLow (the board’s own pull-down): address 0x68. Tie it high for 0x69.

On an ESP32 DevKit, Wire.begin() with no arguments puts SDA on GPIO 21 and SCL on GPIO 22, labeled D21 and D22. Powered from 3V3, the GY-521’s pull-ups hold SDA and SCL at 3.3 V, the ESP32’s own level. Its regulator still works from 3.3 V, with a little less headroom.

Pins to leave alone on the ESP32

GPIO 34, 35, 36 (VP) and 39 (VN) are input only: they cannot drive a pin or take an internal pull-up. GPIO 0, 2, 5, 12 and 15 are strapping pins, read at power-on, and GPIO 6 to 11 are the flash chip.

On a real bench

The thirty-pin DevKit straddles a breadboard with one row of holes free on each side, which is where the MPU6050’s jumpers go. Many ESP32 boards are wider and cover both rows; then use two breadboards side by side. Hold BOOT while uploading if the IDE cannot connect.

The code

The sketch the circuit above runs. Open it in the editor, change a line and press Run: it compiles in your browser.

MPU6050 on ESP32 I2C
#include <Wire.h>

const int MPU = 0x68;   // AD0 low

int16_t read16() {
  int16_t high = Wire.read();
  return (high << 8) | Wire.read();
}

void setup() {
  Serial.begin(115200);
  Wire.begin();                 // SDA GPIO 21 (D21), SCL GPIO 22 (D22)
  Wire.beginTransmission(MPU);
  Wire.write(0x6B);             // PWR_MGMT_1
  Wire.write(0);                // wake up: it starts asleep
  Wire.endTransmission();
  Serial.println("MPU6050 awake");
}

void loop() {
  Wire.beginTransmission(MPU);
  Wire.write(0x3B);             // ACCEL_XOUT_H, then Y, Z, temperature, gyro
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6);
  int16_t ax = read16();
  int16_t ay = read16();
  int16_t az = read16();
  // At the default range, 16384 counts is 1 g.
  Serial.print("Accel x: ");
  Serial.print(ax);
  Serial.print("  y: ");
  Serial.print(ay);
  Serial.print("  z: ");
  Serial.println(az);
  delay(250);
}

The MPU6050 powers up asleep, and every reading is zero until register 0x6B is written with 0. That one write in setup() is the step most broken sketches are missing.

Reading starts at register 0x3B and the chip sends the bytes that follow in order: X, Y and Z acceleration, two bytes each, high byte first. endTransmission(false) keeps the bus between the address write and the read, so the three axes come from the same sample.

Lying flat and still, the board reads 0, 0 and 16384: one g straight down on Z. Tilt it with the pitch and roll sliders and the gravity moves between the axes. This sketch uses Wire directly; Adafruit_MPU6050.h and MPU6050.h also compile here, but the raw registers are what those libraries do underneath. Serial.begin(115200) opens the serial monitor. Serial is UART0 on the USB bridge. ESP32 sketches usually run it at 115200 baud, which this one does.

Common mistakes with the MPU6050 on the ESP32

Not waking it up

Out of reset the chip is asleep and returns zeros on every axis. Write 0 to register 0x6B first. It is the single most common MPU6050 fault.

Wiring to the ESP8266’s I2C pins

Many MPU6050 tutorials were written for the ESP8266, with SDA on GPIO 4 and SCL on GPIO 5. On an ESP32 DevKit Wire.begin() uses GPIO 21 (D21) and GPIO 22 (D22).

Expecting an angle from the gyro

The gyroscope measures how fast the board turns, in degrees per second, not which way it points. For tilt, use the arctangent of two acceleration axes; for a steady angle while moving, combine both with a complementary filter.

Questions and answers

Can I simulate an MPU6050 with an ESP32 DevKit?

Yes. The circuit at the top of this page is an ESP32 DevKit with a MPU6050, running in your browser on a simulated ESP32 (Xtensa LX6). The pitch and roll sliders tilt the simulated chip, so the acceleration on each axis is what gravity would give at that angle. Press Run it in the editor to change the wiring or the code; it is free and needs no account.

Which pins does the MPU6050 use on the ESP32?

On an ESP32 DevKit, Wire.begin() with no arguments puts SDA on GPIO 21 and SCL on GPIO 22, labeled D21 and D22.

Why are all my readings zero?

The chip is still asleep: write 0 to register 0x6B. If the readings are -1 instead, nothing answered at 0x68, so check the wiring and the AD0 pin.

Can I use the Adafruit MPU6050 library?

Adafruit_MPU6050.h compiles here. This page reads the registers with Wire so the sketch shows what the chip actually does, and so it runs the same on every board.

Build your own MPU6050 project

Open this circuit in the editor, change the wiring or the code, and keep your version in a free account.