MPU6050 Arduino: Beschleunigungssensor, Gyroskop, Neigungswinkel
MPU6050 am Arduino: Anschluss, I2C-Adresse, Rohwerte, Kalibrierung, Neigungswinkel mit atan2 und Komplementärfilter, dazu Adafruit-Bibliothek, ESP32 und Pico.
Der MPU6050 vereint einen 3-Achsen-Beschleunigungssensor und ein 3-Achsen-Gyroskop in einem winzigen Chip und ist der meistgenutzte Bewegungssensor in Arduino-Projekten. Er misst, wie stark die Platine geneigt ist, in welche Richtung und wie schnell sie sich dreht und ob sie geschüttelt wird oder herunterfällt. Selbstbalancierende Roboter, Drohnen, Kamerastabilisatoren (Gimbals), Schrittzähler und bewegungsgesteuerte Spiele werden mit diesem Sensor gebaut. Der MPU6050 wird mit nur vier Kabeln über I2C an den Arduino angeschlossen.
In diesem Artikel lernst du Schritt für Schritt, wie der MPU6050 funktioniert, was es mit Achsen und Rohwerten auf sich hat, wie der I2C-Anschluss aussieht, wie du ihn mit und ohne Bibliothek ausliest, wie du kalibrierst, Neigungswinkel mit atan2 berechnest und mit dem Komplementärfilter die Stärken beider Sensoren kombinierst. Danach bauen wir mit einem ESP32 einen Sturzalarm und schreiben MicroPython-Code für den Raspberry Pi Pico.

