MPU6050 и Arduino: акселерометр, гироскоп и угол наклона
MPU6050 с Arduino: подключение, I2C-адрес, сырые значения, калибровка, угол наклона через atan2 и комплементарный фильтр, библиотека Adafruit, код для ESP32 и Pico.
MPU6050 объединяет в одной крошечной микросхеме 3-осевой акселерометр и 3-осевой гироскоп и считается самым популярным датчиком движения в проектах на Arduino. Он измеряет, насколько наклонена плата, в какую сторону и с какой скоростью она вращается, трясут ли её и не упала ли она. На этом датчике строят балансирующих роботов, дроны, стабилизаторы камеры (подвесы, gimbal), шагомеры и игры с управлением движением. MPU6050 подключается к Arduino всего четырьмя проводами по I2C.
В этой статье шаг за шагом разберём, как работает MPU6050, что такое его оси и сырые значения, как подключить его по I2C, как читать данные с библиотекой и без неё, как провести калибровку, посчитать углы наклона через atan2 и применить комплементарный фильтр, который объединяет сильные стороны обоих датчиков. Затем соберём на ESP32 сигнализацию падения и напишем код на MicroPython для Raspberry Pi Pico.

Что такое MPU6050 и как он работает?
MPU6050 производства InvenSense (сейчас TDK) — это IMU, инерциальный измерительный модуль. Внутри находятся крошечные механические структуры из кремния (MEMS). Акселерометр измеряет, насколько смещается при ускорении маленькая масса на пружинах; поскольку он чувствует силу тяжести даже в покое, датчик, лежащий ровно на столе, показывает по оси Z около 1 g (9,81 м/с²), и по этому можно определить его наклон относительно земли. Гироскоп измеряет угловую скорость, то есть на сколько градусов в секунду поворачивается датчик, по силе Кориолиса, действующей на колеблющиеся структуры. Измерения переводятся в числа 16-битными АЦП внутри микросхемы и читаются по I2C. Ещё в микросхеме есть датчик температуры и цифровой процессор движения (DMP), который может взять на себя расчёты движения.
| Параметр | Значение |
|---|---|
| Датчики | 3-осевой акселерометр + 3-осевой гироскоп + температура |
| Диапазон акселерометра | ±2, ±4, ±8, ±16 g |
| Диапазон гироскопа | ±250, ±500, ±1000, ±2000 °/с |
| Разрешение | 16 бит (от −32768 до 32767 на каждую ось) |
| Интерфейс | I2C, до 400 kHz |
| I2C-адрес | 0x68 (AD0 на GND) или 0x69 (AD0 на 3,3 V) |
| Напряжение микросхемы | 2,375–3,46 V (плата GY-521 принимает 3,3–5 V) |
| Ток | Около 3,9 mA (5 µA во сне) |
| Дополнительно | DMP, FIFO на 1024 байта, прерывание по движению, вспомогательная шина I2C для внешнего датчика |
Оси, сырые значения и чувствительность
Стрелки на плате показывают оси X и Y; ось Z перпендикулярна плате и направлена вверх. Для каждой оси датчик выдаёт 16-битное число со знаком. Чтобы перевести это сырое число в физическую величину, его делят на чувствительность выбранного диапазона. Например, в диапазоне по умолчанию ±2 g сырое значение 16384 означает 1 g; у датчика, лежащего на столе, будет az ≈ 16384, а ax, ay ≈ 0. У гироскопа в диапазоне ±250 °/с сырое значение 131 соответствует повороту на 1 градус в секунду. Широкий диапазон позволяет измерять более резкие движения, но мелкие изменения показывает грубее, поэтому выбирай самый узкий диапазон, которого хватает для проекта.
| Настройка | Диапазон акселерометра | LSB/g | Диапазон гироскопа | LSB/(°/с) |
|---|---|---|---|---|
| 0 | ±2 g | 16384 | ±250 °/с | 131 |
| 1 | ±4 g | 8192 | ±500 °/с | 65,5 |
| 2 | ±8 g | 4096 | ±1000 °/с | 32,8 |
| 3 | ±16 g | 2048 | ±2000 °/с | 16,4 |
Микросхема измеряет и температуру: °C = сырое значение / 340 + 36.53. Это температура самой микросхемы, а не комнаты, но поскольку нулевая точка гироскопа уплывает вместе с температурой, она пригодится для продвинутых поправок.
Подключение MPU6050: Arduino Uno, ESP32 и Pico
| Пин MPU6050 | Arduino Uno | ESP32 | Raspberry Pi Pico |
|---|---|---|---|
| VCC | 5V | 3V3 | 3V3(OUT) |
| GND | GND | GND | GND |
| SCL | A5 | GPIO 22 | GP5 |
| SDA | A4 | GPIO 21 | GP4 |
| AD0 | Не подключён (адрес 0x68) | Не подключён (адрес 0x68) | Не подключён (адрес 0x68) |
| INT | D2 (по желанию) | Любой GPIO (по желанию) | Любой пин GP (по желанию) |
| XDA, XCL | Не подключаются | Не подключаются | Не подключаются |
На плате GY-521 есть стабилизатор на 3,3 V, поэтому VCC можно подключить к пину 5V на Uno. Пин AD0 на плате подтянут к GND через резистор 4,7 kΩ, так что, если оставить его неподключённым, адрес будет 0x68; если нужны два MPU6050 на одной шине, подключи AD0 одного из них к 3,3 V, и его адрес сменится на 0x69. Пин INT сообщает, что готовы новые данные или обнаружено движение; для простых проектов его можно не подключать. После подключения полезно проверить скетчем-сканером I2C, что датчик виден на шине; как это сделать, рассказано в статье I2C LCD-дисплей.
Быстрый старт с библиотекой: Adafruit MPU6050
- Открой в Arduino IDE «Менеджер библиотек» (Library Manager) и найди Adafruit MPU6050.
- Когда при установке появится вопрос о зависимостях, выбери «Установить все» (Install all), чтобы заодно установились Adafruit Unified Sensor и Adafruit BusIO.
- Подключи датчик по таблице, загрузи скетч ниже и открой монитор порта на скорости 115200 бод.
- Открой в меню «Инструменты» (Tools) «Плоттер по последовательному соединению» (Serial Plotter), чтобы смотреть на все шесть осей в виде живых графиков: при наклоне платы меняются кривые ускорения, при вращении — кривые гироскопа.
1#include <Wire.h>
2#include <Adafruit_MPU6050.h>
3#include <Adafruit_Sensor.h>
4
5Adafruit_MPU6050 mpu;
6
7void setup() {
8 Serial.begin(115200);
9 if (!mpu.begin()) { // varsayılan adres 0x68 / default address 0x68
10 Serial.println("MPU6050 bulunamadi / not found");
11 while (true) delay(10);
12 }
13 mpu.setAccelerometerRange(MPU6050_RANGE_4_G); // ±4 g
14 mpu.setGyroRange(MPU6050_RANGE_500_DEG); // ±500 °/s
15 mpu.setFilterBandwidth(MPU6050_BAND_21_HZ); // titreşimi süz / filter out vibration
16}
17
18void loop() {
19 sensors_event_t a, g, t;
20 mpu.getEvent(&a, &g, &t);
21 Serial.print("ax:"); Serial.print(a.acceleration.x); // m/s²
22 Serial.print(" ay:"); Serial.print(a.acceleration.y);
23 Serial.print(" az:"); Serial.print(a.acceleration.z);
24 Serial.print(" gx:"); Serial.print(g.gyro.x); // rad/s
25 Serial.print(" gy:"); Serial.print(g.gyro.y);
26 Serial.print(" gz:"); Serial.print(g.gyro.z);
27 Serial.print(" T:"); Serial.println(t.temperature); // °C
28 delay(100);
29}Библиотека Adafruit сразу выдаёт результаты в физических единицах: ускорение в м/с², угловую скорость в рад/с и температуру в °C. Чтобы перевести значение гироскопа в градусы в секунду, достаточно умножить его на 57.3. Встроенный фильтр нижних частот, который выбирают через setFilterBandwidth, уменьшает шум от вибраций: 21 Hz — хорошая отправная точка для движений рукой, а если нужно ловить короткие удары, выбери 94 или 260 Hz. При запуске библиотека читает регистр идентификатора микросхемы (WHO_AM_I), и begin() возвращает false, если там не 0x68.
Чтение без библиотеки, калибровка и угол наклона
Библиотеки облегчают жизнь, но прямое чтение регистров — отличный способ понять, что происходит внутри датчика. MPU6050 запускается в спящем режиме; сначала его нужно разбудить, записав 0 в регистр 0x6B (PWR_MGMT_1). Затем читаются 14 байт, начиная с адреса 0x3B: 6 байт ускорения, 2 байта температуры и 6 байт данных гироскопа. Каждое значение занимает два байта, старший байт идёт первым. Вот основные регистры, которые используются в коде и которые стоит знать:
| Регистр | Адрес | Назначение |
|---|---|---|
| SMPLRT_DIV | 0x19 | Делитель частоты выборки |
| CONFIG | 0x1A | Встроенный фильтр нижних частот (DLPF) |
| GYRO_CONFIG | 0x1B | Диапазон гироскопа (±250 … ±2000 °/с) |
| ACCEL_CONFIG | 0x1C | Диапазон акселерометра (±2 … ±16 g) |
| ACCEL_XOUT_H | 0x3B | Адрес, с которого начинаются измерения (14 байт) |
| PWR_MGMT_1 | 0x6B | Сон и источник тактирования; запись 0 будит датчик |
| WHO_AM_I | 0x75 | Идентификатор; у оригинального MPU6050 возвращает 0x68 |
У неподвижного датчика единственная сила, которую видит акселерометр, — это сила тяжести. По тому, как она распределяется между осями, находят два угла: угол крена (roll) вокруг оси X — roll = atan2(ay, az), а угол тангажа (pitch) вокруг оси Y — pitch = atan2(−ax, √(ay² + az²)). В отличие от обычного арктангенса, atan2 даёт правильный знак во всех четырёх четвертях и не делит на ноль, когда az приближается к нулю. Например, при ay = 8192 и az = 14189 получится roll = atan2(8192, 14189) ≈ 30°. А вот поворот вокруг оси Z (рыскание, yaw) акселерометр не видит, потому что он не меняет распределение силы тяжести между осями.
У обоих датчиков есть слабое место. Акселерометр точен на длинной дистанции, но сильно шумит при движении и вибрации, потому что поверх силы тяжести измеряет и ускорение самого движения. Гироскоп плавный на коротком отрезке, но чтобы получить угол, угловую скорость суммируют во времени (angle += rate × dt), и даже небольшое смещение накапливается и потихоньку уводит угол. Комплементарный фильтр объединяет их: angle = 0.98 × (angle + gyro × dt) + 0.02 × угол акселерометра. На коротком отрезке он доверяет гироскопу, на длинном — акселерометру. При 100 Hz (dt = 0.01 с) эти коэффициенты дают постоянную времени около половины секунды: τ = 0.98 × 0.01 / 0.02 = 0.49 с.
Калибровка важна не меньше фильтра. Даже совершенно неподвижный гироскоп может показывать постоянное смещение в несколько °/с; если его не убрать, рассчитанный угол за считаные секунды уплывёт на десятки градусов. Скетч ниже при запуске, пока датчик неподвижен, усредняет 500 показаний и потом вычитает это значение из каждого следующего. Положи плату на ровную поверхность и не трогай её во время калибровки, а затем смотри на кривые roll, pitch и yaw в плоттере.
1#include <Wire.h>
2
3const int MPU_ADDR = 0x68; // AD0 GND'de ya da boşta / AD0 to GND or floating
4const float GYRO_LSB = 131.0; // ±250 °/s aralığında 1 °/s / 1 °/s at the ±250 °/s range
5const float ALPHA = 0.98; // tamamlayıcı filtre katsayısı / complementary filter weight
6
7int16_t ax, ay, az, tempRaw, gx, gy, gz;
8float gxOff = 0, gyOff = 0, gzOff = 0; // jiroskop sapmaları / gyro offsets
9float roll = 0, pitch = 0, yaw = 0;
10unsigned long lastMicros;
11
12void writeReg(uint8_t reg, uint8_t val) {
13 Wire.beginTransmission(MPU_ADDR);
14 Wire.write(reg);
15 Wire.write(val);
16 Wire.endTransmission();
17}
18
19int16_t read16() {
20 uint8_t hi = Wire.read(); // önce yüksek bayt / high byte first
21 uint8_t lo = Wire.read();
22 return (int16_t)(((uint16_t)hi << 8) | lo);
23}
24
25void readMPU() {
26 Wire.beginTransmission(MPU_ADDR);
27 Wire.write(0x3B); // ACCEL_XOUT_H
28 Wire.endTransmission(false); // hattı bırakma, tekrar başlat / repeated start
29 Wire.requestFrom(MPU_ADDR, 14); // ivme 6 + sıcaklık 2 + jiroskop 6 bayt / accel 6 + temp 2 + gyro 6 bytes
30 ax = read16(); ay = read16(); az = read16();
31 tempRaw = read16();
32 gx = read16(); gy = read16(); gz = read16();
33}
34
35void calibrateGyro() {
36 const int N = 500;
37 long sx = 0, sy = 0, sz = 0;
38 for (int i = 0; i < N; i++) {
39 readMPU();
40 sx += gx; sy += gy; sz += gz;
41 delay(3);
42 }
43 gxOff = sx / (float)N;
44 gyOff = sy / (float)N;
45 gzOff = sz / (float)N;
46}
47
48void setup() {
49 Serial.begin(115200);
50 Wire.begin();
51 Wire.setClock(400000); // 400 kHz hızlı mod / 400 kHz fast mode
52 writeReg(0x6B, 0x00); // PWR_MGMT_1: uykudan uyandır / wake up
53 writeReg(0x1A, 0x03); // CONFIG: alçak geçiren filtre ~44 Hz / low-pass ~44 Hz
54 writeReg(0x1B, 0x00); // GYRO_CONFIG: ±250 °/s
55 writeReg(0x1C, 0x00); // ACCEL_CONFIG: ±2 g
56 delay(100);
57 Serial.println("Kalibrasyon: sensoru oynatma / calibrating: keep still");
58 calibrateGyro();
59 readMPU();
60 roll = atan2(ay, az) * RAD_TO_DEG; // başlangıç açıları / initial angles
61 pitch = atan2(-ax, sqrt((float)ay * ay + (float)az * az)) * RAD_TO_DEG;
62 lastMicros = micros();
63}
64
65void loop() {
66 readMPU();
67 unsigned long now = micros();
68 float dt = (now - lastMicros) / 1000000.0; // saniye / seconds
69 lastMicros = now;
70
71 float accRoll = atan2(ay, az) * RAD_TO_DEG; // ivmeölçerden açı / angle from accelerometer
72 float accPitch = atan2(-ax, sqrt((float)ay * ay + (float)az * az)) * RAD_TO_DEG;
73 float gxRate = (gx - gxOff) / GYRO_LSB; // °/s
74 float gyRate = (gy - gyOff) / GYRO_LSB;
75 float gzRate = (gz - gzOff) / GYRO_LSB;
76
77 roll = ALPHA * (roll + gxRate * dt) + (1 - ALPHA) * accRoll; // tamamlayıcı filtre / complementary filter
78 pitch = ALPHA * (pitch + gyRate * dt) + (1 - ALPHA) * accPitch;
79 yaw += gzRate * dt; // yalnız jiroskop: zamanla kayar / gyro only: drifts over time
80
81 Serial.print("roll:"); Serial.print(roll, 1);
82 Serial.print(" pitch:"); Serial.print(pitch, 1);
83 Serial.print(" yaw:"); Serial.println(yaw, 1);
84 delay(10); // yaklaşık 100 Hz / about 100 Hz
85}| Строка кода | Что делает |
|---|---|
| writeReg(0x6B, 0x00) | Выводит датчик из спящего режима |
| writeReg(0x1A, 0x03) | Включает встроенный фильтр примерно на 44 Hz |
| Wire.requestFrom(MPU_ADDR, 14) | Читает ускорение, температуру и данные гироскопа за один раз |
| calibrateGyro() | Находит смещение гироскопа, усредняя 500 показаний |
| atan2(ay, az) * RAD_TO_DEG | Считает по акселерометру угол крена в градусах |
| ALPHA * (...) + (1 - ALPHA) * ... | Комплементарный фильтр: объединяет гироскоп и акселерометр |
| yaw += gzRate * dt | Считает рыскание только по гироскопу, чтобы было видно, как оно уплывает со временем |
MPU6050 и ESP32: сигнализация падения
На ESP32 подключение такое же, как на Uno, только пины I2C — GPIO 21 (SDA) и GPIO 22 (SCL), а модуль питается от 3V3. Все скетчи выше работают на ESP32 без изменений; при желании пины можно задать явно через Wire.begin(21, 22). Пример ниже — детектор падения. В свободном падении акселерометр показывает почти 0 g, потому что корпус датчика и масса внутри него падают вместе; следующий за этим удар даёт пик в несколько g. Если скетч видит свободное падение длительностью не меньше 100 мс, а в течение полсекунды после него — удар сильнее 2,5 g, он на одну секунду включает активный зуммер на GPIO 25. Свободное падение длительностью 100 мс соответствует высоте около 5 см (h = ½ × g × t²).
1#include <Wire.h>
2#include <Adafruit_MPU6050.h>
3#include <Adafruit_Sensor.h>
4
5Adafruit_MPU6050 mpu;
6const int BUZZER_PIN = 25; // aktif buzzer / active buzzer
7const float FREE_FALL_G = 0.4; // serbest düşüş eşiği / free-fall threshold
8const float IMPACT_G = 2.5; // darbe eşiği / impact threshold
9unsigned long fallStart = 0, fallEnd = 0;
10
11void setup() {
12 Serial.begin(115200);
13 pinMode(BUZZER_PIN, OUTPUT);
14 Wire.begin(21, 22); // SDA, SCL
15 if (!mpu.begin(0x68, &Wire)) {
16 Serial.println("MPU6050 bulunamadi / not found");
17 while (true) delay(10);
18 }
19 mpu.setAccelerometerRange(MPU6050_RANGE_8_G); // darbeler için geniş aralık / wide range for impacts
20 mpu.setFilterBandwidth(MPU6050_BAND_94_HZ); // kısa darbeleri kaçırma / keep short peaks
21}
22
23void loop() {
24 sensors_event_t a, g, t;
25 mpu.getEvent(&a, &g, &t);
26 float x = a.acceleration.x, y = a.acceleration.y, z = a.acceleration.z;
27 float total = sqrt(x * x + y * y + z * z) / SENSORS_GRAVITY_STANDARD; // toplam ivme, g / total acceleration in g
28 unsigned long now = millis();
29
30 if (total < FREE_FALL_G) {
31 if (fallStart == 0) fallStart = now; // düşüş başladı / fall started
32 } else if (fallStart != 0) {
33 if (now - fallStart > 100) fallEnd = now; // en az 100 ms süren düşüş / fall of at least 100 ms
34 fallStart = 0;
35 }
36
37 if (fallEnd != 0 && now - fallEnd < 500 && total > IMPACT_G) { // düşüşten sonra 0,5 s içinde darbe / impact within 0.5 s
38 Serial.println("DUSME ALGILANDI / FALL DETECTED");
39 digitalWrite(BUZZER_PIN, HIGH);
40 delay(1000);
41 digitalWrite(BUZZER_PIN, LOW);
42 fallEnd = 0;
43 }
44 if (fallEnd != 0 && now - fallEnd >= 500) fallEnd = 0; // darbe gelmedi, sıfırla / no impact, reset
45 delay(5);
46}Дальше можно подключить Wi-Fi на ESP32 и, например, отправлять уведомление в Telegram на телефон, если упадёт пожилой родственник, или показывать углы на веб-странице в реальном времени. Пороги подбирай по своим тестам: коробка, упавшая со стола, и датчик на запястье дают разные пики. Как выбрать и подключить зуммер, читай в статье Что такое зуммер?.
MPU6050 и Raspberry Pi Pico (MicroPython)
На Pico дополнительная библиотека не нужна: встроенный класс I2C в MicroPython умеет читать регистры напрямую. Подключи датчик к шине I2C0: SDA на GP4, SCL на GP5. С помощью struct.unpack 14 байт превращаются в семь 16-битных чисел со знаком; «>» означает big-endian (старший байт первым), а «h» — 16-битное число со знаком. Сначала код печатает найденные I2C-адреса; если в списке нет 0x68, проверь подключение. Для простоты калибровку мы не добавляли; при необходимости метод усреднения из скетча для Arduino применяется точно так же.
1from machine import Pin, I2C
2import math, struct, time
3
4MPU = 0x68
5i2c = I2C(0, sda=Pin(4), scl=Pin(5), freq=400000)
6print("Bulunan adresler / found addresses:", [hex(a) for a in i2c.scan()])
7
8i2c.writeto_mem(MPU, 0x6B, b"\x00") # uykudan uyandır / wake up
9i2c.writeto_mem(MPU, 0x1A, b"\x03") # alçak geçiren filtre ~44 Hz / low-pass ~44 Hz
10i2c.writeto_mem(MPU, 0x1B, b"\x00") # jiroskop ±250 °/s / gyro ±250 °/s
11i2c.writeto_mem(MPU, 0x1C, b"\x00") # ivmeölçer ±2 g / accelerometer ±2 g
12roll = pitch = 0.0
13last = time.ticks_us()
14
15while True:
16 data = i2c.readfrom_mem(MPU, 0x3B, 14)
17 ax, ay, az, t, gx, gy, gz = struct.unpack(">hhhhhhh", data) # büyük endian, işaretli / big-endian, signed
18 now = time.ticks_us()
19 dt = time.ticks_diff(now, last) / 1000000
20 last = now
21 acc_roll = math.degrees(math.atan2(ay, az))
22 acc_pitch = math.degrees(math.atan2(-ax, math.sqrt(ay * ay + az * az)))
23 roll = 0.98 * (roll + gx / 131 * dt) + 0.02 * acc_roll # tamamlayıcı filtre / complementary filter
24 pitch = 0.98 * (pitch + gy / 131 * dt) + 0.02 * acc_pitch
25 temp = t / 340 + 36.53 # °C
26 print("roll {:.1f} pitch {:.1f} T {:.1f}".format(roll, pitch, temp))
27 time.sleep_ms(10)Идеи проектов с MPU6050
- Электронный уровень: показывай углы крена и тангажа на OLED-дисплее с движущимся пузырьком.
- Сервопривод с управлением движением: наклоняешь датчик в руке, и сервопривод поворачивается на тот же угол; идеально для руки робота или поворотной головки камеры.
- Игра с управлением наклоном: играй в Pong или лабиринт, наклоняя плату вместо джойстика.
- Балансирующий робот: обрабатывай угол тангажа ПИД-регулятором и удерживай робота в вертикальном положении с помощью DC-моторов на драйвере L298N.
- Шагомер: считай шаги по регулярным пикам полного ускорения.
- Регистратор вибраций: измеряй тряску станка или стиральной машины и подавай сигнал, когда превышен порог.
Частые ошибки и как их исправить
| Симптом | Вероятная причина | Решение |
|---|---|---|
| begin() возвращает false («MPU6050 not found») | Ошибка в подключении, неверный адрес или микросхема-клон | Найди адрес сканером I2C; если WHO_AM_I не 0x68 (например, 0x70), используй код без библиотеки |
| Все значения равны 0 | Датчик в спящем режиме | Запиши 0 в регистр 0x6B |
| Значения равны -1 или замирают | Плохой контакт, слишком длинная шина I2C | Укороти провода, припаяй пины |
| Угол уплывает в покое | Не убрано смещение гироскопа | Откалибруй датчик при запуске, пока он неподвижен |
| Угол скачет при движении | Используется только акселерометр | Добавь комплементарный фильтр |
| Рыскание постоянно уплывает | У MPU6050 нет компаса | Добавь магнитометр, например QMC5883L, или возьми 9-осевой датчик |
| Крен считается неверно, когда тангаж близок к ±90° | Сингулярность углов Эйлера | Избегай этой области или используй кватернионы из DMP |
Несмотря на низкую цену, MPU6050 открывает дверь в мир измерения движения: сначала познакомься с сырыми значениями, затем посчитай углы и в конце сгладь их фильтром. Другие I2C-датчики и их применение смотри в руководстве по датчикам Arduino. В приложении BlueGrays есть проекты с управлением сервоприводом, I2C-дисплеем, джойстиком и роботами, с пошаговыми схемами и кодом, которые можно объединить с MPU6050.
Частые вопросы
Для чего используют MPU6050?
MPU6050 измеряет наклон предмета, скорость его вращения и ускорение. Его используют в балансирующих роботах, дронах и подвесах для камер, шагомерах, для обнаружения падений и ударов, а также в играх с управлением движением.
Какой адрес у MPU6050: 0x68 или 0x69?
Адрес 0x68, если пин AD0 не подключён или соединён с GND, и 0x69, если он подключён к 3,3 V. На плате GY-521 AD0 подтянут к GND через резистор, поэтому адрес по умолчанию 0x68. Чтобы знать наверняка, запусти скетч-сканер I2C.
Работает ли MPU6050 от 5 V?
Сама микросхема MPU6050 работает максимум от 3,46 V, но благодаря стабилизатору на плате GY-521 на пин VCC можно подавать 5 V. Линии I2C остаются на уровне 3,3 V, и Arduino Uno читает их без проблем. На голые платы без стабилизатора 5 V подавать нельзя.
Как посчитать углы с помощью MPU6050?
Когда датчик неподвижен, углы получают из акселерометра: roll = atan2(ay, az) и pitch = atan2(−ax, √(ay² + az²)). Чтобы результат был точным и при движении, угловую скорость гироскопа интегрируют во времени и объединяют с углом акселерометра комплементарным фильтром или фильтром Калмана.
Может ли MPU6050 измерять рыскание (yaw)?
На коротких отрезках — да: рыскание можно посчитать, интегрируя угловую скорость по оси Z. Но поскольку у MPU6050 нет магнитометра, рыскание со временем уплывает, а абсолютное направление (на север) датчик знать не может. Для стабильного курса нужен датчик-компас, например QMC5883L, или 9-осевой IMU.
Чем MPU6050 отличается от MPU9250?
MPU6050 — 6-осевой датчик с акселерометром и гироскопом. В MPU9250 добавлен 3-осевой магнитометр, поэтому он 9-осевой и может измерять рыскание без дрейфа; кроме того, он поддерживает SPI. MPU9250 снят с производства, поэтому для новых проектов предпочитают его преемников, например ICM-20948.
Что собрать после прочтения
Все проекты
Работа с сервоприводом
Рычаг маленького сервопривода по очереди поворачивается в три положения: до упора в начало, ровно на середину и до упора в конец, задерживаясь на каждой остановке на две секунды. Arduino сообщает мото

