Компонент · Датчик
MPU-6050 IMU
MPU-6050 — 6-осевой IMU, измеряющий наклон, вращение и ускорение по I²C; так робот определяет собственную ориентацию для балансировки и поворотов.
Что это такое
MPU-6050 позволяет роботу ощущать собственное движение. Это 6-осевой инерциальный измерительный модуль — гироскоп и акселерометр на одной микросхеме, — сообщающий о наклоне робота, скорости вращения и ускорении. Если ультразвуковой датчик смотрит наружу на мир, то IMU смотрит внутрь на собственный корпус робота, что необходимо самостоятельно балансирующемуся роботу или системе счисления пройденного пути.
Как это работает
Внутри находятся два датчика. Акселерометр измеряет линейное ускорение по X, Y и Z: в покое это просто тяжесть, которая показывает роботу направление вниз и наклон. Гироскоп измеряет скорость вращения робота вокруг каждой оси. Оба датчика считываются по I²C (SCL/SDA).
Ни один датчик сам по себе не достаточен: после интегрирования гироскопа для получения угла результат медленно дрейфует, а при движении робота показания акселерометра становятся шумными. Решение — объединение данных датчиков: их сигналы смешиваются так, что акселерометр корректирует дрейф гироскопа, а гироскоп сглаживает шум акселерометра. Именно этой технике посвящено руководство шум, смещение и фильтрация датчиков.
Когда его следует использовать
Выбирайте MPU-6050, когда роботу нужно знать собственную ориентацию или движение:
- Самостоятельно балансирующиеся роботы — угол наклона, с которым контур регулирования стремится удерживать равновесие.
- Курс и счисление пути — определение поворотов для улучшения одометрии между отсчётами энкодеров.
- Обнаружение движения и жесты — реакция на подъём, наклон или встряхивание.
Для измерения расстояния до объектов, например стен или препятствий, нужен дальномер вроде HC-SR04 или VL53L0X: IMU воспринимает робота, а не мир.
Подключение и важные нюансы
- I²C, 3.3–5 V. У большинства плат расширения, включая фиолетовую GY-521, есть регулятор, поэтому подходит 5 V; исходной микросхеме нужно только 3.3 V.
- Объединяйте данные гироскопа и акселерометра: нельзя управлять по одному сырому измерению. Единственный отсчёт акселерометра при движении непригоден как угол наклона.
- Курс дрейфует без магнитометра; используйте MPU-6050 для тангажа, крена и поворотов на коротком интервале, но не для абсолютного курса по компасу.
- Устанавливайте жёстко и горизонтально; свободный датчик добавляет вибрацию, которую фильтр не сможет устранить.
Расположение выводов
Фиолетовая плата расширения GY-521 обычно подразумевается под названием «MPU-6050». Она имеет восемь выводов, причём четыре из них обычно не подключают.
| Вывод | Название | Назначение | Обычно |
|---|---|---|---|
| 1 | VCC | Питание. Регулятор платы принимает 3.3–5 V; исходной микросхеме нужно только 3.3 V | 5 V на Uno, 3.3 V на ESP32 |
| 2 | GND | Земля, общая с микроконтроллером | Подключено |
| 3 | SCL | Тактовый сигнал I²C | A5 на Uno |
| 4 | SDA | Данные I²C | A4 на Uno |
| 5 | XDA | Вспомогательные данные I²C — для магнитометра, который MPU считывает по поручению | Оставлен открытым |
| 6 | XCL | Вспомогательные тактовые сигналы I²C | Оставлен открытым |
| 7 | AD0 | Выбор адреса. LOW (по умолчанию) = 0x68, HIGH = 0x69 |
Оставлен открытым или соединён вверх для второго датчика |
| 8 | INT | Выход прерывания — срабатывает при готовности данных, движении или свободном падении | Оставлен открытым, пока не требуется отказ от опроса |
AD0 позволяет использовать два MPU-6050 на одной шине и даёт простое решение конфликта адресов, которого нет у большинства датчиков.
Подключение к Arduino
| MPU-6050 | Arduino Uno | ESP32 | Примечание |
|---|---|---|---|
| VCC | 5 V | 3.3 V | Встроенный регулятор поддерживает оба напряжения |
| GND | GND | GND | Должна быть общей со всеми остальными цепями |
| SCL | A5 | GPIO 22 | Не добавляйте внешние подтяжки — на плате уже есть 2.2 kΩ |
| SDA | A4 | GPIO 21 | То же |
| AD0 | — | — | Соединять с VCC только для второго датчика |
На Arduino 5 V есть тонкость. Подтягивающие резисторы GY-521 подключены к регулируемой шине 3.3 V, поэтому линии I²C находятся в покое на 3.3 V, а не 5 V. ATmega328P считает высокий уровень выше 0.6 × Vcc = 3.0 V, поэтому 3.3 V с запасом проходит порог, но лишь на 0.3 V. На практике это работает надёжно, и именно поэтому длинная или шумная линия I²C на этой плате начинает вести себя хуже, чем на плате 5 V.
Чтение: важные регистры
Датчиком можно управлять через библиотеку и вообще не видеть регистры, но четыре из них объясняют почти все возникающие проблемы.
| Регистр | Адрес | Почему важен |
|---|---|---|
PWR_MGMT_1 |
0x6B |
После включения микросхема спит. Запишите сюда 0, иначе все показания равны нулю |
WHO_AM_I |
0x75 |
Возвращает 0x68 — самый быстрый способ проверить подключение |
GYRO_CONFIG |
0x1B |
Диапазон: ±250, ±500, ±1000, ±2000 °/s |
ACCEL_CONFIG |
0x1C |
Диапазон: ±2, ±4, ±8, ±16 g |
ACCEL_XOUT_H |
0x3B |
Начало 14 байт: 6 для ускорения, 2 для температуры, 6 для гироскопа — считывайте одним пакетом |
Два конфигурационных регистра задают масштабный коэффициент, на который делятся сырые отсчёты. Ошибка здесь — самая частая причина сообщения «мои углы в четыре раза больше»:
| Настройка диапазона | LSB гироскопа на °/s | Настройка диапазона | LSB акселерометра на g |
|---|---|---|---|
| ±250 °/s (по умолчанию) | 131 | ±2 g (по умолчанию) | 16384 |
| ±500 °/s | 65.5 | ±4 g | 8192 |
| ±1000 °/s | 32.8 | ±8 g | 4096 |
| ±2000 °/s | 16.4 | ±16 g | 2048 |
Выбирайте наименьший диапазон, который не приводит к насыщению. Балансирующийся робот редко превышает ±250 °/s, а узкий диапазон бесплатно даёт в четыре раза больше разрешения, чем ±1000 °/s.
Минимальный рабочий код
Библиотека не нужна: вот весь код, и его стоит один раз запустить, чтобы понимать, что она делает.
#include <Wire.h>
const uint8_t MPU = 0x68; // 0x69 if AD0 is tied high
void setup() {
Serial.begin(115200);
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B); // PWR_MGMT_1
Wire.write(0); // wake up — the chip boots asleep
Wire.endTransmission(true);
}
void loop() {
Wire.beginTransmission(MPU);
Wire.write(0x3B); // ACCEL_XOUT_H
Wire.endTransmission(false); // repeated start, do not release the bus
Wire.requestFrom(MPU, (uint8_t)14);
int16_t ax = Wire.read() << 8 | Wire.read();
int16_t ay = Wire.read() << 8 | Wire.read();
int16_t az = Wire.read() << 8 | Wire.read();
Wire.read(); Wire.read(); // temperature, discarded here
int16_t gx = Wire.read() << 8 | Wire.read();
int16_t gy = Wire.read() << 8 | Wire.read();
int16_t gz = Wire.read() << 8 | Wire.read();
// Default ranges: +/-2 g and +/-250 deg/s
float pitch = atan2(ax, sqrt((float)ay * ay + (float)az * az)) * 57.2958f;
float rateY = gy / 131.0f; // deg/s
Serial.print(pitch); Serial.print(' '); Serial.println(rateY);
delay(20);
}
Две вещи намеренно не делает этот код: не объединяет два датчика и не вычитает смещение. Оба действия описаны далее.
Калибровка: двадцать важнейших строк
В покое гироскоп показывает не ноль, а небольшое почти постоянное смещение. Поскольку угол получают интегрированием гироскопа, это смещение интегрируется в постоянно растущую ошибку. Несложенное смещение 2 °/s даёт дрейф 120° уже через минуту.
Усредните несколько сотен отсчётов при полной неподвижности датчика, затем вычитайте:
long sum = 0;
for (int i = 0; i < 500; i++) { sum += readGyroY(); delay(3); }
const float gyroBias = sum / 500.0f; // subtract from every later reading
Три практических замечания, которых не даст техническое описание:
- Выполняйте при каждом включении, а не один раз. Смещение гироскопа меняется с температурой, и робот через десять минут работы уже не тот, который откалиброван на холоде.
- «Неподвижно» означает действительно неподвижно. Калибровка при опоре на стол навсегда впечатает это движение в смещение.
- Акселерометру нужна не нулевая, а уровневая опора. На оси, направленной вниз, он должен показывать 1 g. Если показание равно 0.97 g, это ошибка масштаба, проявляющаяся как постоянное отклонение наклона на несколько градусов.
Почему одного датчика никогда недостаточно
Два датчика отказывают строго противоположными способами, и именно поэтому их объединение так эффективно.
| Акселерометр | Гироскоп | |
|---|---|---|
| Измеряет | Линейное ускорение — в покое тяжесть | Скорость вращения |
| Даёт наклон с помощью | Тригонометрии по вектору тяжести | Интегрирования скорости по времени |
| На коротком интервале | Шумный — каждый толчок и вибрация тоже ускорение | Отличный, плавный, отзывчивый |
| На длинном интервале | В среднем верен — тяжесть не дрейфует | Неограниченно дрейфует из-за интегрирования смещения |
| Отказывает | Когда робот ускоряется, поэтому «вниз» перестаёт быть вниз | Всегда и медленно |
Комплементарный фильтр берёт удачную часть каждого сигнала: доверяет гироскопу на коротком интервале и позволяет акселерометру медленно возвращать оценку к истинному значению:
angle = 0.98f * (angle + rate * dt) + 0.02f * accelAngle;
Коэффициент 0.98 задаёт частоту разделения. Большее значение дольше доверяет гироскопу, что повышает плавность, но увеличивает дрейф; меньшее сильнее реагирует на шум акселерометра. Руководство комплементарного фильтра объясняет, как выбирать его осознанно, а не на глаз.
Диагностика
| Симптом | Вероятная причина | Исправление |
|---|---|---|
| Каждое показание равно 0 | Микросхема всё ещё спит | Записать 0 в PWR_MGMT_1 (0x6B) после Wire.begin() |
| Сканер шины ничего не находит | Взят 8-разрядный адрес из технического описания | Адрес 0xD0 из описания равен 0x68, сдвинутому влево; использовать 0x68 |
| Из двух датчиков виден только один | Оба используют адрес по умолчанию | Соединить AD0 одной платы с VCC, чтобы она отвечала по 0x69 |
| Углы в 4× или 8× больше | Масштабный коэффициент не соответствует диапазону | Согласовать делитель с GYRO_CONFIG/ACCEL_CONFIG |
| Угол постоянно дрейфует даже в покое | Смещение гироскопа не откалибровано | Усреднить 500 неподвижных отсчётов при загрузке и вычесть |
| Наклон скачет во время движения | Используется сырой угол акселерометра | Объединить с гироскопом; у движущегося робота «вниз» не вниз |
| Показания замирают через некоторое время | Зависла шина I²C | Проверить подтяжки; добавить восстановление шины девяти тактовыми импульсами SCL |
| Курс медленно вращается бесконечно | У рыскания нет абсолютной опоры | Ожидаемо — для курса нужен магнитометр или другой абсолютный источник |
| Сильный шум при вибрации выше примерно 1 kHz | Жёсткое крепление передаёт вибрацию двигателей | Установить датчик через мягкие элементы; включить встроенный DLPF через CONFIG (0x1A) |
MPU-6050 или более новая деталь?
MPU-6050 снят с производства производителем, но остаётся самым распространённым IMU в хобби-робототехнике, поскольку дёшев, подробно описан и поддерживается всеми библиотеками.
| Деталь | Оси | Отличие | Когда выбирать |
|---|---|---|---|
| MPU-6050 | 6 | Вариант по умолчанию; огромное количество примеров | Обучение, балансировка, любой первый проект с IMU |
| MPU-9250 | 9 | Добавлен магнитометр, поэтому у рыскания есть абсолютная опора | Нужен курс по компасу, а не только скорость вращения |
| ICM-20948 | 9 | Текущий преемник MPU-9250 | Новые конструкции с 9 осями и долгосрочной доступностью |
| BNO055 | 9 | Объединение выполняется на микросхеме, ориентация выдаётся напрямую | Нужен угол без написания фильтра — по цене в несколько раз выше |
| LSM6DS3 | 6 | Современная, доступная деталь с меньшим шумом | Взаимозаменяемое улучшение при окончании поставок MPU-6050 |
Честный итог: если роботу нужны тангаж и крен, как при балансировке, MPU-6050 полностью достаточен, и объединение данных полезно написать самостоятельно. Если нужен абсолютный курс, никакая фильтрация не выведет его из шести осей — потребуется магнитометр.
Исследуйте граф
Используется в этих сборках
Проекты, учебные пути и симуляторы, в которых используется MPU-6050 IMU.
- ПроектРобот, удерживающий равновесие, на MPU6050 и ПИД-регуляторе (PID)
- ПроектСоберите Micromouse для прохождения лабиринта
- ПроектСоберите робота на колёсах Mecanum, который едет боком
- ПроектСоберите робота-ровера для путевых точек GPS
- Учебный путьОмнидирекционный привод: движение вбок без поворота
- Учебный путьОсновы электроники роботов: дорожная карта обучения
- Учебный путьПланирование пути и построение карт: от заливки до SLAM
Вопросы
MPU-6050 IMU: частые вопросы
Что такое датчик MPU-6050?
MPU-6050 — 6-осевой инерциальный измерительный модуль (IMU) на небольшой плате расширения. Он объединяет 3-осевой гироскоп и 3-осевой акселерометр, поэтому робот может определять свой наклон, скорость вращения и ускорение; все данные считываются по шине I²C.
Как работает MPU-6050?
Внутри находятся два датчика. Акселерометр измеряет линейное ускорение: в покое это просто тяжесть, которая показывает роботу направление вниз и наклон. Гироскоп измеряет скорость вращения вокруг каждой оси. Данные считываются по I²C, а затем объединяются для получения стабильной ориентации, которую ни один датчик сам по себе не обеспечивает.
Для чего используют MPU-6050?
Для определения собственного движения робота: удержания самостоятельно балансирующегося робота вертикально, оценки курса и улучшения одометрии между отсчётами энкодеров, а также обнаружения наклона, подъёма или встряхивания. Датчик воспринимает самого робота, а не окружающий мир, поэтому дополняет дальномер, а не заменяет его.
Как откалибровать MPU-6050?
В покое гироскоп и акселерометр показывают небольшие ненулевые смещения. Откалибруйте датчик, усреднив несколько сотен отсчётов при полной неподвижности, затем вычитайте эти смещения из каждого измерения. Особенно это необходимо гироскопу: именно неоткалиброванное смещение вызывает быстрое уплывание расчётного угла.
Как подключить MPU-6050 к ESP32 или Arduino?
По I²C: подключите SDA и SCL к выводам I²C платы, а также питание и землю. Фиолетовая плата расширения GY-521 содержит регулятор, поэтому на ESP32 её можно питать от 3.3 V, а на Arduino Uno — от 5 V. Затем библиотека считывает регистры гироскопа и акселерометра.
Дополнительные материалы