Skip to main content

MPU-6050 Акселерометр и Гироскоп

MPU-6050: Основа равновесия

В цикле Sensing-Thinking-Acting этот модуль отвечает за Sensing (Восприятие) собственного тела в пространстве. Как внутреннее ухо человека, MPU6050 сообщает роботу:

  1. Где низ (вектор гравитации).
  2. Вращается ли он сейчас и с какой скоростью.

Без этого сенсора невозможно создать балансирующего робота, квадрокоптер или систему стабилизации камеры.


1. Физический уровень

Принцип действия

Внутри чипа находятся микроскопические кремниевые структуры (MEMS):

  • Акселерометр: Подпружиненная масса смещается при ускорении, меняя емкость конденсатора. Измеряет линейное ускорение (включая гравитацию $g$).
  • Гироскоп: Использует эффект Кориолиса на вибрирующей массе для измерения угловой скорости (градусы в секунду).

Характеристики

  • Питание: 3.3V - 5V (обычно на модуле GY-521 есть стабилизатор).
  • Интерфейс: I2C.
  • Адрес I2C: 0x68 (по умолчанию) или 0x69 (если пин AD0 подключен к VCC).
  • Диапазоны:
    • Акселерометр: ±2g, ±4g, ±8g, ±16g.
    • Гироскоп: ±250, ±500, ±1000, ±2000 °/s.

Подключение

MPU6050Arduino UnoESP32Описание
VCC5V3.3V/5VПитание
GNDGNDGNDЗемля
SCLA5D22I2C Clock
SDAA4D21I2C Data
INTD2-Прерывание (опционально)

2. Драйверный уровень

Мы используем библиотеку Adafruit MPU6050, которая берет на себя общение с регистрами датчика по шине I2C.

Установка библиотеки

В Arduino IDE: Sketch -> Include Library -> Manage Libraries… -> “Adafruit MPU6050”

Базовый код (Считывание сырых данных)

#include <Adafruit_MPU6050.h>
#include <Adafruit_Sensor.h>
#include <Wire.h>

Adafruit_MPU6050 mpu;

void setup(void) {
  Serial.begin(115200);

  // Инициализация
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) { delay(10); }
  }
  Serial.println("MPU6050 Found!");

  // Настройка чувствительности (Driver Layer configuration)
  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
}

void loop() {
  /* Get new sensor events with the readings */
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);

  /* Вывод сырых данных (Sensing) */
  Serial.print("Accel X: "); Serial.print(a.acceleration.x);
  Serial.print(", Y: "); Serial.print(a.acceleration.y);
  Serial.print(", Z: "); Serial.print(a.acceleration.z);
  Serial.println(" m/s^2");

  Serial.print("Rotation X: "); Serial.print(g.gyro.x);
  Serial.print(", Y: "); Serial.print(g.gyro.y);
  Serial.print(", Z: "); Serial.print(g.gyro.z);
  Serial.println(" rad/s");

  delay(500);
}

3. Прикладной уровень

Сырые данные мало полезны для управления. Акселерометр “шумит” от вибраций моторов, а гироскоп накапливает ошибку (дрейф). На уровне Thinking мы должны объединить их данные.

Задача: Определение угла наклона (Pitch & Roll)

  1. Из акселерометра: Можно вычислить угол через арктангенс вектора гравитации. $$ \text{roll} = \arctan(Y / Z) $$ Проблема: Любое движение робота (ускорение) искажает вектор гравитации.
  2. Из гироскопа: Можно интегрировать скорость вращения. $$ \text{angle} = \text{angle} + \text{gyro\_rate} \times \Delta t $$ Проблема: Ошибка накапливается со временем (дрейф).

Решение: Комплементарный фильтр (Sensor Fusion)

Самый простой и эффективный алгоритм для Arduino. Мы доверяем гироскопу на коротких промежутках времени, а акселерометру — на длинных (для коррекции дрейфа).

// Глобальные переменные
float angle_x = 0;
float alpha = 0.96; // Коэффициент доверия гироскопу (0.0 - 1.0)

void loop() {
  sensors_event_t a, g, temp;
  mpu.getEvent(&a, &g, &temp);
  
  // 1. Расчет угла из акселерометра (Thinking: Geometry)
  // Используем atan2 для корректной работы во всех квадрантах
  float angle_acc = atan2(a.acceleration.y, a.acceleration.z) * 180 / PI;
  
  // 2. Интеграция гироскопа (Thinking: Calculus)
  // g.gyro.x в радианах/сек, переводим в градусы
  float gyro_rate = g.gyro.x * 180 / PI;
  float dt = 0.01; // Примерное время цикла (в реальном коде используйте millis())
  
  // 3. Комплементарный фильтр (Thinking: Fusion)
  // Формула: Угол = (Интеграл гироскопа) * alpha + (Акселерометр) * (1 - alpha)
  angle_x = alpha * (angle_x + gyro_rate * dt) + (1.0 - alpha) * angle_acc;
  
  Serial.print("Filtered Angle X: "); 
  Serial.println(angle_x);
  
  delay(10);
}

Теперь переменная angle_x — это чистый, стабильный угол наклона, который можно подавать в PID-регулятор для балансировки робота (Acting).


🎓 Практика

  1. Wokwi: Запустить симуляцию MPU6050 (Пример с OLED дисплеем).
  2. Задание: Попробуйте изменить коэффициент alpha в комплементарном фильтре.
    • Поставьте 0.1 — угол будет сильно шуметь (как акселерометр).
    • Поставьте 0.99 — угол будет очень плавным, но будет медленно реагировать на реальный наклон.