Measure tilt with an MPU6050 and an Arduino
- 192parts on the bench
- 25boards running now
- 1.00xreal time, on every board
The MPU6050 is a three-axis accelerometer and three-axis gyroscope on one chip, usually sold on the small blue GY-521 board. The circuit above uses it as a tilt meter: an Arduino Uno reads it over I2C, lights a green lamp while it is flat, and a red or blue lamp when it is tipped left or right. The serial monitor prints the raw acceleration, the roll and pitch angles, the gyro rates and the chip’s own temperature.
Open it in the editor and drag the sensor board to tip it. The readings follow gravity, and the gyro follows how fast you are moving it.
What you need
- An Arduino Uno
- An MPU6050 on a GY-521 board
- Red, green and blue LEDs with a 220 ohm resistor each
- A breadboard and jumper wires
Wiring
It powers up asleep
After reset, the MPU6050’s power management register reads 0x40: the sleep bit is set. Until a sketch clears it, every measurement register reads zero. There is no error, no complaint, just a perfectly steady nothing, which is worse than a crash because it looks like a working sensor lying flat and still. Every driver’s first act is to write 0x00 to register 0x6B, and the example prints whether that worked.
The simulated chip powers up asleep too, so forgetting this gives the same steady zeros here as on the bench.
#include <Wire.h>
void setup() {
Serial.begin(9600);
Wire.begin();
Wire.beginTransmission(0x68);
Wire.write(0x6B); // PWR_MGMT_1
Wire.write(0x00); // clear SLEEP
Wire.endTransmission();
}Turning gravity into an angle
An accelerometer sitting still measures gravity and nothing else. Flat on a table, all of gravity is on the Z axis, so the reading is 0, 0 and plus 1 g. Tip it to one side and some of gravity moves onto Y; tip it forward and some moves onto X. The tilt angle is the arctangent of the two components, which is the whole trick behind every spirit level app.
The example reads all fourteen bytes of data in one burst, converts the raw numbers to thousandths of a g, and computes roll from Y and Z and pitch from X and Z. The arctangent comes from a lookup table that is good to about a degree, which is faster and smaller on an Uno than atan2() from the math library, though atan2() works too. Past 12 degrees either way, one of the outer lamps takes over from the green one.
The gyroscope measures something different: how fast the board is rotating, in degrees per second, not where it is pointing. It sits near zero while the board is still and moves only while you are tipping it.
WHO_AM_I and the address
The chip’s address is 0x68, or 0x69 with the AD0 pin pulled high. Its WHO_AM_I register returns 0x68 in both cases, because it holds the address bits without AD0. So a driver that compares WHO_AM_I with the address it is using fails on exactly the board somebody strapped to 0x69. The example prints both, so the difference is visible.
Try it in the editor
Open the circuit in the editor and drag the sensor board to tip it slowly past 12 degrees. The green lamp hands over to red or blue. Change FLAT_DEGREES to 3 and the meter becomes a nervous spirit level; change it to 30 and it only complains about a real tilt.
Watch the gyro numbers in the serial monitor while you drag. They rise while the board is moving and fall back to zero the moment you stop, even though the tilt stays. That is the difference between a rate and a position, and it is why a gyro on its own cannot tell you which way up something is.
Then write a few lines of your own with Wire.h: a transmission to 0x68 with register 0x75, WHO_AM_I, and a one-byte read. It prints 68, the same as a real chip.
Common mistakes
Forgetting to wake it, and getting zeros.
Reading the registers one by one. The six acceleration bytes can change between two separate reads, giving a value made of half of one sample and half of the next. Read the block in one transfer.
Expecting an angle from the gyro alone. Integrating degrees per second over time drifts. Real projects combine the accelerometer and the gyro with a complementary or Kalman filter.
Expecting perfect numbers from real hardware. A real MPU6050 has an offset on every axis until it is calibrated. The simulated one reads clean, which is useful for learning the math and kinder than the bench.
Questions
Do I need a library for the MPU6050?
No. Wire.h compiles here as it stands, and waking and reading the chip is a few register writes and one burst read. The example uses Mokxi’s own MPU6050 helper, which wraps exactly those.
Can I use the MPU6050 with an ESP32?
Yes. The chip runs at 3.3 volts and the same register reads work on the ESP32’s I2C pins.
Does the simulator have the DMP?
No. The motion processor inside the real chip, which runs its own fusion firmware, is not modeled. The raw accelerometer, gyro and temperature registers are.
Build this for real
Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.