Was ist der MPU6050 und wie funktioniert er?
Der MPU6050 von InvenSense (heute TDK) ist eine IMU, also eine inertiale Messeinheit. Im Inneren sitzen winzige mechanische Strukturen aus Silizium (MEMS). Der Beschleunigungssensor misst, wie weit sich eine kleine, federnd aufgehängte Masse unter Beschleunigung verschiebt. Da er auch im Ruhezustand die Schwerkraft spürt, zeigt ein flach auf dem Tisch liegender Sensor auf der Z-Achse etwa 1 g (9,81 m/s²) an; daraus kannst du seine Neigung gegenüber dem Boden bestimmen. Das Gyroskop misst über die Corioliskraft auf schwingende Strukturen die Winkelgeschwindigkeit, also wie viele Grad pro Sekunde sich der Sensor dreht. Die Messwerte werden von 16-Bit-ADCs im Chip in Zahlen umgewandelt und über I2C ausgelesen. Außerdem enthält der Chip einen Temperatursensor und einen digitalen Bewegungsprozessor (DMP), der Bewegungsberechnungen übernehmen kann.
| Merkmal | Wert |
|---|---|
| Sensoren | 3-Achsen-Beschleunigungssensor + 3-Achsen-Gyroskop + Temperatur |
| Messbereich Beschleunigung | ±2, ±4, ±8, ±16 g |
| Messbereich Gyroskop | ±250, ±500, ±1000, ±2000 °/s |
| Auflösung | 16 Bit (je Achse von -32768 bis 32767) |
| Schnittstelle | I2C, bis 400 kHz |
| I2C-Adresse | 0x68 (AD0 an GND) oder 0x69 (AD0 an 3,3 V) |
| Chipspannung | 2,375–3,46 V (die GY-521-Platine verträgt 3,3–5 V) |
| Stromaufnahme | Etwa 3,9 mA (im Schlafmodus 5 µA) |
| Extras | DMP, 1024-Byte-FIFO, Bewegungs-Interrupt, Hilfs-I2C für einen externen Sensor |
Achsen, Rohwerte und Empfindlichkeit
Die Pfeile auf der Platine zeigen die X- und Y-Achse; die Z-Achse steht senkrecht auf der Platine und zeigt nach oben. Der Sensor liefert für jede Achse eine vorzeichenbehaftete 16-Bit-Zahl. Um diesen Rohwert in eine physikalische Einheit umzurechnen, teilst du ihn durch die Empfindlichkeit des gewählten Messbereichs. Im voreingestellten Bereich ±2 g bedeutet zum Beispiel ein Rohwert von 16384 genau 1 g; bei einem Sensor auf dem Tisch liest du az ≈ 16384 sowie ax und ay ≈ 0. Beim Gyroskop entspricht im Bereich ±250 °/s ein Rohwert von 131 einer Drehung von 1 Grad pro Sekunde. Ein größerer Bereich erfasst heftigere Bewegungen, zeigt kleine Änderungen aber gröber an; wähle daher den kleinsten Bereich, der für dein Projekt reicht.
| Einstellung | Bereich Beschleunigung | LSB/g | Bereich Gyroskop | LSB/(°/s) |
|---|---|---|---|---|
| 0 | ±2 g | 16384 | ±250 °/s | 131 |
| 1 | ±4 g | 8192 | ±500 °/s | 65,5 |
| 2 | ±8 g | 4096 | ±1000 °/s | 32,8 |
| 3 | ±16 g | 2048 | ±2000 °/s | 16,4 |
Der Chip misst auch die Temperatur: °C = Rohwert / 340 + 36,53. Dieser Wert zeigt eher die Temperatur des Chips selbst als die der Umgebung; da sich der Nullpunkt des Gyroskops mit der Temperatur verschiebt, ist er aber für fortgeschrittene Korrekturen nützlich.
MPU6050 anschließen: Arduino Uno, ESP32 und Pico
| MPU6050-Pin | 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 | Offen (Adresse 0x68) | Offen (Adresse 0x68) | Offen (Adresse 0x68) |
| INT | D2 (optional) | Beliebiger GPIO (optional) | Beliebiger GP-Pin (optional) |
| XDA, XCL | Nicht anschließen | Nicht anschließen | Nicht anschließen |
Da die GY-521-Platine einen 3,3-V-Spannungsregler hat, kannst du VCC an den 5V-Pin des Uno anschließen. AD0 ist auf der Platine über einen 4,7-kΩ-Widerstand auf GND gezogen, deshalb lautet die Adresse 0x68, wenn der Pin offen bleibt. Willst du zwei MPU6050 am selben Bus betreiben, verbindest du AD0 eines Sensors mit 3,3 V und änderst so seine Adresse auf 0x69. Der INT-Pin meldet, wenn neue Daten bereitstehen oder eine Bewegung erkannt wurde; für einfache Projekte musst du ihn nicht anschließen. Nach dem Verdrahten solltest du dir angewöhnen, mit einem I2C-Scanner-Sketch zu prüfen, ob der Sensor gefunden wird; wie das geht, steht in I2C-LCD-Display.
Schnellstart mit Bibliothek: Adafruit MPU6050
- Öffne in der Arduino IDE den Bibliotheksverwalter und suche nach Adafruit MPU6050.
- Wenn bei der Installation nach Abhängigkeiten gefragt wird, wähle Install all; so werden auch Adafruit Unified Sensor und Adafruit BusIO installiert.
- Schließ den Sensor wie in der Tabelle an, lade den folgenden Sketch hoch und öffne den seriellen Monitor mit 115200 Baud.
- Öffne im Menü Werkzeuge den seriellen Plotter, um alle sechs Achsen als Live-Diagramm zu sehen; neigst du die Platine, ändern sich die Beschleunigungskurven, drehst du sie, die Gyroskopkurven.
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}Die Adafruit-Bibliothek liefert die Ergebnisse direkt in physikalischen Einheiten: Beschleunigung in m/s², Winkelgeschwindigkeit in rad/s und Temperatur in °C. Um einen Gyroskopwert in Grad pro Sekunde umzurechnen, multiplizierst du ihn einfach mit 57,3. Der interne Tiefpassfilter, den du mit setFilterBandwidth wählst, verringert Vibrationsrauschen: 21 Hz ist ein guter Startwert für Handbewegungen; willst du kurze Stöße erfassen, nimm 94 oder 260 Hz. Beim Start liest die Bibliothek das Kennungsregister des Chips (WHO_AM_I) aus, und begin() liefert false, wenn dort nicht 0x68 steht.
Auslesen ohne Bibliothek, Kalibrierung und Neigungswinkel
Bibliotheken machen es bequem, doch die Register direkt auszulesen ist sehr lehrreich, um zu verstehen, was im Sensor passiert. Der MPU6050 startet im Schlafmodus; zuerst weckst du ihn, indem du 0 in das Register 0x6B (PWR_MGMT_1) schreibst. Danach liest du ab Adresse 0x3B insgesamt 14 Byte: 6 Byte Beschleunigung, 2 Byte Temperatur und 6 Byte Gyroskop. Jeder Wert besteht aus zwei Byte, das höherwertige zuerst. Das sind die wichtigsten Register, die der Code nutzt und die du kennen solltest:
| Register | Adresse | Funktion |
|---|---|---|
| SMPLRT_DIV | 0x19 | Teiler für die Abtastrate |
| CONFIG | 0x1A | Interner Tiefpassfilter (DLPF) |
| GYRO_CONFIG | 0x1B | Messbereich Gyroskop (±250 … ±2000 °/s) |
| ACCEL_CONFIG | 0x1C | Messbereich Beschleunigung (±2 … ±16 g) |
| ACCEL_XOUT_H | 0x3B | Startadresse der Messwerte (14 Byte) |
| PWR_MGMT_1 | 0x6B | Schlafmodus und Taktquelle; 0 schreiben weckt ihn |
| WHO_AM_I | 0x75 | Kennung; ein echter MPU6050 liefert 0x68 |
Bei einem ruhenden Sensor ist die einzige Kraft, die der Beschleunigungssensor sieht, die Schwerkraft. Daraus, wie sie sich auf die Achsen verteilt, ergeben sich zwei Winkel: der Rollwinkel um die X-Achse roll = atan2(ay, az) und der Nickwinkel um die Y-Achse pitch = atan2(−ax, √(ay² + az²)). Anders als der normale Arkustangens liefert atan2 in allen vier Quadranten das richtige Vorzeichen und teilt nicht durch null, wenn az gegen null geht. Liest du zum Beispiel ay = 8192 und az = 14189, ergibt sich roll = atan2(8192, 14189) ≈ 30°. Die Drehung um die Z-Achse (Gieren, yaw) sieht der Beschleunigungssensor dagegen nicht, weil sich dabei die Verteilung der Schwerkraft auf die Achsen nicht ändert.
Beide Sensoren haben eine Schwäche. Der Beschleunigungssensor ist langfristig genau, bei Bewegung und Vibration aber sehr verrauscht, weil er zusätzlich zur Schwerkraft die Beschleunigung der Bewegung selbst misst. Das Gyroskop ist kurzfristig glatt, doch für einen Winkel summierst du die Winkelgeschwindigkeit über die Zeit auf (Winkel += Rate × dt), und schon ein kleiner Offset sammelt sich an und lässt den Winkel langsam wegdriften. Der Komplementärfilter verbindet beide: Winkel = 0,98 × (Winkel + Gyro × dt) + 0,02 × Beschleunigungswinkel. Kurzfristig vertraut er dem Gyroskop, langfristig dem Beschleunigungssensor. Bei 100 Hz (dt = 0,01 s) ergeben diese Koeffizienten eine Zeitkonstante von etwa einer halben Sekunde: τ = 0,98 × 0,01 / 0,02 = 0,49 s.
Die Kalibrierung ist mindestens so wichtig wie der Filter. Selbst ein völlig ruhendes Gyroskop kann einen konstanten Offset von einigen °/s zeigen; korrigierst du ihn nicht, driftet der berechnete Winkel innerhalb von Sekunden um Dutzende Grad. Der folgende Sketch mittelt beim Start 500 Messungen, während der Sensor still liegt, und zieht diesen Wert danach von jeder Messung ab. Lege die Platine während der Kalibrierung auf eine ebene Fläche und berühre sie nicht; beobachte anschließend die Kurven für roll, pitch und yaw im seriellen Plotter.
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}| Codezeile | Was sie macht |
|---|---|
| writeReg(0x6B, 0x00) | Holt den Sensor aus dem Schlafmodus |
| writeReg(0x1A, 0x03) | Aktiviert den internen Filter mit etwa 44 Hz |
| Wire.requestFrom(MPU_ADDR, 14) | Liest Beschleunigung, Temperatur und Gyroskop in einem Rutsch |
| calibrateGyro() | Ermittelt den Gyroskop-Offset aus dem Mittel von 500 Messungen |
| atan2(ay, az) * RAD_TO_DEG | Berechnet den Rollwinkel in Grad aus dem Beschleunigungssensor |
| ALPHA * (...) + (1 - ALPHA) * ... | Komplementärfilter: verbindet Gyroskop und Beschleunigungssensor |
| yaw += gzRate * dt | Berechnet yaw nur mit dem Gyroskop; du siehst, wie er mit der Zeit driftet |
MPU6050 mit dem ESP32: ein Sturzalarm
Am ESP32 ist der Anschluss derselbe wie am Uno, nur liegen die I2C-Pins auf GPIO 21 (SDA) und GPIO 22 (SCL), und das Modul wird mit 3V3 versorgt. Alle obigen Sketches laufen unverändert auf dem ESP32; wenn du willst, legst du die Pins mit Wire.begin(21, 22) ausdrücklich fest. Das folgende Beispiel ist ein Sturzdetektor. Bei einem frei fallenden Gegenstand misst der Beschleunigungssensor fast 0 g, weil das Sensorgehäuse und die Masse darin gemeinsam fallen; der anschließende Aufprall erzeugt eine Spitze von mehreren g. Erkennt der Sketch einen freien Fall von mindestens 100 ms und innerhalb einer halben Sekunde danach einen Stoß über 2,5 g, lässt er einen aktiven Summer an GPIO 25 eine Sekunde lang ertönen. 100 ms freier Fall entsprechen einer Fallhöhe von etwa 5 cm (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}Darauf aufbauend kannst du das WLAN des ESP32 nutzen, um zum Beispiel bei einem Sturz eines älteren Angehörigen eine Telegram-Nachricht aufs Handy zu schicken oder die Winkel live auf einer Webseite anzuzeigen. Passe die Schwellen anhand eigener Tests an: Eine vom Tisch fallende Schachtel und ein am Handgelenk getragener Sensor liefern unterschiedliche Spitzen. Zur Auswahl und zum Anschluss eines Summers lies Was ist ein Buzzer?.
MPU6050 mit dem Raspberry Pi Pico (MicroPython)
Auf dem Pico brauchst du keine zusätzliche Bibliothek; die eingebaute I2C-Klasse von MicroPython kann die Register direkt lesen. Schließ den Sensor an den Bus I2C0 an, SDA an GP4 und SCL an GP5. Mit struct.unpack wandeln wir die 14 Byte in sieben vorzeichenbehaftete 16-Bit-Zahlen um; ">" bedeutet Big-Endian (höherwertiges Byte zuerst), "h" eine vorzeichenbehaftete 16-Bit-Zahl. Der Code gibt zuerst die gefundenen I2C-Adressen aus; fehlt 0x68 in der Liste, prüfe die Verdrahtung. Der Einfachheit halber haben wir keine Kalibrierung eingebaut; bei Bedarf übernimmst du die Mittelwertbildung aus dem Arduino-Sketch genauso.
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)Projektideen mit dem MPU6050
- Digitale Wasserwaage: Zeige Roll- und Nickwinkel auf einem OLED-Display mit einer wandernden Blase an.
- Servo per Bewegung steuern: Neigst du den Sensor in der Hand, dreht sich ein Servomotor auf denselben Winkel; ideal für einen Roboterarm oder einen Kamerakopf.
- Spiel per Neigung: Spiele Pong oder ein Labyrinthspiel, indem du die Platine neigst, statt einen Joystick zu benutzen.
- Selbstbalancierender Roboter: Verarbeite den Nickwinkel mit einem PID-Regler und halte den Roboter mit DC-Motoren am L298N aufrecht.
- Schrittzähler: Erfasse das Gehen, indem du die regelmäßigen Spitzen der Gesamtbeschleunigung zählst.
- Vibrationslogger: Miss das Rütteln einer Maschine oder Waschmaschine und gib eine Warnung aus, wenn ein Grenzwert überschritten wird.
Häufige Fehler und Lösungen
| Symptom | Mögliche Ursache | Lösung |
|---|---|---|
| begin() liefert false ("MPU6050 not found") | Verdrahtungsfehler, falsche Adresse oder nachgebauter Chip | Adresse mit I2C-Scanner suchen; ist WHO_AM_I nicht 0x68 (zum Beispiel 0x70), den Code ohne Bibliothek verwenden |
| Alle Werte sind 0 | Sensor im Schlafmodus | 0 in Register 0x6B schreiben |
| Werte sind -1 oder frieren ein | Wackelkontakt, langer I2C-Bus | Kabel kürzen, Stiftleiste anlöten |
| Winkel driftet im Stillstand | Gyroskop-Offset nicht korrigiert | Beim Start in Ruhe kalibrieren |
| Winkel springt bei Bewegung | Nur der Beschleunigungssensor wird genutzt | Komplementärfilter ergänzen |
| Yaw driftet ständig | Der MPU6050 hat keinen Kompass | Magnetometer wie den QMC5883L ergänzen oder einen 9-Achsen-Sensor nutzen |
| Roll wird unbrauchbar, wenn pitch ±90° erreicht | Singularität der Euler-Winkel | Diesen Bereich meiden oder die Quaternion-Ausgabe des DMP nutzen |
Trotz seines niedrigen Preises öffnet der MPU6050 die Tür zur Bewegungsmessung: Lerne zuerst die Rohwerte kennen, berechne dann die Winkel und glätte sie zum Schluss mit einem Filter. Weitere I2C-Sensoren und ihre Einsatzgebiete findest du im Arduino-Sensoren-Ratgeber. In der BlueGrays-App findest du Projekte zu Servosteuerung, I2C-Displays, Joystick und Robotern mit Schritt-für-Schritt-Schaltplan und Code, die du mit dem MPU6050 kombinieren kannst.
Häufige Fragen
Wofür wird der MPU6050 verwendet?
Der MPU6050 misst Neigung, Drehgeschwindigkeit und Beschleunigung eines Objekts. Er steckt in selbstbalancierenden Robotern, Drohnen und Gimbals, Schrittzählern, Sturz- und Erschütterungserkennung sowie in bewegungsgesteuerten Spielen.
Ist die Adresse des MPU6050 0x68 oder 0x69?
Ist der Pin AD0 offen oder mit GND verbunden, lautet die Adresse 0x68; liegt er an 3,3 V, lautet sie 0x69. Auf der GY-521-Platine ist AD0 über einen Widerstand auf GND gezogen, daher ist 0x68 die Standardadresse. Sicher bist du, wenn du einen I2C-Scanner-Sketch laufen lässt.
Funktioniert der MPU6050 mit 5 V?
Der MPU6050-Chip selbst verträgt höchstens 3,46 V, dank des Spannungsreglers auf der GY-521-Platine kann der VCC-Pin aber mit 5 V versorgt werden. Die I2C-Leitungen bleiben auf 3,3-V-Pegel, den der Arduino Uno problemlos liest. Nackte Platinen ohne Regler dürfen keine 5 V bekommen.
Wie berechnet man Winkel mit dem MPU6050?
Im Ruhezustand ergeben sich die Winkel aus dem Beschleunigungssensor mit roll = atan2(ay, az) und pitch = atan2(−ax, √(ay² + az²)). Für genaue Werte in Bewegung wird die Winkelgeschwindigkeit des Gyroskops über die Zeit integriert und mit einem Komplementär- oder Kalman-Filter mit dem Beschleunigungswinkel kombiniert.
Kann der MPU6050 den Gierwinkel (yaw) messen?
Für kurze Zeit ja: Yaw lässt sich berechnen, indem man die Winkelgeschwindigkeit der Z-Achse integriert. Da der MPU6050 aber kein Magnetometer hat, driftet yaw mit der Zeit und kennt keine absolute Richtung (Norden). Für eine stabile Richtung brauchst du einen Kompasssensor wie den QMC5883L oder eine 9-Achsen-IMU.
Was ist der Unterschied zwischen MPU6050 und MPU9250?
Der MPU6050 ist ein 6-Achsen-Sensor mit Beschleunigungssensor und Gyroskop. Der MPU9250 hat zusätzlich ein 3-Achsen-Magnetometer, ist also ein 9-Achsen-Sensor und kann yaw ohne Drift messen; außerdem unterstützt er SPI. Da der MPU9250 nicht mehr hergestellt wird, greift man bei neuen Projekten zu Nachfolgern wie dem ICM-20948.
Projekte, die du danach bauen kannst
Alle Projekte ansehen
Verwendung von Servomotoren
Grundlegendes Anwendungsprojekt, das den Servomotor nacheinander in 0°-, 90°- und 180°-Winkel positioniert. Lehrt die Servo-Bibliothek und die Logik der Winkelsteuerung.

