MPU6050 Beschleunigungssensor und Gyroskop

Über den Beitrag

Der MPU6050, oder genauer gesagt das darauf basierende Modul, ist ein 3-Achsen Beschleunigungssensor und 3-Achsen Gyroskop. Ebenso misst der MPU6050 die Temperatur. Es ist schon ziemlich viel über diesen Sensor geschrieben worden, aber vielleicht kann ich euch mit diesem Beitrag den einen oder anderen neuen Aspekt vermitteln, wie z.B. die Interrupt Programmierung.

Der Beitrag ist folgendermaßen gegliedert:

Wer einfach nur schnell „losmessen“ will, der kann direkt zum Teil mit den Bibliotheken gehen.

Grundlagen

Das Messprinzip des MPU6050

Im Zusammenhang mit Beschleunigungssensoren stoßt ihr häufig auf die Begriffe „3-Achsen“, „6-Achsen“ oder gar „9-Achsen Sensoren“. Wir verlassen dabei nicht die dreidimensionale Welt. Vielmehr kommen ein oder mehrere, in drei Dimensionen wirksame Sensoren parallel zum Einsatz. Und das sind im Falle des MPU6050 ein Beschleunigungs- und ein Gyroskop. 9-Achsen Sensoren haben meistens noch einen Erdmagnetsensor.

Gyroskope

Das klassische Gyroskop wird auch Kreiselinstrument genannt. Einen Kreisel kennt jeder und auch seine Wirkung. Die Drehung stabilisiert ihn und der Versuch, seine Drehachse zu kippen, erfordert Kraft. Und genau das kann man sich zunutze machen, um die Lage eines Gegenstandes (z.B. eines Flugzeuges oder Schiffes) im Raum zu bestimmen. Gegenüber klassischen Kreiseln ist bei Gyroskopen der Kreisel in einem Rahmen angebracht. Hier als Spielzeug:

Ein Spielzeug Gyroskop
Ein Spielzeug Gyroskop

Im MPU6050 gibt es natürlich keinen Kreisel (und glücklicherweise müsst ihr ihn auch nicht aufziehen ;-)). In solchen Sensoren befinden sich „Micro-Electric-Mechanical Systems“ (MEMS). Im Fall von Gyroskopen sind das beweglich aufgehängte Körper, die bei Beschleunigung ihre Lage gegenüber einem festen Rahmen verändern. Die Abstandsänderung führt zu einer Änderung der Kapazität. Im Prinzip sieht das so aus:

Das Messprinzip des MPU6050
Das Messprinzip des MPU6050

Eine ältere Technik beruht auf dem Piezoeffekt, nutzt also Druckänderungen als Messprinzip.

Beschleunigungssensor

Ein Beschleunigungssensor funktioniert nach demselben Prinzip. Der Unterschied ist lediglich, dass der Beschleunigungssensor die Beschleunigung in Richtung der x-, y- und z-Achse detektiert, wohingegen das Gyroskop die Bewegung um die Achsen detektiert. Wenn das Modul in Ruhe ist, liefert das Gyroskop für x, y und z den Wert Null. Der Beschleunigungssensor hingegen detektiert die Erdbeschleunigung auch im Ruhezustand (in z-Richtung, wenn das Modul flach liegt).

Die Module haben die Lage der x- und y-Achse aufgedruckt. Die z-Achse steht senkrecht auf dem Modul.

MPU6050 Modul
MPU6050 Modul

Technische Daten / Eigenschaften

Die wichtigsten technischen Daten des MPU6050 sind:

  • Spannungsversorgung (VDD/GND): das Modul besitzt einen LDO Spannungskonverter (siehe auch hier), kann also sowohl mit 3,3 V wie auch mit 5 V versorgt werden. Der „nackte“ IC sollte mit 2,375 – 3,46 V versorgt werden.
  • Stromverbrauch (Modul): ca. 5,1 mA, im Sleep-Mode ca. 1,4 mA (eigene Messungen). Wenn ihr die LED entfernt, reduziert sich der Verbrauch auf 3,7 mA bzw. 33 µA im Sleep-Mode.
  • Beschleunigungssensor: 16-Bit Auflösung, Messbereiche +/- 2, 4, 8 oder 16 g; mit g = Erdbeschleunigung, nicht Gramm!
  • Gyroskop: 16-Bit Auflösung, Messbereiche: +/- 250, 500, 1000 oder 2000°/s.
  • Kommunikation (SDA/SCL): I2C, Adresse 0x68 (AD0 = GND oder unverbunden) oder 0x69 (AD0 = HIGH)
  • Interruptfunktion: „Data Ready“, „Free Fall“, Beschleunigungslimit;
  • Anschluss weiterer Sensoren (XDA / XCL): darauf werde ich nicht eingehen

Weitere Informationen findet ihr im Datenblatt und der Register Map.

Ansteuerung des MPU6050 ohne Bibliothek

Der Minimalsketch

Wenn ihr mit den Voreinstellungen (+/-2 g, +/-250°/s) leben könnt, dann kommt ihr vielleicht mit dem folgenden Sketch (Basis: Arduino Playground) aus. 

Ich werde nicht alle Details des Sketches durchgehen, nur so viel:

  • zunächst wird der MPU6050 durch den Eintrag einer Null in das „Power Management 1“ Register geweckt
  • der MPU6050 erzeugt kontinuierlich Ergebnisse für Beschleunigung, Gyroskop und Temperatur
  • da die Ergebnisregister direkt aufeinanderfolgen, lassen sie sich bequem in einem Rutsch auslesen
  • es werden nur Rohdaten ausgegeben (-32767 bis + 32767)
#include "Wire.h" 

#define MPU6050_ADDR 0x68 // Alternatively set AD0 to HIGH  --> Address = 0x69

int16_t accX, accY, accZ, gyroX, gyroY, gyroZ, tRaw; // Raw register values (accelaration, gyroscope, temperature)
char result[7]; // temporary variable used in convert function

void setup() {
  Serial.begin(9600);
  Wire.begin();
  Wire.beginTransmission(MPU6050_ADDR);
  Wire.write(0x6B); // PWR_MGMT_1 register
  Wire.write(0); // wake up!
  Wire.endTransmission(true);
}
void loop() {
  Wire.beginTransmission(MPU6050_ADDR);
  Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. 
                               // As a result, the connection is kept active.
  Wire.requestFrom(MPU6050_ADDR, 14, true); // request a total of 7*2=14 registers
  
  // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same int16_t variable
  accX = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
  accY = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
  accZ = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
  tRaw = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
  gyroX = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
  gyroY = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
  gyroZ = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)
  
  Serial.print("AcX = "); Serial.print(toStr(accX));
  Serial.print(" | AcY = "); Serial.print(toStr(accY));
  Serial.print(" | AcZ = "); Serial.print(toStr(accZ));
  // from data sheet:
  Serial.print(" | tmp = "); Serial.print((tRaw + 12412.0) / 340.0);
  Serial.print(" | GyX = "); Serial.print(toStr(gyroX));
  Serial.print(" | GyY = "); Serial.print(toStr(gyroY));
  Serial.print(" | GyZ = "); Serial.print(toStr(gyroZ));
  Serial.println();
  
  delay(1000);
}

char* toStr(int16_t character) { // converts int16 to string and formatting
  sprintf(result, "%6d", character);
  return result;
}

 

Unten seht ihr die Ausgabe. Da der MPU6050 flach auf in seiner x/y-Ebene lag, sollten eigentlich alle Ergebnisse mit Ausnahme der Beschleunigung in z-Richtung (Erdbeschleunigung) Null ergeben. Das ist nicht der Fall, aber qualitativ ist das Ergebnis schon nicht schlecht.

Ihr könnt die Ausgangswerte anpassen, indem ihr Offset Werte in dafür vorgesehene Register eintragt. Einige Bibliotheken haben das implementiert, andere nicht.

Ausgabe des Minimalsketches für den MPU6050
Ausgabe des Minimalsketches für den MPU6050

Der Vollständigkeit halber habe ich hier noch die Beschaltung abgebildet. Die LED und die Leitung zum Interrupt brauchen wir später noch. Pull-ups für die I2C Leitungen (3.3 V) sind auf dem Modul integriert.

Verkabelung des MPU6050 am Arduino
Verkabelung des MPU6050 am Arduino

Der erweiterte Minimalsketch

Ich habe dem Minimalsketch dann ein paar Extras spendiert:

  • setAccRange() legt den Messbereich für die Beschleunigung fest
  • setGyrRange() legt den Messbereich für das Gyroskop fest
  • MCP6050_wakeUp() weckt den MPU6050
    • Er braucht etwas Zeit zum Aufwachen, erst nach 30 ms habe ich sinnvolle Gyroskopwerte ermitteln können.
  • MCP6050_sleep schickt den MPU6050 in den Schlaf

Durch zwischenzeitlichen Schlaf habe ich den Stromverbrauch mit dem folgenden Sketch von 5,2 auf 1,4 mA drücken können. Wenn ihr dann noch die LED entfernt, geht der Verbrauch auf unter 0,1 mA. 

