# 🛹 Инерциальный измерительный модуль MPU6050 (SensorHub Component)

Профессиональная реализация драйвера IMU (Inertial Measurement Unit) на базе архитектуры **FreeRTOS** для микроконтроллера ESP32. Проект реализует полный цикл обработки: от низкоуровневого чтения сырых регистров до вычисления стабильных углов ориентации в реальном времени.

## 🚀 Основные возможности
- **Многопоточность (Dual-Core FreeRTOS):** Опрос датчика и расчёт фильтров зафиксированы на **Core 0** на частоте **200 Гц**, вывод телеметрии работает асинхронно на **Core 1** — задержки Serial-порта не влияют на точность интегратора.
- **Драйвер Mpu6050Driver:** инкапсуляция логики I2C с Dependency Injection (`TwoWire`). Совместим с неофициальными клонами чипа (без блокирующей проверки `WHO_AM_I`).
- **Автоматическая калибровка:** компенсация статического смещения нуля гироскопа по трём осям при старте.
- **Телеметрия:** углы наклона (**Pitch/Roll**), угол рыскания (**Yaw**), вертикальное ускорение (**Z-Acc**), модуль полной перегрузки (**TotalG**).
- **Потокобезопасность:** обмен данными между ядрами защищён аппаратными мьютексами FreeRTOS (`portENTER_CRITICAL`).
- **Детектор движения и связи:** статусы `MOVING`/`STATIONARY` и `Link: OK`/`LOST` (см. `isAlive()`).