SG90 Servo-Winkelsteuerung mit Poti
Servomotor (SG90) Steuerung mit Potentiometer Das Hauptziel dieses Projekts ist die präzise Steuerung der Winkelposition eines Servomotors in Echtzeit mit Hilfe einer analogen Eingangseinheit, dem Potentiometer. Das Projekt ist ein grundlegendes technisches Beispiel, um die Logik der Analog-Digital-Wandlung (ADC) und der Signalabbildung zu verstehen. Betriebslogik: Lesen analoger Daten: Wenn der Benutzer das Potentiometer dreht, wird als Ergebnis der Widerstandsänderung ein Spannungssignal zwis

Servo-Steuerung mit Joystick
Schwenk-Neige-Projekt, das zwei Servomotoren in X- und Y-Achse unabhängig voneinander mit einem Joystick-Modul steuert. Lehrt die Logik der Joystick-Servo-Integration und der Positionsverfolgung.

ESP32-Servomotor (Steuerung über Potentiometer)
In diesem Projekt steuern wir einen SG90-Servomotor mit einem Potentiometer. Wir stellen den Servowinkel ein, indem wir den vom Potentiometer gelesenen Analogwert auf den Bereich von 0 bis 180 Grad abbilden. Dank der ESP32Servo-Bibliothek kann jeder GPIO-Pin des ESP32 ein PWM-Signal erzeugen. Dies ist eine grundlegende Steuerungsmethode für Roboterarme, Kamera-Gimbals und automatische Türmechanismen.