Wer den Sketch hinsichtlich der Registereinstellungen nachvollziehen möchte, der schaue in die Register Map.

#include "Wire.h" 

#define MPU6050_ADDR              0x68 // Alternatively set AD0 to HIGH  --> Address = 0x69
#define MPU6050_GYRO_CONFIG       0x1B ///< Gyro specfic configuration register
#define MPU6050_ACCEL_CONFIG      0x1C
#define MPU6050_ACCEL_XOUT_H      0x3B
#define MPU6050_PWR_MGT_1         0x6B
#define MPU6050_SLEEP             0x06

typedef enum {
  MPU6050_ACC_RANGE_2G,  // +/- 2g (default)
  MPU6050_ACC_RANGE_4G,  // +/- 4g
  MPU6050_ACC_RANGE_8G,  // +/- 8g
  MPU6050_ACC_RANGE_16G // +/- 16g
} mpu6050_acc_range;

typedef enum {
  MPU6050_GYR_RANGE_250,  // +/- 250 deg/s (default)
  MPU6050_GYR_RANGE_500,  // +/- 500 deg/s
  MPU6050_GYR_RANGE_1000, // +/- 1000 deg/s
  MPU6050_GYR_RANGE_2000  // +/- 2000 deg/s
} mpu6050_gyr_range;

int16_t accX, accY, accZ, gyroX, gyroY, gyroZ, tRaw; // Raw register values (accelaration, gyroscope, temperature)
char result[7];

void setup() {
  Serial.begin(9600);
  Wire.begin();
  MPU6050_wakeUp();
  setAccRange(MPU6050_ACC_RANGE_16G);
  setGyrRange(MPU6050_GYR_RANGE_250);
}

void loop() {
  MPU6050_wakeUp();
  Wire.beginTransmission(MPU6050_ADDR);
  Wire.write(MPU6050_ACCEL_XOUT_H); // starting with register ACCEL_XOUT_H
  Wire.endTransmission(false); // the parameter indicates that the Arduino will send a restart. 
                               // As a result, the connection is kept active.
  Wire.requestFrom(MPU6050_ADDR, 7*2, true); // request a total of 7*2=14 registers
  
  // "Wire.read()<<8 | Wire.read();" means two registers are read and stored in the same variable
  accX = Wire.read()<<8 | Wire.read(); // reading registers: 0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
  accY = Wire.read()<<8 | Wire.read(); // reading registers: 0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
  accZ = Wire.read()<<8 | Wire.read(); // reading registers: 0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
  tRaw = Wire.read()<<8 | Wire.read(); // reading registers: 0x41 (TEMP_OUT_H) and 0x42 (TEMP_OUT_L)
  gyroX = Wire.read()<<8 | Wire.read(); // reading registers: 0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
  gyroY = Wire.read()<<8 | Wire.read(); // reading registers: 0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
  gyroZ = Wire.read()<<8 | Wire.read(); // reading registers: 0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)
  MPU6050_sleep();
  
  // print out data
  Serial.print("AcX = "); Serial.print(toStr(accX));
  Serial.print(" | AcY = "); Serial.print(toStr(accY));
  Serial.print(" | AcZ = "); Serial.print(toStr(accZ));
  // the following equation was taken from the documentation [MPU-6000/MPU-6050 Register Map and Description, p.30]
  Serial.print(" | tmp = "); Serial.print((tRaw + 12412.0) / 340.0);
  Serial.print(" | GyX = "); Serial.print(toStr(gyroX));
  Serial.print(" | GyY = "); Serial.print(toStr(gyroY));
  Serial.print(" | GyZ = "); Serial.print(toStr(gyroZ));
  Serial.println();
  
  delay(1000);
}

char* toStr(int16_t i) { // int16 to string plus output format
  sprintf(result, "%6d", i);
  return result;
}

void setAccRange(mpu6050_acc_range range){
  writeRegister(MPU6050_ACCEL_CONFIG, range<<3);
}

void setGyrRange(mpu6050_gyr_range range){
  writeRegister(MPU6050_GYRO_CONFIG, range<<3);
}

void MPU6050_wakeUp(){
  writeRegister(MPU6050_PWR_MGT_1, 0); 
  delay(30); // give him time to wake up, gyro needs quite a while to stabilize;
}

void MPU6050_sleep(){
  writeRegister(MPU6050_PWR_MGT_1, 1<<MPU6050_SLEEP); 
}

void writeRegister(uint16_t reg, byte value){
  Wire.beginTransmission(MPU6050_ADDR);
  Wire.write(reg); 
  Wire.write(value); 
  Wire.endTransmission(true);
}

 

Da ich in dem Beispiel die Range +/- 16 g gewählt habe, gehen die Messwerte für die Beschleunigung in z-Richtung auf ein Achtel zurück:

Ausgabe des erweiterten Minimalsketches
Ausgabe des erweiterten Minimalsketches

Ich hätte noch weitere Funktionen einfügen können, aber irgendwann wird es unübersichtlich und dann sind Bibliotheken die bessere Wahl.

Umrechnung der Rohdaten

Für die Umrechnung der Beschleunigungsrohdaten (rawValue) in g gilt:

\text{g-value}\;[\text{g}]=\frac{\vert range \vert\cdot rawV\!alue}{32768}

Die Umrechnung der Gyroskop Daten in Winkelgeschwindigkeiten erfolgt nach folgender Formel (aus dem Datenblatt abgeleitet):

\omega\;[\text{°\!/s}] = \frac{\vert range \vert\ \cdot rawV\!alue}{131\cdot 250}

Interrupts

Vielleicht macht ja das folgende, ganz kurze Video des „Magic Push Buttons“ Appetit auf die Interrupt Funktion, die übrigens in keiner Bibliothek, die ich mir angeschaut habe, implementiert war.

Wie ihr seht, bringt ein Druck auf den Taster die LED zum Leuchten – obwohl der Taster gar nicht verbunden ist. Die Lösung des Rätsels ist: die Erschütterung beim Drücken des Tasters reicht aus, um einen entsprechend empfindlich eingestellten „wake on motion“ Interrupt auszulösen. Ich hätte also genauso gut auf den Tisch klopfen können. Der Arduino Sketch sorgt dafür, dass bei Registrierung des Interrupts die LED für eine Sekunde leuchtet.

Ihr könnt auch andere tolle Sachen mit diesem Interrupt anstellen. Zum Beispiel könnt ihr ein Gerät realisieren, dass sich anschaltet, wenn ihr es in die Hand nehmt. Wenn es herumliegt, soll es schlafen. Kein Problem, ihr müsst dann nur das Interrupt Signal als Wecksignal für den Microcontroller nutzen. Siehe dazu auch mein Beitrag über Sleep Modes.

Das Problem mit nicht dokumentierten Registern

Im Datenblatt des MPU6050 ist eine Prozedur beschrieben, wie Interrupts einzurichten sind. Das Problem ist nur, dass sie nicht funktioniert. Beim Nachforschen stieß ich auf diese Seite, die erklärt, wie man es richtig macht. Dabei werden sowohl im Datenblatt nicht dokumentierte Register benutzt, wie auch nicht dokumentierte Bits dokumentierter Register.

Interessanterweise gibt es fleißige Leute, die im „reverse engineering“ Verfahren die Dokumentationsarbeit nachgeholt haben. Das Ergebnis, also die vollständige Register Map, gibt es hier.

Der Interrupt Sketch

Ich habe also die Anleitung genommen und darauf basierend den gleich folgenden Sketch geschrieben. Ein paar der in der Anleitung vorgeschlagenen Schritte, braucht man meiner Meinung nach nicht. Ich habe sie eingefügt aber auskommentiert.