## 📋 Содержание
- [Описание](#описание)
- [Программная архитектура](#программная-архитектура)
- [Работа через CLI](#работа-через-cli)
- [Визуализация](#-визуализация)
- [Схема подключения](WIRING.md)
- [Теория и математика](THEORY.md)
- [План занятия](Lesson.md)
- [Презентация](PREZ.md)

## Описание
MPU6050 — это 6-осевой датчик движения (MEMS), объединяющий 3-осевой гироскоп и 3-осевой акселерометр. Данная реализация преобразует угловые скорости и линейные ускорения в стабильный вектор ориентации. Вся математика оптимизирована под работу с платами, имеющими разворот шелкографии осей (X — вдоль короткой стороны (Крен/Roll), Y — вдоль длинной стороны (Тангаж/Pitch)).

## Программная архитектура
Код спроектирован для бесшовной интеграции в общую экосистему **Sensor Hub**:
- **`include/Mpu6050Driver.h`**: Интерфейс драйвера, структура данных `Data`.
- **`src/Mpu6050Driver.cpp`**: Реализация математики комплементарного фильтра, интегратора оси Z и работы с регистрами шины.
- **`src/main.cpp`**: Высокоуровневая точка входа, конфигурация задач FreeRTOS, расчет перегрузок и асинхронный вывод данных.
- **`tools/*.py`**: живые графические визуализаторы для Serial-вывода (см. раздел "Визуализация").

## Работа через CLI
Для компиляции, прошивки и запуска мониторинга выполните стандартные команды PlatformIO CLI:
```bash
cd "Components/2.MPU6050"
# Сборка и прошивка в ESP32
pio run -t upload && pio device monitor
```

Данные выводятся в терминал в формате, удобном как для чтения человеком, так и для парсинга утилитой **Serial Plotter** (Arduino IDE / PlatformIO):
`Pitch:0.0,Roll:0.0,Yaw:0.0,Z-Acc:1.00,TotalG:1.00 | Status:STATIONARY | Link:OK`

---
*Примечание: при калибровке гироскопа (первые ~2.5 секунды после включения питания) датчик должен оставаться абсолютно неподвижным для корректного расчёта смещения нуля.*

## 📊 Визуализация

Serial Plotter показывает голые числа — для урока нагляднее живая картинка.
`tools/` содержит три скрипта на matplotlib, которые парсят тот же текстовый
вывод прошивки и рисуют его в реальном времени:

| Скрипт | Что показывает | Какой урок из `Lesson.md` иллюстрирует |
|--------|-----------------|------------------------------------------|
| `orientation_cube.py` | 3D-куб, поворачивающийся по Pitch/Roll/Yaw | Урок 2 (маятник), Урок 3 (проекции вектора), Урок 4 (Gimbal Lock) |
| `g_force_view.py` | Лента `TotalG` с подсветкой невесомости/удара | Урок 1 (невесомость и перегрузка) |
| `yaw_drift_view.py` | График накопленного отклонения `Yaw` во времени | Урок 5 (накопление погрешности интегратора) |

```bash
cd tools
pip install -r requirements.txt
python3 orientation_cube.py /dev/ttyUSB0   # или g_force_view.py / yaw_drift_view.py
```

Serial Monitor/Serial Plotter прошивки на момент запуска скрипта должен быть
закрыт — иначе порт занят и Python не сможет его открыть.

## 📝 Параметры телеметрии

Что означает каждое поле в строке вывода и где похожая физика встречается за пределами лаборатории:

### 1. `Pitch` (Тангаж / Наклон вперёд-назад)
*   **Тип данных:** `float`, диапазон `-180.0` … `180.0` градусов.
*   **Физический смысл:** угол наклона платы вокруг её оси Y (вдоль длинной стороны). Значение `-84.2` означает, что плата почти вертикальна, «носом» вниз.
*   **Где встречается за пределами лаборатории:** угол атаки крыла у беспилотников, определение уклона дороги в автомобильных системах помощи при трогании в гору.

### 2. `Roll` (Крен / Наклон влево-вправо)
*   **Тип данных:** `float`, диапазон `-180.0` … `180.0` градусов.
*   **Физический смысл:** угол наклона платы вокруг оси X (вдоль короткой стороны).
*   **Где встречается:** основной сигнал обратной связи для балансирующих роботов (Segway-подобные, перевёрнутый маятник).

### 3. `Yaw` (Рыскание / Курс)
*   **Тип данных:** `float`, диапазон `0.0` … `360.0` градусов (круговая шкала).
*   **Физический смысл:** угол разворота в горизонтальной плоскости, получен численным интегрированием угловой скорости $\omega_z$. Без магнитометра для коррекции у параметра есть дрейф (см. `Lesson.md`, урок про накопление погрешности) — он хорош для быстрой динамики, но не для долгого удержания курса.
*   **Где встречается:** курсовая ориентация складских роботов (AGV) в помещениях без GPS.

### 4. `Z-Acc` (Вертикальное линейное ускорение)
*   **Тип данных:** `float`, диапазон `-2.00` … `2.00` g (ограничено настройкой чувствительности FS_SEL).
*   **Физический смысл:** проекция вектора ускорения на ось Z чипа. Падает до значений, близких к 0, когда плата развёрнута вертикально — вектор гравитации уходит с оси Z на другую ось.
*   **Где встречается:** подсчёт шагов в фитнес-трекерах по пикам вертикального ускорения.

### 5. `TotalG` (Модуль вектора полной перегрузки)
*   **Тип данных:** `float`, диапазон `0.00` … `3.46` g (теоретический предел при ±2g по 3 осям).
*   **Физический смысл:** длина трёхмерного вектора ускорения, не зависящая от угла наклона: $\text{TotalG} = \sqrt{a_x^2 + a_y^2 + a_z^2}$. Значение около `1.00` означает покой (на чип действует только гравитация); падение к `0.00` — свободное падение/невесомость; резкий всплеск — удар.
*   **Где встречается:** детекторы свободного падения (например, защита жёстких дисков при падении устройства).

### 6. `Status` (Кинематический статус)
*   **Допустимые значения:** `STATIONARY` или `MOVING`.
*   **Физический смысл:** если угловая скорость по всем трём осям гироскопа $|\omega_{x,y,z}| < 0.5^\circ/\text{с}$ — плата считается неподвижной.
*   **Где встречается:** перевод IoT-устройств в спящий режим при долгом покое для экономии батареи.

### 7. `Link` (Статус связи)
*   **Допустимые значения:** `OK` или `LOST`.
*   **Физический смысл:** пришли ли новые данные с датчика по I2C за последние 500 мс (см. `Mpu6050Driver::isAlive()`). `LOST` означает физический обрыв связи (отпаялся провод, датчик завис) — данные на экране в этот момент устаревшие, доверять им нельзя.


## Связанные материалы

- [Сигналы и данные](/docs/robotics/concepts/signals/) — почему любое измерение
  содержит шум, откуда берётся дрейф гироскопа и зачем усреднять.
- [Управление и обратная связь](/docs/robotics/concepts/control/) — комплементарный
  фильтр и ПИД решают родственные задачи: доверять быстрому или точному источнику.
- [Компоненты: шина I2C](/docs/sensors/meteo/aht20_bmp280/) — как несколько
  устройств делят два провода и различаются по адресам.
- [БПЛА: настройка ПИД](/docs/uav/02-algorithms/pid-tuning/) — тот же датчик в
  полётном контроллере: данные IMU напрямую управляют моторами.