Pong-Spiel - SSD1306
Das klassische Pong-Spiel, gebaut mit Arduino und SSD1306 OLED-Display, ausgestattet mit einer autonomen künstlichen Intelligenz (CPU) Gegner, die sofort verfolgt die Bewegungen des Balls und reagiert

Verwendung des LCD-Bildschirms mit I2C
Dank des I2C-Moduls druckt das Projekt Nachrichten, indem es den LCD-Bildschirm mit nur 2 Kabeln (SDA, SCL) steuert. Es lehrt, wie man Pins mit dem I2C-Protokoll speichern kann.

ESP32 I2C-LCD-Display (16×2)
In diesem Projekt zeigen wir Text an, indem wir ein 16x2-Zeichen-LCD-Display über das I2C-Protokoll an den ESP32 anschließen. Dank I2C können wir das Display mit nur zwei Datenpins (SDA und SCL) steuern; die Verschwendung von 6+ Pins bei einer klassischen parallelen Verbindung entfällt. Der Code schreibt in die erste Zeile eine feste Meldung und in die zweite Zeile einen Zähler, der sich jede Sekunde erhöht. Außerdem lassen wir zu Beginn den I2C-Scanner laufen und geben die Adresse des Displays

Roboter zur Hindernisvermeidung
Wie wäre es, ein intelligentes Fahrzeug zu bauen, das seinen Weg selbst findet? Der Obstacle Avoiding Robot scannt dank des Ultraschallsensors vor ihm ständig seine Umgebung. Wenn er auf ein Hindernis
Weitere Artikel
Lerne, den MPU6050 mit Beschleunigungssensor und Gyroskop an den Arduino anzuschließen, Rohwerte zu lesen, den Sensor zu kalibrieren, Neigungswinkel zu berechnen und sie mit einem Komplementärfilter zu glätten – inklusive ESP32-Sturzalarm und Pico-Code.

