Movement and position

MPU6050 with ESP32: Wiring, Code and Calibration

MPU6050 Project Guide with ESP32 and Arduino; Datasheets, ranges, I2C addressing, wiring, hex code, gyro bias and troubleshooting.

Contents

Six-axis motion sensor project-based training

Setting up MPU6050 with ESP32; From datasheet to gyroscope calibration

In this guide, we'll introduce the MPU6050 as a true six-axis IMU, clarify the difference between a raw chip and a ready-made board, and step-by-step through I2C addressing, measurement ranges, wiring, practical code, output analysis, and troubleshooting. All technical values ​​are adapted from TDK/InvenSense official documentation and Adafruit library API.

Real Adafruit MPU6050 board connected to a development board and an on-board OLED display, with I2C wires
Actual photo of the Adafruit MPU6050 board in a wired test; By Bryan Siepert licensed under CC BY-SA 3.0, resized without cropping for LCENJ.
Sensor type3-axis accelerometer + 3-axis gyroscope
Raw chip feeding2.375 to 3.46V
MPU6050 interfaceI2C to 400kHz
7-bit address0x68 or 0x69

What is the MPU6050 and what does it measure?

The MPU6050 is an inertial measurement unit, or IMU, with six degrees of freedom: it measures linear acceleration and the effect of gravity on the X, Y, and Z axes, and reports angular velocity on the same three axes. All six ADC channels have sixteen bits. This piece does not have a magnetometer; Therefore, the absolute direction to the north cannot be obtained from its raw data alone.

Robot balance control, tilt detection, motion recording, motion controller, vibration monitoring and roll and pitch estimation are suitable applications. For a stable angle, gyroscope and accelerometer data should be combined with an algorithm such as Complementary or Kalman. Simple integration of the gyroscope drifts over time due to bias and noise.

Appropriate applications and important limitations

Balancing robot

A long-term gravity reference accelerometer and gyroscope provide fast roll response. The controller must have a fixed sampling rate, filter and bias calibration.

Slope detection

When the linear motion is low, the direction of the gravity vector can be used for Roll and Pitch. In extreme acceleration, this assumption is temporarily invalid.

Motion and vibration monitoring

The measurement range and bandwidth should be chosen according to the amplitude and frequency of the phenomenon; Choosing a filter that is too slow can remove important parts of the motion.

Compass and Heading

The MPU6050 does not measure magnetic north by itself. Absolute Heading requires proper magnetometer, calibration and Sensor Fusion.

How to read the MPU6050 datasheet correctly?

First, see the difference between MPU-6000 and MPU-6050: MPU-6000 has I2C and SPI interface, but MPU-6050 only supports I2C and has a separate VLOGIC pin. The numbers below are for the raw MPU6050 chip, not necessarily the power input of a ready-made module.

Official parameteramountPractical result
Supply VDD chip2.375 to 3.46VDo not connect raw chip directly to 5V.
VLOGIC logic reference1.71V to VDDThe I2C level must be compatible with the host and circuit board.
working temperature-40 to +85°CBias calibration at one temperature is not sufficient for all temperatures.
The main interfaceI2C Fast Mode up to 400kHzStart at 100kHz for boards and short wires.
Output resolution16-bit ADC for each axisCode resolution does not equal true precision or zero noise.
FIFO buffer1024 byteUseful for reading Burst and reducing host load.
Six axis flow + DMPtypical 3.9mAThe datasheet number is defined for the chip and conditions.

A 16-bit output does not imply angular accuracy of 1/65536 of a revolution. Noise, initial bias, temperature-dependent bias, scale-factor error, mechanical mounting and vibration all affect the result. The gyroscope datasheet specifies initial zero-rate output tolerance and its temperature variation, so measuring bias at the start of a project is essential.

Ranges, sensitivity and filter selection

SensorFull ScaleDatasheet raw code sensitivity
accelerometer±2g، ±4g، ±8g، ±16g16384, 8192, 4096 and 2048 LSB/g respectively
Gyroscope±250، ±500، ±1000، ±2000 °/s131, 65.5, 32.8 and 16.4 LSB/(°/s), respectively.

Smaller range gives more numerical sensitivity but saturates in large movement. For the training sample, ±4g and ±500°/s are suitable balance; This is not a fixed version choice for all projects. If your bot has a hard hit or fast spin, record the actual Peak before increasing the range.

The Adafruit library offers bandwidth choices of 260, 184, 94, 44, 21, 10, and 5 Hz. The 21Hz filter in the sample code reduces noise on the table, but may be slow to capture fast motion. Design bandwidth, sampling rate and control delay together.

The difference between raw chip, GY-521 and Adafruit board

The VDD limit of 2.375 to 3.46 volts belongs to the chip itself. The Adafruit board shown in the picture has a regulator and level shifter according to the official manual, its Vin operates at 3-5V and it has a tenk ohm pull-up resistor on SDA and SCL. This specification should not be extended to any GY-521 blue board or unnamed module.