Управление сервоприводом джойстиком
Управляй двумя моторами джойстиком, как будто поворачиваешь камеру наблюдения. Наклони рычажок влево или вправо, и нижний сервопривод медленно поворачивается, наклони вверх или вниз — верхний сервопри

Сервопривод на ESP32 (управление потенциометром)
В этом проекте сервопривод SG90 управляется потенциометром. Угол сервопривода задаётся сопоставлением аналогового значения потенциометра с диапазоном 0–180 градусов. Библиотека ESP32Servo формирует сигналы сервопривода на подходящих выходных пинах GPIO у ESP32; этот проект использует GPIO 18. Это базовый способ управления для роборук, подвесов камер и механизмов автоматических дверей.

Игра в пинг-понг — SSD1306
Мяч, две ракетки и ты: на маленьком OLED-экране ты играешь в настольный теннис — одну из самых первых видеоигр. Две кнопки двигают твою ракетку справа вверх и вниз, а левой ракеткой управляет компьюте

LCD-экран с I2C
Дай своему Arduino собственный экран и заставь его написать первое сообщение. Двухстрочный LCD-экран подключается всего несколькими проводами; в верхней строке появляется приветствие, затем второе соо

I2C LCD-дисплей (16x2) на ESP32
В этом проекте символьный LCD-экран 16x2 подключается к ESP32 по протоколу I2C и выводит текст. Благодаря I2C экраном можно управлять всего двумя пинами данных (SDA и SCL), не тратя 6+ пинов, как при классическом параллельном подключении. Код печатает постоянное сообщение в первой строке и счётчик, растущий каждую секунду, во второй. Кроме того, при запуске работает сканер I2C, который выводит адрес дисплея в монитор порта.

Робот, объезжающий препятствия
Как насчёт того, чтобы собрать умную машину, которая сама находит дорогу? Робот, объезжающий препятствия, постоянно осматривает всё вокруг благодаря ультразвуковому датчику спереди. Встретив препятств
Другие статьи
Приложение BlueGrays
Собери эту схему шаг за шагом в телефоне
Схема подключения, код и список деталей на одном экране. 200+ проектов на Arduino, ESP32 и Pico готовы к сборке.
Наведи камеру телефона
Наведи камеру на код — откроется магазин приложений на телефоне.
или открыть магазин