Den Sketch im Detail zu erklären, würde den Rahmen sprengen. Nur ein paar Anmerkungen:

  • setInterrupt(x) aktiviert den Interrupt; x bestimmt die Sensitivität mit einem Wert von 1 (4 mg = „4 milli-g“, nicht Milligramm) bis 255 (1024 mg)
    • bei 255 muss man den MPU6050 schon kräftig schütteln, um den Interrupt auszulösen
  • wenn ihr den Interrupt Pin active-low einstellen wollt, dann entkommentiert Zeile 41
  • mit der Latch Funktion könnt ihr einstellen, dass der Interrupt Pin bis zum nächsten Lesevorgang aktiv bleibt. Ändert dazu Zeile 41 in: writeRegister(MPU6050_INT_PIN_CFG, 1<<MPU6050_LATCH_INT_EN)
  • Kombi von active-low und latch: writeRegister(MPU6050_INT_PIN_CFG, ((1<<MPU6050_ACTL) | (1<<MPU6050_LATCH_IN_EN))

Hier nun der Sketch:

#include "Wire.h" 

#define MPU6050_ADDR              0x68 // Alternatively set AD0 to HIGH  --> Address = 0x69
#define MPU6050_ACCEL_CONFIG      0x1C // Accelerometer Configuration Register
#define MPU6050_PWR_MGT_1         0x6B // Power Management 1 Register
#define MPU6050_INT_PIN_CFG       0x37 // Interrupt Pin / Bypass Enable Configuration Register
#define MPU6050_INT_ENABLE        0x38 // Interrupt Enable Register
#define MPU6050_LATCH_INT_EN      0x05 // Latch Enable Bit for Interrupt 
#define MPU6050_ACTL              0x07 // Active-Low Enable Bit
#define MPU6050_WOM_EN            0x06 // Wake on Motion Enable bit
#define MPU6050_WOM_THR           0x1F // Wake on Motion Threshold Register
#define MPU6050_MOT_DUR           0x20 // Motion Detection Duration Register
#define MPU6050_ACCEL_INTEL_CTRL  0x69 // Accelaration Interrupt Control Register
#define MPU6050_SIGNAL_PATH_RESET 0x68 // Signal Path Reset Register

byte interruptPin=2;
byte ledPin=10;
volatile bool accEvent = false;

void setup() {
  Wire.begin();
  writeRegister(MPU6050_PWR_MGT_1, 0);
  setInterrupt(1); // set Wake on Motion Interrupt / Sensitivity; 1(highest sensitivity) - 255
  pinMode(ledPin, OUTPUT);
  pinMode(interruptPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(interruptPin), motion, RISING);
}

void loop() {
   if(accEvent){
    digitalWrite(ledPin, HIGH);
    delay(1000);
    digitalWrite(ledPin, LOW);
    accEvent = false;
    attachInterrupt(digitalPinToInterrupt(interruptPin), motion, RISING);   
  }
}

void setInterrupt(byte threshold){
//writeRegister(MPU6050_SIGNAL_PATH_RESET, 0b00000111);  // not(?) needed
//writeRegister(MPU6050_INT_PIN_CFG, 1<<MPU6050_ACTL); // 1<<MPU6050_LATCH_INT_EN
  writeRegister(MPU6050_ACCEL_CONFIG, 0b00000001);
  writeRegister(MPU6050_WOM_THR, threshold); 
  writeRegister(MPU6050_MOT_DUR, 0b00000001);  // set duration (LSB = 1 ms)
//writeRegister(MPU6050_ACCEL_INTEL_CTRL, 0x15);  // not needed (?)
  writeRegister(MPU6050_INT_ENABLE, 1<<MPU6050_WOM_EN);
}

void writeRegister(uint16_t reg, byte value){
  Wire.beginTransmission(MPU6050_ADDR);
  Wire.write(reg);
  Wire.write(value);
  Wire.endTransmission();
}

void motion(){
  accEvent = true;
  detachInterrupt(digitalPinToInterrupt(interruptPin));
}

 

Bibliotheken für den MPU6050

Keine Bibliothek, die ich gefunden habe, nutzt die Möglichkeiten des MPU6050 wirklich umfassend aus. Die Interrupts sind dabei nur Beispiel. Es reizt mich schon, eine vollständigere Bibliothek zu erstellen. Der Aufwand ist allerdings erheblich und die meisten von euch werden wahrscheinlich mit den Basisfunktionen auskommen. Vielleicht komme ich noch mal darauf zurück.

Adafruit MPU6050

Die vollständigste Bibliothek, die ich gefunden habe, ist die von Adafruit. Ihr könnt sie hier direkt von Github herunterladen oder über die Bibliotheksverwaltung in der Arduino IDE installieren.

Basic reading Sketch

Am besten startet ihr mit dem mitgelieferten Beispielsketch basic_readings.ino. Er liest die Beschleunigungswerte, die Temperatur und die Gyroskop Werte. Ihr könnt die Messbereiche und einen Low-Pass Filter (setFilterBandwith()) für die Sensoren einstellen. Auf den Filter komme ich weiter unten noch zu sprechen. Hier erst einmal der unveränderte Sketch:

// Basic demo for accelerometer readings from Adafruit MPU6050

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

Adafruit_MPU6050 mpu;

void setup(void) {
  Serial.begin(115200);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("Adafruit MPU6050 test!");

  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");

  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
  Serial.print("Accelerometer range set to: ");
  switch (mpu.getAccelerometerRange()) {
  case MPU6050_RANGE_2_G:
    Serial.println("+-2G");
    break;
  case MPU6050_RANGE_4_G:
    Serial.println("+-4G");
    break;
  case MPU6050_RANGE_8_G:
    Serial.println("+-8G");
    break;
  case MPU6050_RANGE_16_G:
    Serial.println("+-16G");
    break;
  }
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);
  Serial.print("Gyro range set to: ");
  switch (mpu.getGyroRange()) {
  case MPU6050_RANGE_250_DEG:
    Serial.println("+- 250 deg/s");
    break;
  case MPU6050_RANGE_500_DEG:
    Serial.println("+- 500 deg/s");
    break;
  case MPU6050_RANGE_1000_DEG:
    Serial.println("+- 1000 deg/s");
    break;
  case MPU6050_RANGE_2000_DEG:
    Serial.println("+- 2000 deg/s");
    break;
  }

  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
  Serial.print("Filter bandwidth set to: ");
  switch (mpu.getFilterBandwidth()) {
  case MPU6050_BAND_260_HZ:
    Serial.println("260 Hz");
    break;
  case MPU6050_BAND_184_HZ:
    Serial.println("184 Hz");
    break;
  case MPU6050_BAND_94_HZ:
    Serial.println("94 Hz");
    break;
  case MPU6050_BAND_44_HZ:
    Serial.println("44 Hz");
    break;
  case MPU6050_BAND_21_HZ:
    Serial.println("21 Hz");
    break;
  case MPU6050_BAND_10_HZ:
    Serial.println("10 Hz");
    break;
  case MPU6050_BAND_5_HZ:
    Serial.println("5 Hz");
    break;
  }

  Serial.println("");
  delay(100);
}

void loop() {

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

  /* Print out the values */
  Serial.print("Acceleration 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");

  Serial.print("Temperature: ");
  Serial.print(temp.temperature);
  Serial.println(" degC");

  Serial.println("");
  delay(500);
}

 

Beachtet, dass die Ergebnisse in m/s2 bzw. rad/s ausgegeben werden. Hier habe ich das Modul einmal mit seiner z-Achse, einmal mit seiner x-Achse und schließlich mit seiner y-Achse senkrecht ausgerichtet:

Ausgabe von basic_readings.ino
Ausgabe von basic_readings.ino

Falls ihr Winkelgeschwindigkeiten in Grad/s umrechnen wollt:

2\pi\cdot rad = 360° \;\; \Rightarrow\;\;1°=\frac{2\pi\cdot rad}{360}

Für die Umrechnung der Beschleunigungswerte in g, teilt die Werte durch 9,81.

Plotter Sketch

Gerade bei Winkelgeschwindigkeiten möchtet Ihr vielleicht nicht nur Einzelwerte ermitteln, sondern den Verlauf verfolgen. Dafür eignet sich der Sketch plotter.ino, den ich hier auch unverändert abdrucke:

// Basic demo for accelerometer readings from Adafruit MPU6050

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

Adafruit_MPU6050 mpu;

void setup(void) {
  Serial.begin(115200);
  while (!Serial) {
    delay(10); // will pause Zero, Leonardo, etc until serial console opens
  }

  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }

  mpu.setAccelerometerRange(MPU6050_RANGE_16_G);
  mpu.setGyroRange(MPU6050_RANGE_250_DEG);
  mpu.setFilterBandwidth(MPU6050_BAND_21_HZ);
  Serial.println("");
  delay(100);
}

void loop() {

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

  /* Print out the values */
  Serial.print(a.acceleration.x);
  Serial.print(",");
  Serial.print(a.acceleration.y);
  Serial.print(",");
  Serial.print(a.acceleration.z);
  Serial.print(", ");
  Serial.print(g.gyro.x);
  Serial.print(",");
  Serial.print(g.gyro.y);
  Serial.print(",");
  Serial.print(g.gyro.z);
  Serial.println("");

  delay(10);
}

 

Ladet den Sketch hoch und wählt dann anstelle des seriellen Monitors den seriellen Plotter. Hier habe ich den MPU6050 mehrfach um 90° gedreht:

Plotterausgabe
Plotterausgabe

Cycle und Filter Bandwith

Ich möchte noch auf zwei Parameter zu sprechen kommen, deren Wirkung der folgende Sketch illustriert. Dieser Sketch stammt von mir, ist also nicht Teil der Beispielsketche der Bibliothek.

Die Funktion setCycleRate(frequency) bewirkt, dass der MPU6050 in den Schlaf geht und in der vorgegebenen Frequenz (frequency) aufwacht, um einen Satz Messwerte aufzunehmen. Das spart erheblich Strom. Genau genommen legt die Funktion nur die Frequenz fest. Aktiv geschaltet wird sie mit enableCycle(true).  Übergebt ihr „false“, wird sie inaktiv.

Die Funktion setFilterBandwith(bandwith) dämpft die Messwerteschwankung. Wenn ihr den Sketch mit den von mir gewählten Parametern (siehe Zeile 58/84) hochladet und euren MPU6050 kippt, werdet ihr sehen, dass die Messwerte sehr träge reagieren. In Kombination mit der Cycle Funktion solltet ihr die Bandbreite also hoch setzen. Ändert den Wert zum Beispiel auf 260 Hz und schaut, was passiert.