Some GY-521s have a feed regulator, but Level Shifting and Pull-up may be different. Before applying 5V, check the schematic of the same version and the actual SDA/SCL voltage. A safe and simple connection for the ESP32 is to power the document board with 3.3V and keep the I2C logic at 3.3V.

Pins, I2C Address and Key Registers

The base of the board is readyApplicationTip
VIN / VCCwin feedRead the limit from the documentation of the same module; For Adafruit board it is 3 to 5V.
GNDcommon landThe ground of ESP32 and the sensor must be common.
SDAI2C dataOpen-drain line with appropriate pull-up to logic level.
SCLI2C clockStart with the short wire.
AD0Select the least significant bit of the addressBottom: 0x68, Top: 0x69.
INTInterrupt outputCan be used for Data Ready, Motion and set events.

The official Register Map defines the register SMPLRT_DIV in 0x19, CONFIG in 0x1A, GYRO_CONFIG in 0x1B, and ACCEL_CONFIG in 0x1C. Acceleration, chip temperature, and gyro continuous data are from 0x3B to 0x48. PWR_MGMT_1 is in 0x6B and WHO_AM_I is in 0x75.

Wiring MPU6050 with ESP32 and Arduino Uno

Documented MPU6050 boardGeneric ESP32Arduino Uno
VIN3V35V only for documented Adafruit board; Otherwise, the module specification
GNDGNDGND
SDAGPIO21A4 / SDA
SCLGPIO22A5 / SCL
AD0GND for 0x68GND for 0x68
INTIn this example, it is not connectedIn this example, it is not connected

GPIO21 and GPIO22 are just default Generic ESP32. On ESP32-S3, C3 and custom boards, replace the actual pins on your board. The official Arduino-ESP32 documentation recommends using Wire.setPins before begin or the proper form of Wire.begin(SDA,SCL) to change pins.

Step-by-step setup in Arduino IDE

  1. From the Library Manager, install the Adafruit MPU6050, Adafruit Unified Sensor and Adafruit BusIO libraries.
  2. Select the correct ESP32 or Arduino Uno board and port.
  3. Do the wiring with power off and then check the module voltage and I2C line level.
  4. Run the i2c-scanner.ino file; 0x68 should be seen with AD0 down.
  5. Place the sensor on a fixed surface, upload the original code and open the Serial Monitor at 115200 baud.
  6. Do not touch the sensor until the end of 500 calibration samples; Then slowly move each axis and check the units.

MPU6050 practical code for ESP32 and Arduino

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

#if defined(ESP32)
constexpr int SDA_PIN = 21;
constexpr int SCL_PIN = 22;
#endif

constexpr uint8_t MPU6050_ADDRESS = 0x68;
constexpr uint16_t CALIBRATION_SAMPLES = 500;
Adafruit_MPU6050 mpu;
float biasX = 0, biasY = 0, biasZ = 0;

void calibrateGyro() {
  sensors_event_t a, g, t;
  for (uint16_t i = 0; i < CALIBRATION_SAMPLES; ++i) {
    mpu.getEvent(&a, &g, &t);
    biasX += g.gyro.x;
    biasY += g.gyro.y;
    biasZ += g.gyro.z;
    delay(5);
  }
  biasX /= CALIBRATION_SAMPLES;
  biasY /= CALIBRATION_SAMPLES;
  biasZ /= CALIBRATION_SAMPLES;
}

void setup() {
  Serial.begin(115200);
#if defined(ESP32)
  Wire.begin(SDA_PIN, SCL_PIN);
#else
  Wire.begin();
#endif
  Wire.setClock(100000);

  if (!mpu.begin(MPU6050_ADDRESS, &Wire)) {
    Serial.println(F("MPU6050 not found"));
    while (true) delay(10);
  }
  mpu.setAccelerometerRange(MPU6050_RANGE_4_G);
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
  calibrateGyro();
}

void loop() {
  sensors_event_t a, g, t;
  mpu.getEvent(&a, &g, &t);
  Serial.print(F("aX=")); Serial.print(a.acceleration.x, 3);
  Serial.print(F(" aY=")); Serial.print(a.acceleration.y, 3);
  Serial.print(F(" aZ=")); Serial.print(a.acceleration.z, 3);
  Serial.print(F(" | wX=")); Serial.print(g.gyro.x - biasX, 4);
  Serial.print(F(" wY=")); Serial.print(g.gyro.y - biasY, 4);
  Serial.print(F(" wZ=")); Serial.println(g.gyro.z - biasZ, 4);
  delay(100);
}

