Компонент · Датчик

MPU-6050 IMU

MPU-6050 — 6-осевой IMU, измеряющий наклон, вращение и ускорение по I²C; так робот определяет собственную ориентацию для балансировки и поворотов.

Что это такое

MPU-6050 позволяет роботу ощущать собственное движение. Это 6-осевой инерциальный измерительный модуль — гироскоп и акселерометр на одной микросхеме, — сообщающий о наклоне робота, скорости вращения и ускорении. Если ультразвуковой датчик смотрит наружу на мир, то IMU смотрит внутрь на собственный корпус робота, что необходимо самостоятельно балансирующемуся роботу или системе счисления пройденного пути.

Подписанная схема платы расширения MPU-6050 IMU, платы GY-521: фиолетовая печатная плата (PCB) с микросхемой MPU-6050 и пассивными элементами в центре, индикатором осей X/Y/Z, показывающим три направления измерения, и 8-выводным разъёмом (VCC, GND, SCL, SDA, XDA, XCL, AD0, INT) снизу.
Гироскоп и акселерометр на одной микросхеме измеряют вращение и наклон вокруг всех трёх осей; данные считываются по I²C. Скачать SVG

Как это работает

Внутри находятся два датчика. Акселерометр измеряет линейное ускорение по 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.

Вопросы

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. Затем библиотека считывает регистры гироскопа и акселерометра.

Дополнительные материалы

Источники