// Basic demo for cycle and filter bandwith from Adafruit MPU6050

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

Adafruit_MPU6050 mpu;

void setup(void) {
  Serial.begin(115200);
  while (!Serial)
    delay(10); // will pause Zero, Leonardo, etc until serial console opens

  Serial.println("Adafruit MPU6050 test!");

  // Try to initialize!
  if (!mpu.begin()) {
    Serial.println("Failed to find MPU6050 chip");
    while (1) {
      delay(10);
    }
  }
  Serial.println("MPU6050 Found!");

  mpu.setAccelerometerRange(MPU6050_RANGE_8_G);
  Serial.print("Accelerometer range set to: ");
  switch (mpu.getAccelerometerRange()) {
  case MPU6050_RANGE_2_G:
    Serial.println("+-2G");
    break;
  case MPU6050_RANGE_4_G:
    Serial.println("+-4G");
    break;
  case MPU6050_RANGE_8_G:
    Serial.println("+-8G");
    break;
  case MPU6050_RANGE_16_G:
    Serial.println("+-16G");
    break;
  }
  mpu.setGyroRange(MPU6050_RANGE_500_DEG);
  Serial.print("Gyro range set to: ");
  switch (mpu.getGyroRange()) {
  case MPU6050_RANGE_250_DEG:
    Serial.println("+- 250 deg/s");
    break;
  case MPU6050_RANGE_500_DEG:
    Serial.println("+- 500 deg/s");
    break;
  case MPU6050_RANGE_1000_DEG:
    Serial.println("+- 1000 deg/s");
    break;
  case MPU6050_RANGE_2000_DEG:
    Serial.println("+- 2000 deg/s");
    break;
  }

  mpu.setFilterBandwidth(MPU6050_BAND_10_HZ);
  Serial.print("Filter bandwidth set to: ");
  switch (mpu.getFilterBandwidth()) {
  case MPU6050_BAND_260_HZ:
    Serial.println("260 Hz");
    break;
  case MPU6050_BAND_184_HZ:
    Serial.println("184 Hz");
    break;
  case MPU6050_BAND_94_HZ:
    Serial.println("94 Hz");
    break;
  case MPU6050_BAND_44_HZ:
    Serial.println("44 Hz");
    break;
  case MPU6050_BAND_21_HZ:
    Serial.println("21 Hz");
    break;
  case MPU6050_BAND_10_HZ:
    Serial.println("10 Hz");
    break;
  case MPU6050_BAND_5_HZ:
    Serial.println("5 Hz");
    break;
  }

  mpu.setCycleRate(MPU6050_CYCLE_5_HZ);
  Serial.print("Cycle rate set to: ");
  switch (mpu.getCycleRate()) {
  case MPU6050_CYCLE_1_25_HZ:
    Serial.println("1.25 Hz");
    break;
  case MPU6050_CYCLE_5_HZ:
    Serial.println("5 Hz");
    break;
  case MPU6050_CYCLE_20_HZ:
    Serial.println("20 Hz");
    break;
  case MPU6050_CYCLE_40_HZ:
    Serial.println("40 Hz");
    break;
  }
  
  mpu.enableCycle(true);
 
  Serial.println("");
  delay(100);
}

void loop() {

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

  /* Print out the values */
  Serial.print("Acceleration 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");

  Serial.print("Temperature: ");
  Serial.print(temp.temperature);
  Serial.println(" degC");

  Serial.println("");
  delay(500);
}

Noch mehr Informationen findet ihr in diesem Adafruit Tutorial zum MPU6050. Außerdem gibt es eine Reihe weiterer Beispielsketche.  

MPU6050 light

Ganz interessant ist auch die Bibliothek MPU6050_light, die ihr hier auf Github findet oder auch über die Arduino IDE installieren könnt. Sie ist sehr einfach gehalten (eben „light“). Dafür aber bietet sie die Möglichkeit, Neigungswinkel auszugeben, die sie aus den (Erd-)Beschleunigungsdaten berechnet. Voraussetzung ist dabei, dass die Bewegungen langsam erfolgen, damit die Erdbeschleunigung die bestimmende Größe ist. Hier eine Ausgabe des Beispielsketches getAngle.ino. Ich habe dabei die xy-Ebene hin- und hergekippt. Das klappt ziemlich gut, wobei ich meine Wasserwaage aber noch nicht entsorgen würde.

Ausgabe von GetAngle.ino der MPU6050 light Library
Ausgabe von GetAngle.ino der MPU6050 light Library