Code analysis and output unit

  • The condition #if defined(ESP32) specifies the Generic ESP32 pins; Uno uses Wire hardware foundations.
  • Wire.setClock(100000) is a conservative board to start with and stays below the 400kHz datasheet ceiling.
  • mpu.begin(0x68, &Wire) checks the WHO_AM_I ID through the library and performs initialization.
  • The acceleration output of the library is in m/s² and the gyroscope output is in rad/s; These are not LSB raw code.
  • The average of 500 samples only estimates the gyroscope bias at rest and the instantaneous temperature. This method does not correct for scale factor, misalignment, or temperature variations.
  • The constant bias of the accelerometer is not reduced, because even in the stationary state, the axis parallel to gravity sees approximately one g, and it is wrong to blindly remove it.

What is the use of the internal temperature sensor?

Temperature registers sit between the accelerometer and gyroscope data, and the datasheet gives the Temperature = TEMP_OUT / 340 + 36.53 relation to convert the raw code to Celsius. This temperature is related to the inside of the chip and does not take the place of the accurate ambient temperature sensor.

Its useful application is recording the temperature of the IMU itself along with the gyroscope bias. For accurate product, one can measure the bias at several controlled temperatures and build a compensation model; An offset is not guaranteed at room temperature for the entire -40 to +85 degree range.

Common errors and troubleshooting of MPU6050

signprobable causeSuggested review
0x68 is not seenSDA/SCL shift, ground not common, improper power supply or pull-upMeasure the voltage and run the scanner with a short wire and 100kHz.
Only 0x69 is visibleAD0 is at High levelChange the code address to 0x69 or lower AD0 as per design.
The gyroscope is not zero at restZero-rate natural bias or movement during calibrationKeep the range constant, repeat the average and record the temperature.
The angle slowly deviatesGyroscope Bias IntegralFix bias and sample rate and add Sensor Fusion.
Z acceleration is not close to zeroThe effect of gravityOn a horizontal surface, the axis parallel to gravity should show an absolute value near one g.
The numbers are loud while the engine is runningMechanical vibration, ground/feed or bad bandwidthTest the mechanical installation, decoupling, ground path and filter separately.
The output is stuck on the limitSmall Full Scale and SaturationRecord a larger range of selection and peak real motion.
Multiple modules respond togetherBoth have the same addressFor up to two pieces, set AD0 one down and one up.

PCB design tips, power supply and mechanical installation

  • Place the decoupling capacitors and feed path according to the Typical Operating Circuit datasheet near the chip.
  • Install the IMU near the rigid part of the PCB; Board bending and screw tension can change MEMS bias.
  • Avoid placing the IMU next to a motor, power inductor, or local heat source without testing.
  • document the axes printed on the module with the product coordinate device; Apply software 90 degree rotation explicitly.
  • For long cable, check bus capacitance, pull-up and SDA/SCL waveform with oscilloscope; 400kHz is an interface ceiling, not a requirement.
  • Use fixed timing or Data Ready interrupt for real-time control; delay(100) is for educational display only.
  • Perform the final calibration after assembly in the actual frame and within the product's temperature range.

conclusion

A reliable setup of the MPU6050 is not just about connecting four wires. You should consider chip and module difference, AD0 address, measurement range, bandwidth, output unit, gyro bias and mechanical installation at the same time. The code in this article is a repeatable baseline for six-axis reading; The next step is to estimate the angle, design the Sensor Fusion and calibrate it to fit the actual product.

Frequently asked questions

MPU6050 address is equal to 0x68 or 0x69?

Both are correct. When the AD0 pin is low, the seven-bit address is 0x68 and when AD0 is high, it is 0x69. An I2C scanner is the best way to detect the actual status of the board.

Can the MPU6050 be connected directly to 5V?

The raw chip only accepts VDD of 2.375 to 3.46 volts. Only power a module with 5V for which the manufacturer of the same board has documented the presence of a regulator and logic compatibility; The Adafruit board has this capability.

Why does the gyroscope not show accurate zero at rest?

The gyroscope has zero-rate bias and noise, and the bias changes with temperature. Hold the sensor steady, average a few hundred samples, and perform temperature compensation for an accurate product.

Can MPU6050 give accurate yaw angle or north direction?

Not alone. The MPU6050 does not have a magnetometer; Yaw resulting from the integral of the gyroscope drifts over time. Absolute direction requires external reference and Sensor Fusion.

Is the temperature of the MPU6050 the same as the ambient temperature?

no The temperature output shows the state inside the chip and is more useful for monitoring and compensating the behavior of the IMU; Do not use it instead of an accurate air temperature sensor.

Detailed sources and follow-up

Raw chip numbers are taken from PS-MPU-6000A-00 Rev.3.4 and registers from RM-MPU-6000A-00 Rev.4.2. The 3-5V and 10kOhm pull-up specifications are extended to the Adafruit documentation board only. Obsolete status is monitored from the current TDK Product Center page.

Question and answer article

Ask your technical question

Questions and answers are published after moderation. Authors can see their own pending drafts.

No confirmed questions have been registered for this article yet.