Accelerometer and gyroscope, MPU6050
Six axes over I2C. Drag the board to tip it and the accelerometer follows gravity.
- 8 pins
- 3 properties
Every one of its 8 pins
What it does
The MPU6050 is a three-axis accelerometer and a three-axis gyroscope on one chip, usually sold on the GY-521 board with its own I2C pull-ups. At rest, the accelerometer measures gravity, so the angle the board is tilted at is the arctangent of two of its readings; the gyroscope measures how fast the board is turning, and sits at zero whenever it is still. Mokxi’s part is the register file a driver talks to, at 0x68 or 0x69, and it keeps the detail that trips up hand-written drivers: the chip powers up asleep, with every measurement reading zero until the sleep bit is cleared. WHO_AM_I reads 0x68 at either address. The ranges are the datasheet’s four and four. Drag the board on the canvas to tip it. The motion processor’s own firmware is not modeled, and the chip is perfectly calibrated where a real one has offsets to subtract.
How to use the MPU6050 with an Arduino
SCL to A5, SDA to A4, VCC and GND to the rails; the GY-521 board has its own pull-ups. Before anything else, wake the chip: it powers up asleep and every measurement reads zero until register 0x6B is written with 0. Then read the fourteen data bytes from 0x3B in one burst, so the axes all come from the same sample.
Flat and still, the accelerometer reads 0, 0 and 1 g. The tilt angle is the arctangent of two of those readings; the gyro reads how fast the board is turning, not where it points.
The same register reads work on an ESP32 or a Pico on their own I2C pins.
#include <Wire.h>
void setup() {
Wire.begin();
Wire.beginTransmission(0x68);
Wire.write(0x6B); // PWR_MGMT_1
Wire.write(0x00); // clear SLEEP
Wire.endTransmission();
}The 3 properties you can set
What is true about the Accelerometer and gyroscope, MPU6050, here
The MPU6050, and the two things everybody hits
A three-axis accelerometer and a three-axis gyroscope in one chip, on the little purple GY-521 board. The bus part is easy; the register map is the work.
It powers up asleep. PWR_MGMT_1 (0x6B) reads 0x40 after reset (the
SLEEP bit), and until it is cleared every measurement register reads zero. No
error, no complaint: a perfectly steady nothing, which is worse than a crash.
Every driver's begin() writes 0 there first.
WHO_AM_I is 0x68 whatever the address is. The register holds bits 6:1 of
the address, and AD0 is bit 0. So a board strapped to 0x69 still identifies
as 0x68, and a driver that compares WHO_AM_I against the address it is using
fails on exactly the board somebody had to strap.
After that it is arithmetic. ACCEL_CONFIG bits 4:3 and GYRO_CONFIG bits 4:3
pick the ranges, and the counts per unit are on the datasheet:
| bits | accelerometer | counts per g | bits | gyroscope | counts per deg/s | |
|---|---|---|---|---|---|---|
| 0 | +/-2 g | 16384 | 0 | +/-250 deg/s | 131 | |
| 1 | +/-4 g | 8192 | 1 | +/-500 deg/s | 65.5 | |
| 2 | +/-8 g | 4096 | 2 | +/-1000 deg/s | 32.8 | |
| 3 | +/-16 g | 2048 | 3 | +/-2000 deg/s | 16.4 |
Every reading is a signed 16-bit number, high byte first, and it saturates at the end of the scale rather than wrapping, which is the whole argument for the wider ranges.
Not modeled
Clock stretching, which none of these three chips does anyway. Arbitration between two masters. Ten-bit addressing. And the rate: the parts decode the bus from its edges and impose no timing of their own, so a driver that is too fast works here where a real device would not answer.
Arduino I2C LCD not working uses a scanner and Wire.endTransmission() to tell a wiring fault from a wrong address.
From Two wires, several chips, in full.
See the Accelerometer and gyroscope, MPU6050 in a project
Shown here on: Arduino Uno R3
Where it turns up in a lesson
The rest of the bench
Every one of these is drawn and simulated the same way.
Wire up the Accelerometer and gyroscope, MPU6050
Open the editor and push it into the breadboard. It is free, and it runs on your own machine.