Categories
Examples

ESP32+MPU6050 Interfacing without Adafruit Library

Today we are going to write a baremetal kind of code for accessing the values from MPU6050 in ESP32 Wroom Nodemcu module without using Adafruit library. Sometimes we just need a plain reading and using an external library seems overkill, besides, it hides lot of underlaying simplicity and do hardware abstraction that it will not let us see how simply things could be done. Our today’s approach will simply the process and let us read the MPU6050 gyroscope without any kind of complexity. So, let’s get started.

What is I2C Protocol?

I2C (Inter-Integrated Circuit) is a widely used communication protocol that enables multiple devices to communicate using just two wires: SDA (Serial Data) and SCL (Serial Clock).

How I2C Works

  1. Master-Slave Architecture
    • Devices on an I2C bus are either masters (controllers) or slaves (peripherals).
    • The master initiates communication, while slaves respond.
  2. Addressing Devices
    • Each slave has a unique 7-bit or 10-bit address.
    • Before exchanging data, the master first sends the address of the slave it wants to communicate with.
  3. Two-Wire Communication
    • SDA (Data Line): Transmits data between devices.
    • SCL (Clock Line): Synchronizes data transfer.
  4. Start & Stop Conditions
    • A Start Condition occurs when SDA transitions from HIGH to LOW while SCL remains HIGH.
    • A Stop Condition happens when SDA transitions back to HIGH while SCL is HIGH.
  5. Data Transmission (Read/Write)
    • The master sends a slave address + read/write bit.
    • If writing, the master sends data byte-by-byte.
    • If reading, the slave sends data while the master acknowledges.
  6. Acknowledge (ACK/NACK)
    • Each byte transfer is followed by an ACK (Acknowledgment) from the receiver.
    • If no acknowledgment (NACK) occurs, the communication stops.

Overall Communication Steps

  • ESP32 (Master) sends the MPU6050 address (0x68).
  • ESP32 requests data (accelerometer, gyroscope values).
  • MPU6050 responds by sending data over SDA.

MPU6050 to ESP32 Wiring (I2C)

MPU6050 PinESP32 Pin
VCC3.3V or 5V
GNDGND
SCLGPIO 22
SDAGPIO 21
INT(Optional, for interrupts)

Steps to Connect:

  1. Power the MPU6050: Connect VCC to 3.3V or 5V (ESP32 supports both).
  2. Ground Connection: Connect GND to GND on ESP32.
  3. I2C Communication:
    • SCL (Clock) → GPIO 22
    • SDA (Data) → GPIO 21
  4. Interrupt Pin (Optional): If needed, connect INT to an available GPIO for event-based data retrieval.

ESP32 + MPU6050 Code (Using Only Wire Library)

#include <Wire.h>

#define MPU_ADDR 0x68

int16_t ax, ay, az, gx, gy, gz;

void setup() {
  Wire.begin(); // SDA = 21, SCL = 22 by default on ESP32
  Serial.begin(115200);

  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // wake up MPU6050
  Wire.endTransmission(true);
}

void loop() {
  Wire.beginTransmission(MPU_ADDR);
  Wire.write(0x3B); // starting with ACCEL_XOUT_H
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_ADDR, 14, true);

  ax = Wire.read() << 8 | Wire.read();
  ay = Wire.read() << 8 | Wire.read();
  az = Wire.read() << 8 | Wire.read();
  Wire.read(); Wire.read(); // skip temperature
  gx = Wire.read() << 8 | Wire.read();
  gy = Wire.read() << 8 | Wire.read();
  gz = Wire.read() << 8 | Wire.read();

  Serial.print("AX: "); Serial.print(ax);
  Serial.print(" AY: "); Serial.print(ay);
  Serial.print(" AZ: "); Serial.print(az);
  Serial.print(" GX: "); Serial.print(gx);
  Serial.print(" GY: "); Serial.print(gy);
  Serial.print(" GZ: "); Serial.println(gz);

  delay(500);
}

Code language: Arduino (arduino)