66 thoughts on “MPU6050 Beschleunigungssensor und Gyroskop

  1. Hi Wolfgang! Ich suche nach einer Möglichkeit roll/pitch eines sich übers Wasser bewegenden Bootes zu Messen und mithilfe eines PID-Reglers aktiv zu Steuern. Mein erster Versuch war ein reiner Beschleunigungssensor (ADXL345). Wenn ich das richtig verstanden habe weiß der ja aber nur so lange wo Oben und Unten ist, solange er still gehalten wird. Jetzt habe ich den MPU6050 hier liegen und bekomme meine x/y rad/s und wundere mich ob das ausreichen wird dauerhaft zu bestimmen in welchem Winkel Sensor/Boot liegen.

    1. Hi Simon, wenn du die Himmelsrichtung relativ zu einer Ausgangsrichtung bestimmen willst, dann geht das mit dem Gyroskop in begrenztem Maße. Grad/Zeit * Zeit = Grad. Je kleiner die Zeitabstände, in denen du misst, desto genauer die berechnete Richtung. Aber auf Dauer wird man immer größere Abweichungen bekommen. Eine Hilfe könnte ein Modul mit zusätzlichem Magnetometer sein (MPU9250 oder ICM20948). Theoretisch hat man damit einen Kompass. Das
      hat allerdings auch seine Tücken,wie Kalibrierung, Abhängigkeit von der Neigung und Magnetfeldstärkenschwankungen aufgrund örtlicher Gegebenheiten. Eine ideale Lösung habe ich nicht.

  2. Hallo Wolfgang,
    danke für deinen Beitrag. Ich habe das mal mit einem ATTiny1616 aufgebaut. Dazu habe ich folgende Pins beim ATTiny verwendet:
    SCL Pin 11
    SDA Pin 10
    Interrupt Pin 6
    LED Pin 7
    In deinem Interrupt-Sketch habe ich dann folgende Einstellung gemacht:
    interruptPin=4
    ledPin=5

    Wenn ich dann den GyroSensor bewege, leuchtet die LED leider nicht auf. Die LED ist richtig herum, dass habe ich getestet. Der GyroSensor wird mit 3,3 V versorgt. Kannst du mir sagen, woran das liegen könnte?
    VG Wolfgang

    1. Nachtrag:
      Ich habe jetzt mal statt der Wire.h die TinyMegaI2CMaster.h verwendet. Ich vermute, dass die Kommunikation über SCL und SDA nicht in Ordnung ist. Die TinyMegaI2CMaster.h arbeitet auch mit 400kHz.

      Ich verwende kein Arduino. Ich verwende nur die Arduino-IDE mit der megaTinyCore-Lib, wie hier beschrieben: https://wolles-elektronikkiste.de/en/using-megatinycore.

      1. Hallo Wolfgang,
        von den Anschlüssen her sieht alles richtig aus. Eine kleine Veränderung habe ich gerade noch am Code vorgenommen, und zwar habe detachInterrupt(2) durch detachInterrupt(digitalPinToInterrupt(interruptPin)) ersetzt. Das kann es aber eigentlich nicht gewesen sein. Was du noch mal machen könntest, ist mit einem I2C Scanner zu prüfen, ob der MPU6050 überhaupt erkannt wird bzw. mit welcher Adresse. Hier findest du einen Scanner:
        https://wolles-elektronikkiste.de/i2c-scanner
        Wenn er nicht erkannt wird, dann braucht die Schaltung vielleicht Pull-Up Widerstände für die I2C Leitungen?
        Vielleicht machst du das erst einmal. Wenn es dann immer noch nicht geht, dann probiere ich selbst noch einmal. Ich habe zwar keinen ATtiny1616, aber einen ATtiny1626 oder ATtiny1614.
        VG, Wolfgang

        1. Hallo Wolfgang,
          vielen Dank für deine Antwort.
          Ich habe das mittlerweile mal mit der Lib von Adafruit „Adafruit_MPU6050.h“ versucht und auch Werte erhalten. Die Adresse dort ist auch 0x68. Also der Gyro antwortet und gibt auch Werte zurück. Auch dort ist die Frequenz von 400kHz für den I2C-Bus eingestellt.

          Habe jetzt auch die Lib „TinyMegaI2CMaster.h“ wieder entfernt und stattdessen die Lib „Wire.h“ aktiviert. Parallel dazu habe ich am gleichen Bus ein OLED-Display angeschlossen, damit auch auch mal etwas loggen kann.
          VG Wolfgang

        2. Hallo Wolfgang,
          wenn ich die Interrupt-Leitung entferne, also der ATTiny-Eingang (Pin 6) in der Luft hängt, fängt die LED an zu blinken. Bedeutet für mich, dass der Eingang sich in seinem undefinierten Zustand etwas „einfängt“ und deshalb die Funktion motion() aufgerufen wird. Im Umkehrschluss bedeutet das, dass der Interrupt-Ausgang am Gyro nicht schaltet.
          VG Wolfgang

          1. Hallo Wolfgang,

            ich habe es gerade mal mit einem ATtiny1626 ausprobiert. Zuerst funktionierte es auch nicht bei mir. Bei mir war die Lösung ein kurzes delay an den Anfang von setup() zu setzen, noch vor Wire.begin(). Ein delay(10) hat ausgereicht. Anscheinend braucht es kurze Zeit bis alle Beteiligten Strom haben und bereit sind.

            VG, Wolfgang

            1. Hallo Wolfgang,
              leider funktioniert das bei mir nicht. Ich habe auch mal delay(20) und delay(200) probiert. Leider ohne Erfolg. Auch die OLED-Ansteuerung habe ich herausgenommen.

              Anscheinend verhält sich der ATTiny1616 anders, als der ATTiny1626.
              VG Wolfgang

            2. Hallo Wolfgang,
              du wirst es nicht glauben. Kalte Lötstelle. Ich habe alle Anschlüsse nachgelötet und jetzt funktioniert es.
              Vielen Dank für deine Mühe.
              VG Wolfgang

              1. Hallo Wolfgang,
                das freut mich. Dann ist unsere Welt ja wieder in Ordnung!
                VG, Wolfgang

  3. Hallo, erstmal vielen Dank für den Ausführlichen Bericht über diesen Sensor, jedoch habe ich habe eine sehr entscheidende Frage, woher wird die Range der Rohdaten genommen (-32767 bis + 32767)? Ich habe die Datenblätter durchgelesen und verstehe nicht woher der Wert und mit die Division durch 131 erfolgt. Könnt Ihr mir weiterhelfen?

    1. Hi, die 131 steht auf Seite 12 des Datenblattes in den Electrical Charateristics. Es ist die Sensitivity Scale Factor für die Umrechnung der Bits in Grad/Sekunde. Und da es sich um ein 16 Bit Modul handelt geht die Range von -2^15 bis +2^15, genauer gesagt bis +2^15 – 1 = 32767. Klar?
      Grüße, Wolfgang

  4. Hallo Herr Ewald,

    kann der MPU6050 bei einem Smartring zur Schlaf- und Sportaktivitätsüberwachung verwendet werden? Ich würde den STM32F051K8U7 Mikrocontroller dazu verwenden.

    Danke für Ihre Unterstützung!

    Freundliche Grüße
    Ali Al-janabi

    1. Hallo,
      ich weiß nicht so recht wie ich die Frage beantworten soll, weil mir nicht klar ist, was „bei einem Smartring verwenden“ konkret heißt. Ein MPU6050, den man am Körper trägt, kann registrieren, ob man sich bewegt oder nicht. Das ist einfach. Über bestimmte Muster lässt sich vielleicht sogar analysieren, ob es sich bei der Bewegung um gehen oder Laufen o. ä. handelt. Das ist aber schon extrem aufwendig. Ob man einfach nur herumliegt oder schläft, wird schwierig zu unterscheiden sein. Aber was genau soll der Smartring mit dem MPU6050 machen oder umgekehrt?
      VG, Wolfgang

      1. Lieber Wolfgang,

        der Sensor sollte die folgenden Bewegungen analysieren und erfassen:
        Anwendungsbereiche des Wearable Rings im Medizinbereich

        – Überwachung von Patienten: Die Bewegung von Patienten zu verfolgen
        analysieren, um sicherzustellen, dass sie sich sicher bewegen und nicht
        stützen.
        – Überwachung älterer Menschen oder Menschen mit Behinderung: Um
        sicherzustellen,
        dass diese Menschen sich sicher bewegen und nicht stützen.
        – Rehabilitation: Fortschritte der Patienten zu verfolgen und sicherzustellen,
        dass sie sich auf dem Weg zur Genesung befinden.

        Anwendungsbereiche des Wearable Rings im sportlichen Bereich
        – Laufen: Zur Messung der Schrittfrequenz, Schrittlänge und
        Laufgeschwindigkeit.
        – Schwimmen: Zur Messung von Schwimmzüge, Schwimmgeschwindigkeit und
        zurückgelegte Strecke.
        – Basketball: Zur Messung von Sprunghöhe, Wurfgeschwindigkeit und
        Wurfgenauigkeit.
        – Fußball: Zur Messung von Schussgeschwindigkeit, Laufgeschwindigkeit und
        zurückgelegte Strecke.

        Viele Grüße, Ali

        1. Hallo Ali, d.h. also, wenn ich das richtig verstehe, dann ist dein Plan, einen MPU6050 als Smartring einzusetzen. Gesichert kann ich nur über die technischen Eigenschaften des MPU6050 Aussagen treffen. Und ja ich gehe davon aus, dass man die Beschleunigungs- und Rotationsdaten sicherlich auch auf bestimmte Muster hin untersuchen kann, um Bewegungsarten (Laufen, Springen, Schwimmen, usw hin untersuchen kann. Das ist allerdings eine ganz eigene Wissenschaft für sich. Da kann ich nicht weiterhelfen. Ich gehe davon aus, dass man für diesen Zweck einen schnellen Mikrocontroller mit viel Arbeitsspeicher braucht. Vielleicht gehst du da mit Timo mehr ins Detail. Wenn ihr zustimmt kann ich die e-mail Adressen von euch weitergeben.
          VG, Wolfgang

    2. Moin Herr Al-janabi,

      ich entwickle gerade (was heißt gerade 😀 seit etwa fast einem Jahr) privat einen Smartring. Wie weit sind Sie mit Ihrem Smartring schon gekommen?
      Vielleicht kann man sich ja gemeinsam austauschen über das Projekt?! 😉

      Viele Grüße,
      Timo

      1. Hallo Timo,

        ja gerne!
        Ich habe die Anforderungen des Smartrings zur Schlaf- und Aktivitätsüberwachung (z.B. funktionale Anforderungen, elektrische Anforderungen, technische Anforderungen, …etc.) festgelegt und dann die dafür benötigten Komponenten ausgewählt. Danach habe ich eine Schaltungsplan mit Eagle gemacht und anschließend habe ich die Leiterplatte entwickelt. Am Ende habe ich ein 3D-Design für den Smartring gemacht und die Leiterplatte drauf platziert.

        VG, Ali

  5. Gibt es einen Befehl um die Einbaulage des MPU6050 festzulegen.
    Irgendwo habe ich mal was gelesen, kann es aber nicht wiederfinden.
    Bei meiner Anwendung ist der MPU6050 um 180 Grad vergedreht eingegbaut.
    Jetzt werden natürlich die Werte verkehrt angezeigt, was man theroretisch umrechnen könnte.

    1. Ich denke, bei der Adafruit Bibliothek bleibt nur die Umrechnung. Ich habe keine Funktion gefunden, Man kann natürlich auf GitHub mal freundlich fragen, ob die eine Funktion implementieren möchten.

      Bei dieser Bibliothek hier lassen sich Offsets angeben:
      https://github.com/jarzebski/Arduino-MPU6050
      Aber ob das funktioniert weiß ich nicht. Außerdem hat die Bibliothek seit Jahren kein Update erfahren.

  6. Moin Wolfgang,
    erstmal danke für den Beitrag.

    Ich war auch etwas verwundert, dass Interrupts nicht so wirklich von der Adafruit library unterstützt werden.
    Es gibt allerding noch eine weitere Library für den MPU6050
    Nämlich die von i2cdev die du shcon für die Registermap herangezogen hast:
    https://www.i2cdevlib.com/docs/html/class_m_p_u6050.html

    Die kann schon ne ganze menge mehr als die von Adafruit aber ist auch etwas komplexer im Umgang.

    Gruß

  7. hallo Wolfgang,
    ich verwende zum ersten mal dem MPU6050 als gyro (bisher habe ich den als neigungssensor eingesetzt). In dem jetzigen anwendungsfall (stell dir mal ein kleines RC-auto vor) ist das modul waagerecht eingebaut, dazu ein ESP8266, verbunden an 5V, GND, D3 und D4 (als SDA und SCL), alles funktioniert. Es wird an der adresse x69 angesprochen (AD0 ist mit 3,3V verbunden).
    Wenn ich jetzt die Ax/Ay und Az werte am seriellen monitor ausgebe reagiert das modul und gibt veränderte werte aus wenn ich das auto um die längsachse und die querachse drehe. Beim drehen um die senkrechte (auto steht auf den rädern, modul waagerecht), also Z, tut er das nicht. Das passiert auch wenn das auto auf das heck stelle und dann um die nun senkrecht stehende längsachse des autos drehe. Dann wird auch die drehung um die senkrechte nicht gemessen und nicht ausgegeben. Habe schon zwei module getestet und unzählige sketche, keine änderung. Was kann das sein?

    1. Hallo Georg,
      also mit Ax, Ay, Az meinst du die Gyroskopwerte, richtig? Ich frage das nur weil „A“ meistens für das Accelerometer steht und nicht für das Gyroskop. Ändern sich denn nur die Gyroskopwerte nicht oder ändern sich die Accelerometerwerte auch nicht unter den Bedingungen, die du beschrieben hast? Das mit den Gyroskopwerte ist immer etwas schwierig, weil die sich ja nur ändern, solange du drehst, also Fliehkräfte wirken. Am besten verfolgen kann man die Dinge mit dem Plottersketch.
      …aber du merkst schon – ein richtig gute Antwort habe ich noch nicht.
      VG, Wolfgang

      1. hallo Wolfgang,
        die werte, die ich meine sind als Ax, Ay und Az gekennzeichnet, sie verändern sich aber beim drehen um die gyroachsen dauerhaft, nicht nur während des drehens. Ich habe Deinen minimalsketch mit den SDA,SCL und x69 anpassungen verwendet, habe Dir meine version per email geschickt. Das video mit den gyrobewegungen und den daraus resultierenden werten ist hier ( https://youtu.be/stq5pdIXsvs ) zu sehen…

        gruss georg

        1. Hallo Georg,
          das Video war sehr hilfreich zum Verständnis – mit deinem MPU6050 ist alles in Ordnung. Die „A“-Werte sind die Messwerte des Beschleunigungssensors (Accelerometer). Die „G“-Werte sind die Messwerte des Gyroskops. Der Beschleunigungssensor misst – keine Überraschung – Beschleunigungen, das Gyroskop detektiert Rotationen. Beide messen diese Werte nur so lange wie sie auch auftreten (auch keine Überraschung). Im Ruhezustand sind die Gyroskopwerte idealerweise Null. Aufgrund von Fertigungstoleranzen und Rauschen nicht exakt Null. Bei der Beschleunigung ist das anders, denn die Erdbeschleunigung (1g) ist immer vorhanden. Wenn der Messbereich auf 2g eingestellt ist, dann entspricht +32767 (= 2^15-1) der Beschleunigung +2g und -32767 der Beschleunigung -2g. Liegt dein Sensor flach, dann sind die x- und die y-Achse horizontal- n Richtung dieser Achsen ist die Erbeschleunigung 0. Die z-Achse steht senkrecht und bekommt die Erdbeschleunigung voll „zu spüren“, als 1g = 32767/2 = ~ 16384. Bei dir ist der Wert negativ, d.h. der Sensor liegt falsch herum (was aber kein Problem ist. Wenn du den Sensor flach liegen lässt und um die Senkrechte dreht ändert sich daran nichts. Nur wenn du die Drehung schnell beschleunigst oder bremst wirst du eine Wirkung auf x und y sehen. Wenn du die z-Achse kippst, wirkt die Erdbeschleunigung nur noch zum Teil auf sie – der Wert sinkt. Und je nachdem, ob du die z-Achse in Richtung der x-oder y-Achse kippst, wird sich der Wert für eine der Achsen ändern. Ob der Wert steigt oder sinkt hängt davon ab, ob die geänderte Achse sich gen Himmel oder Boden neigt. Nur wenn dein Sensor frei fällt, wirst du an allen Achsen Null messen.
          Lange Erklärung, aber ich hoffe, damit ist die Funktionsweise des Beschleunigungssensors klar geworden.
          VG, Wolfgang

          1. hallo Wolfgang,
            danke, ja, einiges ist klarer geworden. Der sensor eignet sich demnach für die sensierung der kippwinkel um die x und y achse, nicht als das, was ich unterm „gyro“ verstanden habe, nämlich ein „kreiselkompass“. Trotzdem ist es irritierend, wenn die X und Y werte die beschleunigung anzeigen sollen, bei anschliessenden ruhelage aber nicht auf null zurückgehen und bei einer in welcher richtung auch gehenden bewegung von dem zuletzt vorhandenen wert ausgehen…. Gibt es eigentlich solche kreiselkompassmodule für den arduino?

            1. Ja, die Sensoren können halt nicht unterscheiden ob die Schwerkraft (Erdbeschleunigung) auf sie wirkt oder eine andere Beschleunigung. Auf der ISS würde sich der Sensor so verhalten wie du es wünscht – oder im freien Fall.

              Ein Kreiselkompass für den Arduino ist mir nicht bekannt, aber es gibt Sensoren die Zusätzlich einen Magnetsensor haben. Damit kann man den Mangel ausgleichen, dass man bei Drehung um die Senkrechte (um die z-Achse) immer dieselbe Werte hat.

              Zum Beispiel den MPU9250:
              https://wolles-elektronikkiste.de/mpu9250-9-achsen-sensormodul-teil-1

              Oder den ICM-20948:
              https://wolles-elektronikkiste.de/icm-20948-9-achsensensor-teil-i
              Viel Spaß noch bei deinen Projekten, Wolfgang

              1. ich komme ja aus der „mechanikecke“. Für einen schmied ist jedes problem zunächst mal ein stück eisen auf was er dann draufhaut…
                Wie würde es sich auf die werte um die z-achse (des fahrzeugs) auswirken wenn ich die MPU quasi „auf die ecke“ stelle und das fahrzeug dreht sich? Jede bewegung des sensors müsste sich doch dann auf alle drei achsen – anteilmässig – auswirken, oder?

                1. Das müsste funktionieren. Immer wenn der Winkel zwischen der Richtung, aus der die Kraft wirkt und der Sensorachse gleich ist, hast du die gleiche Wirkung.

                  Manchmal bin ich auch Schmied – wenn mal wieder etwas nicht funktioniert, dann möchte ich auch mit dem Hammer drauf hauen! 🙂

          2. Hallo Wolfgang,
            vielen Dank für die interessanten Ausführungen zum MPU6050 auf dieser Seite. Ich habe noch eine Frage zum Verständnis: Die x- und die y-Achse des IMU-Koordinatensystems liegen beide in der Ebene der Platine. Wenn der Sensor so auf einer waagrechten Fläche/Tischplatte in Ruhe liegt, zeigt die positive Z-Achse senkrecht nach oben. Der Sensor ermittelt keine Beschleunigung in x- und y- Richtung, lediglich der z-Wert zeigt die Erdbeschleunigung. Aber wieso wird hier ein positiver Wert ausgegeben, obwohl die Gravitation ja in negativer z-Richtung wirkt ?
            VG Rainer

            1. Hallo Rainer,

              die Frage ist gar nicht so schlecht! Schau dir das Modell mit den Federn zur Funktion der Sensoren an (Abschnitt Messprinzip). Und jetzt stelle dir vor der Sensor liegt flach auf der Erde (Beschleunigung für x und y = 0). Jetzt beschleunigst du den Sensor in die positive x-Richtung. Wegen der Trägheit des beweglichen Elementes wird die Feder in Richtung der positiven Seite wird gedehnt und die Feder in Richtung der negativen Seite gestaucht. Und jetzt schau auf die z-Achse: Die Schwerkraft zieht nach unten, also in Richtung negativer z-Achse. Das ist damit dasselbe, als wenn du in der Schwerelosigkeit in Richtung positiver z-Achse beschleunigen würdest.

              VG, Wolfgang

            2. Die Frage hat mich noch nicht ganz losgelassen. Hier noch ein weiterer Erklärungsversuch: Der Beschleunigungssensor, auch wenn er so heißt, misst primär keine Beschleunigungen, sondern Kräfte. Wenn du eine Kraft auf den Sensor ausübst und ihn damit Richtung der positiven x-Achse beschleunigst, wirkt durch die Trägheit der Masse eine Kraft in die entgegengesetzte Richtung. Actio gleich Reactio, also Kraft gleich Gegenkraft (drittes Gesetz von Newton). Wenn die z-Achse senkrecht nach oben zeigt, dann wirkt einfach nur die Schwerkraft auf den Sensor, und zwar in Richtung -z. Und das wiederum ist nicht zu unterscheiden von der Kraft, die auf den Sensor wirken würde, wenn du ihn in der Schwerelosigkeit mit 1g in Richtung der positiven z-Achse beschleunigen würdest.
              Oder ganz kurz: Einmal misst du eine Kraft, die durch eine Beschleunigung hervorgerufen wird und einmal schlicht die Schwerkraft.

  8. Hallo Herr Ewald,

    Ich habe eine Frage zu ihrem Script. Ich benutze nämlich den arduino Micro dessen SCL und SDA
    Pins 2 und 3 sind. Vielleicht ist es ihnen schon aufgefallen aber der Pin 2 schon für den int Anschluss benutzt. Ich weiß nicht ob der int Anschluss nötig ist. Da ich vor dem Kapitel mit der Bibliothek auch ohne ausgekommen bin. Aber nach den Kapitel mit der Bibliothek gibt es nur noch Fehler Meldungen.

    Mit einem Uno habe ich es auch schon versucht, allerdings habe ich nur einen sehr alten. Ausser komischen Zeichen und Fragezeichen kommt aber nichts brauchbares heraus und Auch bei den Scripten die ohne Bibliothek auskommen.

    Ich würde mich über eine Rückmeldung freuen.
    LG Mika

    1. Hallo, den Pin 2 benutze ich lediglich im Sketch MPU6050_interrupt.ino als Interruptpin. Wenn Sie keinen Interrupt einsetzen brauchen Sie ihn nicht zu verbinden. Wenn Sie den Interrupt nutzen wollen und Sie brauchen den Pin 2 schon für die I2C Verbindung, dann nehmen Sie einen anderen Interruptpin des Arduino Micro. Ich habe keine Erfahrung mit dem Arduino Micro, aber nachdem was ich gelesen habe, können Sie auf die Pins 0 und 1 ausweichen.
      Wenn komische Zeichen auftauchen, könnte es an der Baudrate liegen. Die Baudrate im Sketch, also Serial.begin(baudrate), muss mit der der Baudrate im seriellen Monitor übereinstimmen. Könnte es das sein?

  9. Hallo Herr Ewald,
    erst mal vielen Dank für die super Unterstützung, die Sie hier anbieten!

    Ich habe eine Frage zum DLPF. Ich habe ihn auf 5Hz eingestellt und das Rauschen der Beschleunigungswerte in Ruhelage sehr gut in den Griff bekommen. Da der Timestamp bei schnellen Messungen mit den Millisekunden nicht hinterher kommt, benutze ich zusätzlich die Methode millis(), um den zeitlichen Abstand zischen den Messungen nachvollziehen zu können. Da mich bei meinen Messungen nur die Beschleunigung in y-Richtung interessiert, ist meine Ausgabe auch alleinig auf diesen Wert mit den zugehörigen Millisekunden beschränkt. Bei einer Baudrate von 38400 bekomme ich alle 6-7 ms einen Ausgabewert für die Beschleunigung des Objekts in y-Richtung. Nun habe ich gelesen, dass die Grenzfrequenz von 5Hz ein Delay von 19ms mit sich bringt. Was bedeutet dies für meine Beschleunigungswerte, die mir alle 6-7 ms ausgegeben werden ? Bilden diese Werte dann überhaupt die Realität ab, oder bedeuten die 19ms delay einfach nur, dass die gemessenen Werte einfach etwas später ausgegeben werden ? Also quasi, dass der Messwert der mir aktuell ausgegeben wird der Beschleunigung des Objekts 19 ms zuvor entspricht. Dies wäre für mein Projekt kein Problem, da ich die Werte nur aufzeichne und später auswerte.

    Beste Grüße

    1. Hallo Tobi,

      ich sage mal „du“. Der Filter bewirkt eine Glättung der Werte. Kurze Ausschläge nach oben oder unten werden eliminiert oder zumindest abgeschwächt. Bei einer hohen Filterstärke wird über einen längeren Zeitraum geglättet. Und das braucht eben Zeit. Vielleicht als Beispiel: Du gehst schlagartig von Beschleunigung A auf Beschleunigung B und B ist sehr viel größer A. Dann weiß der Sensor ja nicht, ob es um eine tatsächliche Zunahme oder um Rauschen handelt. Würde der Wert sofort ausgegeben, hättest du ja keine Glättung. Die Verzögerung liegt also in der Natur der Sache. Bei dem eben genannten Sprung von A nach B kommst du später bei B an, weil die Datenhistorie mit einbezogen wird.
      Ob die Verzögerung stört, hängt von deiner Anwendung ab. Ein anderer Punkt, der wichtig ist, ist, welche Ereignisse du erfassen möchtest. Wenn du zum Beispiel die Beschleunigung eines Modellautos messen willst, dann solltest du einen hohen Filter einsetzen. Willst du Erschütterungen oder Vibrationen erfassen, dann sollte der Filter gering sein, damit diese Ereignisse nicht weggefiltert werden.
      Hoffe, das hilft.
      VG, Wolfgang

      1. Vielen Dank für die gute Erklärung Wolfgang. Das lässt mich den DLPF nochmal deutlich besser verstehen. Ich messe die Beschleunigung des Druckkopfs meines 3D-Druckers entlang der x-Achse ( beim Sensor y-Achse ). Hierbei verursachen die Schrittmotoren bei Betrieb große Vibrationen, welche ich aus meinen Beschleunigungswerten rausfiltern möchte. Aus dem Slicer ist zu entnehmen, dass die maximale Beschleunigung des Extruder entlang der x-Achse 1200 mm/s^2 entspricht. Bei einer Grenzfrequenz von 5Hz bekomme ich Werte, welche die maximale Beschleunigung nicht überschreiten. Zudem sind im zeitlichen Verlauf der Messwerte ein Anstieg bis zum Höchstwert und daraufhin wieder ein Abfall in Form von Rampen zu erkennen. Bei einem geringeren Filter springen die Werte direkt auf den maximalen Beschleunigungswert und zum Teil darüber hinaus. Die zuvor beschriebenen Rampen sind nicht vorhanden. Nun bin ich mir nicht sicher ob die zuvor beschriebenen Rampen nur ein Produkt der Glättung sind und eventuell große Beschleunigungsänderungen eliminiert werden.
        Würdest du mir eine Grenzfrequenz von 5Hz für diese Anwendung empfehlen und macht eine Ausgabe alle 6-7 ms überhaupt Sinn, wenn eine Glättung 19ms benötigt ?

        Beste Grüße
        Tobi

        1. Ob Beschleunigungswerte eliminiert werden, hängt von ihrer Dauer ab. Sie müssten schon ziemlich kurz sein um herausgefiltert zu werden. Aber aus der Ferne lässt sich das schwer sagen. Wegen der Frage nach der Messfrequenz: ja, vielleicht kommst du mit weniger aus. Probiere es einfach aus und schaue wie die Kurven aussehen. VG, Wolfgang

  10. Hallo Wolfgang,
    vielen Dank für diesen Beitrag! Ich hätte auch noch eine Frage: Ich benutze den MPU6050 für so eine Art Pendel. Da messe ich mit dem Gyro um die X-Achse, lese das über I2C mit einerm Arduino UNO aus, der auch die Zeit misst. Das ganze gebe ich seriell aus und schreibe es in eine Datei, die ich später mit Matlab auswerte. Nun sehe ich aber bei der Integration, dass die Werte recht exakt Faktor 2 zu groß sind.
    Ich lenke das Pendel (über einen Zeitraum von bestimmt einer halben Sekunde) um ca 60° aus, das wird mir aber schon als 120° angezeigt.
    Per default ist der Gyro ja auf Range 250°/s eingestellt. Da bin ich nah dran und vielleicht auch manchmal drüber. Was passiert denn, wenn ich über die Grenze des Range komme? Kann das der Grund sein oder fällt Dir noch etwas anderes ein? Die Integration habe ich überprüft und in verschiedenen Versionen getestet – die würde ich als Fehlerquelle ausschließen..
    Vielen Dank bereits im Voraus!
    Malte

    1. Hallo Malte,

      ein Faktor von ziemlich genau 2 „schreit“ ja förmlich danach, dass irgendwo ein Fehler drinsteckt. Wenn du über die 250°/s sollte eigentlich der Maximalwert angezeigt werden, wenn ich mich recht erinnere. Also vermute ich nicht, dass da der Fehler liegt. Aber einen anderen Messbereich einzustellen ist ja nicht schwer. Im erweiterten Minimalsketch oder in den Beispieldateien für die Bibliotheken wird gezeigt, wie das geht.

      Welche Bibliothek oder welchen Sketch nutzt du zur Auswertung? Vielleicht irgendein Fehler bei der Umrechnung in°/s? Soviel verkehrt machen kann man eigentlich nicht. In der Range 250 ist es Rohwert/131. Oder ist doch eine andere Range eingestellt? Oder liegt es am Versuchsaufbau (Position des Moduls)?

      Das ist das, was mir so auf die Schnelle einfällt.

      VG, Wolfgang

  11. Hallo Herr Ewald,
    Ich bin relativ neu auf dem Gebiet und habe mir nun einen Arduino Uno und MPU 6050 zugelegt. Ich benötige für meine Anwendung eine sehr hohe Auflösung, welche der MPU 6050 im Messbereich +- 2g mit sich bringt. Meine Frage ist nun , ob es ein Problem ist, dass mein Arduino Uno nur einen 10 bit A/D Wandler besitzt und ich mit meinem MPU 6050 aber die vollen 16 bit Auflösung erhalten möchte. Ich habe auch was davon gelesen, dass der MPU 6050 schon einen 16 bit A/D Wandler integriert hat, dann sollten die 10 bit des Arduino Uno ja egal sein oder ? Wäre nett, wenn Sie mir bei der Fragestellung behilflich sein könnten.
    Schon mal vielen Dank im Voraus!

    1. Hallo, der A/D Wandler des Arduino ist unbeteiligt. Das Auslesen des Sensors, die Verstärkung und A/D-Wandlung erfolgt im MPU6250. Die Daten werden dann per I2C „abgeholt“. VG, Wolfgang

  12. Hallo!
    Ich habe mir auch seinen Sensor bestellt und heute erhalten. Jetzt wollte ich ihn ausprobieren, allerdings bekomme ich immer nur 0 angezeigt bei der Ausgabe (Ausnahme temp = 36.1). Hast du eine Idee woran das liegen könnte?

    1. Hallo, bekommst du das Ergebnis unabhängig vom Sketch und von der Bibliothek? Funktioniert die I2C Verbindung? Das könntest du mit einem I2C Scanner Sketch ausprobieren:
      https://wolles-elektronikkiste.de/i2c-scanner
      oder mit der Adafruit-Bibliothek. Der Beispielsketch oben fragt am Anfang ab, ob eine Verbindung vorliegt. Man kann natürlich auch mal Pech haben, dass das Modul einen Schaden hat, aber die I2C Verbindung ist „mein Favorit“ als möglicher Fehler. Schau erst mal in der Richtung. Manchmal ist es auch so etwas Banales wie ein kaputtes Steckbrückenkabel. Viel Glück bei der Suche!

  13. Hallo Wolfgang,
    danke für die schnelle Antwort. Ist ein langsamer Drift, so eine Stunde ein Grad. kan bis 3 oder 6 Grad gehen, kann auch schon beim Einschalten bei 2 Grad sein. alles etwas diffus. Ich stell dann mechanisch auf Null, driftet aber wieder weg. Ich versuch es mal mit dem Light und neuem 6050.
    Gebe dann Bescheid wie es läuft.

  14. Hallo Wolfgang,
    hänge nun schon seit 2 Stunden auf deiner Seite und bin begeistert!
    Habe mit dem MPU6050 eine Wohnkabinenausrichtung realisiert, klappt auch sehr gut. Einziges Problem ist, das mir die Winkel über den Tag bis zu 6 Grad wegdriften. Ich hoffe das ich das eventuell mit der Light Version wegkriege. Hast Du da Erfahrungen?

    1. Hallo Rudolf,
      ich habe keinen Drift festgestellt, ich habe aber auch nie über den ganzen Tag gemessen. Ist das ein langsamer, kontinuierlicher Drift oder erreichst du irgendwann einen Wert, der sich nicht mehr ändert? Oder schwankt der Wert hin und her? Ob das mit der Light Bibliothek besser wird, kann ich dir nicht sagen. Wenn ich wetten sollte, würde ich aber eher auf nein tippen.

      1. Hallo Wolfgang,
        danke für die schnelle Antwort. Ist ein langsamer Drift, so eine Stunde ein Grad. kan bis 3 oder 6 Grad gehen, kann auch schon beim Einschalten bei 2 Grad sein. alles etwas diffus. Ich stell dann mechanisch auf Null, driftet aber wieder weg. Ich versuch es mal mit dem Light und neuem 6050.
        Gebe dann Bescheid wie es läuft.

        1. Hallo Wolfgang, schon eine Weile her, hab es aber endlich geschafft mich darum zu kümmern.
          Mit neuer Hardware und Kalibrierung des Sensors ist der Drift jetzt bei max. 0,5 Grad über 24 Stunden. Damit kann ich arbeiten. Nochmals Danke für Deine Hinweise.

  15. hallo,
    wie immer sind die erklärungen 1A!
    Frage:
    ich habe zwei MPU6050, jeweils mit einem ESP8266 verbunden. Gleicher aufbau auf jeweils einer platine, sensor ist mechanisch fest mit der platine verbunden. Verwende eines der mustersketche und lese das signal mit dieser zeile aus, wobei ich den sensor in der X/Z ebene jeweils um ca. 90° drehe (0°, 90°, 180°, 270°), der sensor volführt quasi einen looping:

    Ax = (double)AccelX / AccelScaleFactor;

    die ergebnisse sehen so aus:
    sensor-1 : 1,5 0,5 -0,5 0,5
    sensor-2 : 1 0 -1 0

    wie kann ich mir die unterschiede erklären? Wobei die sind schon enorm! Es wäre mir wichtig, dass die ergebnisse im rahmen vernünftiger toleranzen vergleichbar gross wären. Wie mache ich das?

    danke…
    gruss georg

    1. Also, dass die Module ein bisschen variieren, ist normal, aber solche Unterschiede sind merkwürdig. Da ist irgendetwas im Argen. Ich würde erst einmal mal den Adafruit basic_readings sketch laufen lassen. Dann kannst du ja zumindest schon mal sehen, ob die Module im Prinzip vernünftige Werte liefern. Die Achsen, die senkrecht stehen sollten ja ca. 10 m/s2 liefern. Wenn etwas Richtiges herauskommt, dann muss der Fehler irgendwo im Programm liegen. Wenn du nicht weiterkommst dann schicke es mir mal an wolfgang.ewald@wolles-elektronikkiste.de..

      1. hallo Wolfgang,
        der sketch von Adafruit meldet nur „Failed to find MPU6050 chip“ – es sind ja auch clone…
        gruss georg

        1. ich hatte aber noch ein exemplar des MPU6050 clones auf meinem breadboard, das habe ich auch getestet, die werte entsprechen ziemlich genau dem modell 2. Also ist modell 1- sensor schrott…

        2. Der Adafruit Sketch sollte auch mit Klonen funktionieren. Das klingt nach einem Problem mit der I2C Verbindung. Du kannst das mit einem I2C Scanner Sketch prüfen:

          https://wolles-elektronikkiste.de/i2c-scanner

          Findest du damit die beiden Adressen 0x68 und 0x69? Falls nein: Wenn du nur einen MPU6050 anschließt, findest du die Adresse 0x68? Falls ja, hast du beim zweiten Modul den Pin AD0 auf High gesetzt?

          1. ich habe jetzt einen eigenen i2c scanner probiert, weder der noch der von Deiner webseite hat bei keinem der dreien MPU module eine adresse gefunden. Was meinst Du mit AD0 High setzen?

            1. jetzt habe ich das mit dem „zweiten“ AD0 verstanden. Es sind jeweils ein esp8266 und eine mpu6050 auf zwei getrennten platinen… Identische schaltung, aber jede für sich… sollten aber ähnliche werte je nach lage liefern…

              1. Wenn der Scanner keine Adresse findet, dann ist irgendetwas mit der I2C Verbindung im Argen. Pull-Ups sind eigentlich auf dem Modul. Hast du die richtigen I2C Pins am esp8266 gewählt? Welches Board / welche Pins nutzt du?

                1. SCL zu D7 / SDA zu D6 sind verbunden, dann nur noch VCC und GND. Ich konnte da nicht mehr viel probieren, die MPU war ja in beiden fällen fest verlötet. Bin dann den einfachsten weg gegangen:
                  Aus einem bereits eingemotteten roboter habe ich noch eine MPU „kanibalisieren“ können, die mit den falschen werten durch die neue ersetzt, alles läuft, ich habe jetzt zwei module die beide die gleichen wert liefern…
                  gruss und danke für die hilfe…georg

                  1. hallo Wolfgang,
                    die beschriftung auf der platine mit der MPU:
                    spielt es eine rolle ob „ITG/MPU“ oder „GY-521“ drauf steht?

                    gruss…

                    1. Ich habe solche Module mit ITG / MPU auch schon gesehen. Ist meines Erachtens dasselbe. Offen gestanden weiß ich bis heute nicht wo die GY Nomenklatur herkommt bzw. wer sie festlegt. Hauptsache es steht MPU6050 auf dem IC. VG, Wolfgang

  16. Hallo Hr. Ewald
    Ich finde ihre Ausführungen sehr interesant.Ich habe da gleich auch ein paar Fragen.
    Kann man mit dem MPU6050 auch Schalbefehle, (arduino uno) also in der X achse 2x und in der Y achse 2x die sich im messbereich 2g befinden.Ich möchte ein Wohnmobil automatisch in Waage bringen.Da muss ein “ Neigungssensor“ sehr empfindich sein,meine ich.Ich bauch natürlich noch mehr,an Bauteilen und Schaltungen
    um die ganze Sache zum Laufen zu bringen.Im ganzen Internet ist nichts zu finden (sketche,usw.)
    Ich selber bin ganz neu beim Arduino unterwegs,finde es aber sehr interesant.Bin auch fleißig beim Üben.
    Vom Beruf her bin ich Elektromeister und Hobbyelektroniker.Würde mich sehr freuen wenn sie was für mich haben.Besten Dank. Erhard Schiewe.

  17. Danke wieder mal für den tollen Blog-Beitrag!
    Ich habe für eine elektronische Wasserwaage zur Ausrichtung einer Astronomie-Teleskopplattform einen ADXL345 (GY291 Baustein) genommen. Wußte gar nicht, dass es da auch andere Typen gibt. Hast Du Dich bewußt für den verwendeten Typ entschieden oder war das Zufall? Gibts da ggf. eklatante Unterschiede?

    Viele Grüße

    1. Das ist nicht der einzige Beschleunigungssensor, den ich ausprobiere. Ich habe schlicht mit diesem Modell angefangen, weil es doch recht stark verbreitet zu sein scheint. Der ADXL345 ist auch auf meiner Liste – liegt aber noch unausgepackt auf meinem Schreibtisch. .

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert