MPU-6050 Акселерометр и Гироскоп
MPU-6050: Основа равновесия
В цикле Sensing-Thinking-Acting этот модуль отвечает за Sensing (Восприятие) собственного тела в пространстве. Как внутреннее ухо человека, MPU6050 сообщает роботу:
- Где низ (вектор гравитации).
- Вращается ли он сейчас и с какой скоростью.
Без этого сенсора невозможно создать балансирующего робота, квадрокоптер или систему стабилизации камеры.
1. Физический уровень
Принцип действия
Внутри чипа находятся микроскопические кремниевые структуры (MEMS):
- Акселерометр: Подпружиненная масса смещается при ускорении, меняя емкость конденсатора. Измеряет линейное ускорение (включая гравитацию $g$).
- Гироскоп: Использует эффект Кориолиса на вибрирующей массе для измерения угловой скорости (градусы в секунду).
Характеристики
- Питание: 3.3V - 5V (обычно на модуле GY-521 есть стабилизатор).
- Интерфейс: I2C.
- Адрес I2C:
0x68(по умолчанию) или0x69(если пин AD0 подключен к VCC). - Диапазоны:
- Акселерометр: ±2g, ±4g, ±8g, ±16g.
- Гироскоп: ±250, ±500, ±1000, ±2000 °/s.
Подключение
| MPU6050 | Arduino Uno | ESP32 | Описание |
|---|---|---|---|
| VCC | 5V | 3.3V/5V | Питание |
| GND | GND | GND | Земля |
| SCL | A5 | D22 | I2C Clock |
| SDA | A4 | D21 | I2C Data |
| INT | D2 | - | Прерывание (опционально) |
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)
- Из акселерометра: Можно вычислить угол через арктангенс вектора гравитации. $$ \text{roll} = \arctan(Y / Z) $$ Проблема: Любое движение робота (ускорение) искажает вектор гравитации.
- Из гироскопа: Можно интегрировать скорость вращения. $$ \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).
🎓 Практика
- Wokwi: Запустить симуляцию MPU6050 (Пример с OLED дисплеем).
- Задание: Попробуйте изменить коэффициент
alphaв комплементарном фильтре.- Поставьте
0.1— угол будет сильно шуметь (как акселерометр). - Поставьте
0.99— угол будет очень плавным, но будет медленно реагировать на реальный наклон.
- Поставьте