Results:

Here are the serial monitor results for this code running

AX: 3692 AY: 4436 AZ: -14496 GX: -393 GY: 192 GZ: -211
AX: 3604 AY: 4864 AZ: -14456 GX: -335 GY: 230 GZ: -16
AX: 3616 AY: 4892 AZ: -14320 GX: -366 GY: 205 GZ: -71
AX: 3676 AY: 4864 AZ: -14320 GX: -400 GY: 234 GZ: -43
AX: 3752 AY: 4840 AZ: -14784 GX: 75 GY: 435 GZ: -447
AX: 3496 AY: 4692 AZ: -14444 GX: -330 GY: 174 GZ: -40
AX: 3396 AY: 4856 AZ: -14820 GX: -339 GY: 107 GZ: -245
AX: 3952 AY: 4468 AZ: -15260 GX: -665 GY: 1314 GZ: 353
AX: 3236 AY: 17452 AZ: 5512 GX: -7835 GY: -17 GZ: 15337
AX: 9260 AY: 4900 AZ: 15736 GX: -12521 GY: -3973 GZ: -9261
AX: 8332 AY: 5936 AZ: 13084 GX: 1739 GY: 3657 GZ: -4937
AX: 9932 AY: 8920 AZ: 10864 GX: -945 GY: -4511 GZ: 608
AX: 11576 AY: 8380 AZ: 8516 GX: 468 GY: 2884 GZ: 248
AX: 12336 AY: 7436 AZ: 10264 GX: -672 GY: 282 GZ: 265
AX: -1228 AY: 9360 AZ: 9672 GX: 6131 GY: 21945 GZ: -9953
AX: -10992 AY: 10820 AZ: 5456 GX: 3386 GY: 4453 GZ: -2161
AX: -10848 AY: 12864 AZ: 7708 GX: -2808 GY: -13280 GZ: 6528
AX: 8012 AY: 11188 AZ: 11048 GX: -5945 GY: -13967 GZ: 11098
AX: 15460 AY: 7684 AZ: 808 GX: 3334 GY: -6553 GZ: -14082
AX: 4168 AY: 17176 AZ: -2592 GX: -5018 GY: -816 GZ: -8308
AX: 448 AY: 14332 AZ: 8468 GX: -13901 GY: 13118 GZ: -2512
AX: -12060 AY: 16148 AZ: 15904 GX: -11537 GY: 17098 GZ: -1113
AX: -5568 AY: 9780 AZ: 3300 GX: -1523 GY: -10671 GZ: 15930
AX: 14788 AY: 8476 AZ: 2496 GX: -6817 GY: -18660 GZ: 11173
AX: 12416 AY: 7580 AZ: -1604 GX: -8017 GY: 21054 GZ: -12969
AX: -1008 AY: 11052 AZ: 12232 GX: 2489 GY: 32411 GZ: -4520
AX: -6896 AY: 12340 AZ: 8272 GX: 1011 GY: 6016 GZ: 3154
AX: -4836 AY: 15548 AZ: 11008 GX: -8437 GY: -18132 GZ: 7223
AX: 13016 AY: 4444 AZ: 6592 GX: -4827 GY: -4501 GZ: 2188
AX: 9300 AY: 6724 AZ: 14484 GX: 10048 GY: 21093 GZ: -32341
AX: -9316 AY: 10860 AZ: 2836 GX: 1089 GY: 2972 GZ: -402
AX: 13372 AY: 1316 AZ: -1988 GX: 101 GY: 10149 GZ: 2296
AX: -3585 AY: -1 AZ: -1 GX: -1 GY: -1 GZ: -1
AX: -2728 AY: 556 AZ: 10724 GX: -12785 GY: 342 GZ: -7891
AX: -4108 AY: 388 AZ: 16732 GX: -319 GY: 373 GZ: -38
AX: -4296 AY: 528 AZ: 16860 GX: -440 GY: -99 GZ: 25
AX: -4628 AY: 252 AZ: 17092 GX: -989 GY: 365 GZ: 82
AX: -4396 AY: 480 AZ: 16796 GX: -432 GY: 168 GZ: -34
AX: -4472 AY: 588 AZ: 16676 GX: -391 GY: 169 GZ: -80
AX: -4492 AY: 480 AZ: 16728 GX: -353 GY: 151 GZ: -58
AX: -4532 AY: 488 AZ: 16788 GX: -362 GY: 231 GZ: -78
AX: -4504 AY: 452 AZ: 16736 GX: -413 GY: 163 GZ: -47
AX: -4448 AY: 452 AZ: 16692 GX: -399 GY: 233 GZ: -62
AX: -4452 AY: 440 AZ: 16724 GX: -350 GY: 175 GZ: -36
AX: -4428 AY: 512 AZ: 16724 GX: -398 GY: 196 GZ: -86
AX: -4440 AY: 468 AZ: 16628 GX: -372 GY: 220 GZ: -46
AX: -4364 AY: 504 AZ: 16796 GX: -353 GY: 214 GZ: -14
AX: -4412 AY: 428 AZ: 16840 GX: -542 GY: 1317 GZ: -294Code language: HTTP (http)

