Accelerometer
Interfacing MPU-6500 Accelerometer and Gyroscope with ESP32
Interfacing MPU-6500 Accelerometer and Gyroscope with ESP32 demonstrates how an MPU-6500 motion sensor can be interfaced with an ESP32 board using the I²C communication protocol.
The MPU-6500 contains a 3-axis accelerometer and a 3-axis gyroscope. It can be used to measure acceleration, angular velocity and sensor temperature.
The ESP32 communicates with the MPU-6500 through the I²C bus.
ESP32 → I²C → MPU-6500 → Acceleration / Gyroscope / Temperature
Objectives
- To study the working of the MPU-6500 sensor.
- To interface the MPU-6500 with the ESP32 using I²C communication.
- To read acceleration values along the X, Y and Z axes.
- To read gyroscope values along the X, Y and Z axes.
- To read the temperature value from the MPU-6500.
- To verify the identity of the connected MPU-6500 sensor.
Hardware Modules
- ESP32 Board
- MPU-6500 Accelerometer and Gyroscope Module
- PC / Laptop
- USB Cable
- Connecting wires
Software
- Arduino IDE
- ESP32 Board Package
Theory
MPU-6500
The MPU-6500 is a motion-tracking sensor that contains:
- 3-axis accelerometer
- 3-axis gyroscope
- Temperature sensor
The sensor communicates with the ESP32 using the I²C communication protocol.
The MPU-6500 provides measurements along three axes:
| Axis | Accelerometer | Gyroscope |
|---|---|---|
| X-axis | Acceleration along X-axis | Angular velocity around X-axis |
| Y-axis | Acceleration along Y-axis | Angular velocity around Y-axis |
| Z-axis | Acceleration along Z-axis | Angular velocity around Z-axis |
MPU-6500 → X, Y, Z Axis Measurements
Accelerometer
An accelerometer measures acceleration along the three axes.
The accelerometer values are represented as:
- AX – X-axis acceleration
- AY – Y-axis acceleration
- AZ – Z-axis acceleration
In the program, the default accelerometer range is:
±2g
For the ±2g range, the sensitivity is approximately:
16384 LSB/g
Therefore, the raw accelerometer values are converted into acceleration in units of g using:
Acceleration = Raw Value / 16384.0
For example:
Accel X = ax / 16384.0
Gyroscope
The gyroscope measures angular velocity around the three axes.
The gyroscope values are represented as:
- GX – angular velocity around X-axis
- GY – angular velocity around Y-axis
- GZ – angular velocity around Z-axis
In the program, the default gyroscope range is:
±250 degrees/second
The sensitivity for this range is approximately:
131 LSB/(degrees/second)
The raw gyroscope values are converted using:
Angular Velocity = Raw Value / 131.0
For example:
Gyro X = gx / 131.0
Temperature Sensor
The MPU-6500 also contains an internal temperature sensor.
The raw temperature value is read from the temperature registers and converted into degrees Celsius using the formula:
Temperature = (Raw Temperature / 333.87) + 21.0
The calculated temperature is displayed on the Serial Monitor.
I²C Communication
The MPU-6500 communicates with the ESP32 using the I²C protocol.
The I²C bus uses two communication lines:
- SDA – Serial Data
- SCL – Serial Clock
In this program, the ESP32 uses:
| I²C Signal | ESP32 GPIO | Function |
|---|---|---|
| SDA | GPIO 21 | Serial data |
| SCL | GPIO 22 | Serial clock |
The I²C communication is initialized using:
Wire.begin(21, 22);
MPU-6500 I²C Address
The MPU-6500 is accessed using the I²C address:
0x68
The address is defined in the program using:
#define MPU_ADDR 0x68
The ESP32 uses this address when reading from and writing to the MPU-6500 registers.
MPU-6500 Registers
The program communicates directly with the MPU-6500 registers.
Important registers used in this practical are:
| Register | Address | Function |
|---|---|---|
| PWR_MGMT_1 | 0x6B | Power management / wake-up |
| ACCEL_XOUT_H | 0x3B | Accelerometer X-axis data |
| GYRO_XOUT_H | 0x43 | Gyroscope X-axis data |
| WHO_AM_I | 0x75 | Sensor identification |
The sensor data registers contain high and low bytes that are combined to form a signed 16-bit value.
Sensor Wake-Up
After starting communication, the program writes:
writeRegister(PWR_MGMT_1, 0x01);
This configures the power management register and wakes the sensor for operation.
A short delay is provided after this operation before reading sensor data.
WHO_AM_I Identification
The MPU-6500 contains a WHO_AM_I register at address 0x75.
The program reads this register to check whether the expected sensor is connected.
The expected identification value in the program is:
WHO_AM_I = 0x70
If the value is 0x70, the Serial Monitor displays:
MPU-6500 Found!
Otherwise, the program displays:
Unknown sensor!
Connections
| Device | Pin | ESP32 | Function |
|---|---|---|---|
| MPU-6500 | VCC | 3.3V | Power supply |
| MPU-6500 | GND | GND | Ground |
| MPU-6500 | SDA | GPIO 21 | I²C data |
| MPU-6500 | SCL | GPIO 22 | I²C clock |
Note: Use the appropriate supply voltage specified for the MPU-6500 module being used. While connecting to Vcc of Accelerometer, try 3.3V first, if it doesn't work then try 5V

Steps for Assembling the Circuit
- Connect the VCC pin of the MPU-6500 module to the appropriate supply of the ESP32.
- Connect the GND pin of the MPU-6500 module to GND of the ESP32.
- Connect the SDA pin of the MPU-6500 to GPIO 21 of the ESP32.
- Connect the SCL pin of the MPU-6500 to GPIO 22 of the ESP32.
- Check all connections before applying power.
- Connect the ESP32 to the PC/Laptop using a USB cable.
Safety Precautions
- First, make all connections according to the circuit diagram.
- Check the MPU-6500 supply voltage before connecting it to the ESP32.
- Ensure that SDA and SCL are connected to the correct GPIO pins.
- Ensure that the I²C connections are properly connected.
- Check the ground connection between the ESP32 and MPU-6500.
- Do not apply an incorrect voltage to the sensor module.
- Then connect the ESP32 board to the PC/Laptop.
Schematic Diagram
The MPU-6500 is connected to the ESP32 using the I²C interface.
ESP32 GPIO 21 (SDA) → MPU-6500 SDA
ESP32 GPIO 22 (SCL) → MPU-6500 SCL
The ESP32 communicates with the MPU-6500 at I²C address 0x68.
Interfacing Diagram Using Breadboard
The MPU-6500 module can be connected to the ESP32 using a breadboard and jumper wires.
The required connections are:
| MPU-6500 | ESP32 |
|---|---|
| VCC | 3.3V |
| GND | GND |
| SDA | GPIO 21 |
| SCL | GPIO 22 |
Procedure
- Start the Arduino IDE.
- Connect the MPU-6500 to the ESP32 according to the connection table.
- Write or enter the program.
- Save and compile the program.
- Connect the ESP32 to the PC/Laptop using a USB cable.
- Upload the program to the ESP32.
- Open the Serial Monitor.
- Set the Serial Monitor baud rate to 115200.
- Observe the MPU-6500 identification message.
- Observe the accelerometer, gyroscope and temperature values.
Algorithm
The following algorithm is used to interface the MPU-6500 with the ESP32:
- Start the Arduino IDE.
- Include the Wire library for I²C communication.
- Define the MPU-6500 I²C address as 0x68.
- Define the required MPU-6500 register addresses.
- Start Serial communication at 115200 baud.
- Initialize I²C communication using GPIO 21 as SDA and GPIO 22 as SCL.
- Wake up the MPU-6500 by writing to the power management register.
- Read the WHO_AM_I register.
- Check whether the returned identification value is 0x70.
- Read the raw accelerometer values for the X, Y and Z axes.
- Read the raw gyroscope values for the X, Y and Z axes.
- Read the raw temperature value.
- Convert the accelerometer values into g.
- Convert the gyroscope values into degrees/second.
- Convert the raw temperature value into degrees Celsius.
- Display all values on the Serial Monitor.
- Wait for 200 ms.
- Repeat the process continuously.
The overall operation is:
MPU-6500 → I²C → ESP32 → Sensor Data Processing → Serial Monitor
Working
The ESP32 communicates with the MPU-6500 using the I²C protocol.
The I²C communication is initialized with:
Wire.begin(21, 22);
GPIO 21 is used as the SDA line and GPIO 22 is used as the SCL line.
The MPU-6500 is accessed at I²C address 0x68.
First, the ESP32 wakes the sensor by writing to the PWR_MGMT_1 register.
The ESP32 then reads the WHO_AM_I register to verify the sensor identity.
After the sensor is verified, the ESP32 reads the raw accelerometer, gyroscope and temperature data.
The raw accelerometer values are converted into g.
Raw Accelerometer → Acceleration in g
The raw gyroscope values are converted into degrees/second.
Raw Gyroscope → Angular Velocity in °/s
The raw temperature value is converted into degrees Celsius.
Raw Temperature → Temperature in °C
All calculated values are displayed on the Serial Monitor every 200 ms.
Data Conversion
The program uses the following conversion formulas:
| Parameter | Conversion | Unit |
|---|---|---|
| Accelerometer X | ax / 16384.0 | g |
| Accelerometer Y | ay / 16384.0 | g |
| Accelerometer Z | az / 16384.0 | g |
| Gyroscope X | gx / 131.0 | degrees/second |
| Gyroscope Y | gy / 131.0 | degrees/second |
| Gyroscope Z | gz / 131.0 | degrees/second |
| Temperature | (tempRaw / 333.87) + 21.0 | °C |
Program
#include <Wire.h>
#define MPU_ADDR 0x68
// MPU-6500 registers
#define PWR_MGMT_1 0x6B
#define ACCEL_XOUT_H 0x3B
#define GYRO_XOUT_H 0x43
#define WHO_AM_I 0x75
void writeRegister(byte reg, byte value)
{
Wire.beginTransmission(MPU_ADDR);
Wire.write(reg);
Wire.write(value);
Wire.endTransmission();
}
int16_t read16(byte reg)
{
Wire.beginTransmission(MPU_ADDR);
Wire.write(reg);
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 2);
int16_t value = 0;
if (Wire.available() >= 2)
{
value = (Wire.read() << 8) | Wire.read();
}
return value;
}
void setup()
{
Serial.begin(115200);
delay(1000);
Wire.begin(21, 22);
Serial.println("MPU-6500 Test");
// Wake up sensor
writeRegister(PWR_MGMT_1, 0x01);
delay(100);
// Check identity
Wire.beginTransmission(MPU_ADDR);
Wire.write(WHO_AM_I);
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 1);
if (Wire.available())
{
byte id = Wire.read();
Serial.print("WHO_AM_I: 0x");
Serial.println(id, HEX);
if (id == 0x70)
Serial.println("MPU-6500 Found!");
else
Serial.println("Unknown sensor!");
}
}
void loop()
{
int16_t ax = read16(0x3B);
int16_t ay = read16(0x3D);
int16_t az = read16(0x3F);
int16_t gx = read16(0x43);
int16_t gy = read16(0x45);
int16_t gz = read16(0x47);
int16_t tempRaw = read16(0x41);
// Default ranges:
// Accelerometer = ±2g
// Gyroscope = ±250 deg/s
float accelX = ax / 16384.0;
float accelY = ay / 16384.0;
float accelZ = az / 16384.0;
float gyroX = gx / 131.0;
float gyroY = gy / 131.0;
float gyroZ = gz / 131.0;
// MPU-6500 temperature formula
float temperature = (tempRaw / 333.87) + 21.0;
Serial.print("AX: ");
Serial.print(accelX, 2);
Serial.print(" AY: ");
Serial.print(accelY, 2);
Serial.print(" AZ: ");
Serial.print(accelZ, 2);
Serial.print(" GX: ");
Serial.print(gyroX, 2);
Serial.print(" GY: ");
Serial.print(gyroY, 2);
Serial.print(" GZ: ");
Serial.print(gyroZ, 2);
Serial.print(" Temp: ");
Serial.println(temperature, 2);
delay(200);
}
Observation
Open the Serial Monitor and set the baud rate to 115200.
Initially, the program displays the MPU-6500 test message and checks the sensor identity.
A valid sensor produces:
WHO_AM_I: 0x70 MPU-6500 Found!
The Serial Monitor then displays the sensor measurements in the following format:
AX: x.xx AY: x.xx AZ: x.xx GX: x.xx GY: x.xx GZ: x.xx Temp: xx.xx
When the sensor is moved or rotated, the accelerometer and gyroscope values change accordingly.
The temperature value is also displayed continuously.
The readings are updated every 200 ms.
Result
The ESP32 successfully interfaces with the MPU-6500 using I²C communication.
The ESP32 successfully reads and displays:
- X-axis acceleration
- Y-axis acceleration
- Z-axis acceleration
- X-axis angular velocity
- Y-axis angular velocity
- Z-axis angular velocity
- Sensor temperature
The MPU-6500 identity is also verified using the WHO_AM_I register before sensor measurements are displayed.