Converting Raw MPU6050 Data to Proper Units

Your MPU6050 sensor is providing raw data, which needs to be converted into proper units (e.g., acceleration in g and angular velocity in °/s). Here’s how you can process the readings:

The MPU6050 provides raw 16-bit values, and the default sensitivity is 16384 LSB/g (for ±2g range). The raw gyroscope values use 131 LSB per °/s (for ±250°/s range).

Troubleshooting

If things don’t goes as expected you might need to verify few things to make sure everything is wired correctly and do some troubleshooting on hardware side as well as debugging on software side to verify things are correctly in order.

If your MPU6050 is reading -1 for all values, here are some common issues to check:

1. Check Wiring Connections

Make sure:

  • VCC is connected to 3.3V or 5V (depending on your module).
  • GND is connected properly.
  • SDA (Data) is connected to GPIO 21.
  • SCL (Clock) is connected to GPIO 22.

Use a multimeter to check continuity of the wires.

2. Verify I2C Communication

Run the following I2C scanner sketch to ensure the ESP32 is detecting the MPU6050:

#include <Wire.h>

void setup() {
    Serial.begin(115200);
    Wire.begin();
    Serial.println("Scanning I2C devices...");
}

void loop() {
    for (byte address = 1; address < 127; address++) {
        Wire.beginTransmission(address);
        if (Wire.endTransmission() == 0) {
            Serial.print("Found device at 0x");
            Serial.println(address, HEX);
        }
    }
    delay(2000);
}
Code language: Arduino (arduino)
  • If MPU6050 is detected at 0x68 or 0x69, I2C is working.

3. Check Power Management Register (PWR_MGMT_1)

MPU6050 starts in sleep mode by default. If you don’t wake it up correctly, it might return -1 for all readings.

Try manually waking it up:

Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // Wake up MPU6050
Wire.endTransmission();Code language: Arduino (arduino)

Ensure this line runs before reading sensor values.

4. Try Reading Single Register

Instead of requesting 14 bytes, test reading one register manually:

Wire.beginTransmission(MPU6050_ADDR);
Wire.write(0x3B); // ACCEL_XOUT_H
Wire.endTransmission(false);
Wire.requestFrom(MPU6050_ADDR, 2, true);

int16_t accelX = (Wire.read() << 8) | Wire.read();
Serial.println(accelX);
Code language: Arduino (arduino)

If this also returns -1, your MPU6050 might be faulty or not properly wired.

By Abdul Rehman

My name is Abdul Rehman and I love to do Reasearch in Embedded Systems, Artificial Intelligence, Computer Vision and Engineering related fields. With 10+ years of experience in Research and Development field in Embedded systems I touched lot of technologies including Web development, and Mobile Application development. Now with the help of Social Presence, I like to share my knowledge and to document everything I learned and still learning.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.