IMU MPU-9250/6500

Autor: Prof. Schneider
Einleitung
Die Inertiale Messeinheit (Engl. intertial measurement unit, IMU) ist ein 9-Achsen-Positionserkennungsmodul, das die folgenden Sensoren kombiniert:
- 3-Achsen-Gyroskop
- 3-Achsen-Beschleunigungssensor
- 3-Achsen-Magnetfeldsensor (Erdmagnetfeld/Kompass)
Ein Digital Motion Processor (DMP) ist zudem in einer winzigen Gehäusegröße von nur 3x3x1 mm verbaut. Das Modul kann über einen I2C-Bus angesprochen werden. Der MPU-9250 ist ein Multi-Chip-Modul welches die MPU-6500 (Geschleunigung und Gyro) via I2C mit dem AKM-8963 (Magnetometer) verbindet.
Technische Übersicht
| Eigenschaft | Daten |
|---|---|
| Artikel | MPU-9250/6500 |
| ADU | 3x 16-Bit Analog-Digital Konverter für Gyro, Beschleunigung und Magnetfeld |
| Schnittstelle | I2C und SPI Schnittstelle |
| Spannungsversorgung am VCC Pin | 3,3 V bis 5 V
Über den intern verbauten LDO ME6211C33M5G-N ((S2RC),out 3.3V 500mA 300mW), bekommt der Sensor intern seine benötigten 2,4 V bis 3,6 V |
| Stromaufnahme | 4 mA |
| Messbereich Gyroskop | einstellbar: ±250, ±500, ±1000 and ±2000 °/s |
| Messbereich Beschleunigung | einstellbar: ±2g, ±4g, ±8g and ±16g |
| Messbereich Magnetometer | ±4800 µT |
| Hersteller | InvenSense, TDK |
Pinbelegung
| Pin | MPU-9250 | Signal | Arduino Uno R3 | Leitungsfarbe der im Alpha Bot verbauten | Pin am Alpha Bot mmit Arduino Uno R4 |
|---|---|---|---|---|---|
| 1 | Betriebsspannung Vcc | VCC | VCC, 3,3 V | rot | +5V |
| 2 | Masse GND | GND | GND | schwarz | GND |
| 3 | SCL | I2C Taktleitung interner 10 kOhm Widerstand auf 3,3 V | SCL | weiß | SCL |
| 4 | SDA | I2C Datenleitung interner 10 kOhm Widerstand auf 3,3 V | SDA | blau | SDA |
| 5 | EDA | externe I²C Pins | NC | NC | |
| 6 | ECL | externe I²C Pins | NC | NC | |
| 7 | ADO/SDO | Änderung der I²C Buss Adresse LOW (NC/GND) = 0x68, HIGH (+3,3V) = 0x69 | NC | NC | |
| 8 | INT | Interrupt Pin um anzuzeigen, dass aktuelle Daten vorliegen, welche ausgewertet werden können. | NC | gelb | eventuell auf einen neun nicht benötigten Interrupt Pin Uno R4 |
| 9 | NCS | Chip Select bei SPI Nutzung | NC | NC | |
| 10 | FSYNC | Frame Synchronisation für Interrupts von externen Sensoren | NC | NC |
Messverfahren
Technischer Aufbau
Das MPU-9250 ist ein Multi-Chip-Modul (MCM), das aus zwei Chips besteht, die in einem einzigen QFN-Gehäuse integriert sind, siehe Abbildung 5.

Ein Chip beherbergt das 3-Achsen-Gyroskop und den 3-Achsen-Beschleunigungssensor. Der andere Chip beherbergt das 3-Achsen- Magnetometer AK8963 der Asahi Kasei Microdevices Corporation. Somit ist das MPU-9250 ein 9-Achsen-MotionTracking-Gerät, das ein 3-Achsen-Gyroskop, einen 3-Achsen-Beschleunigungssensor, ein 3-Achsen-Magnetometer und einen Digital MotionProcessor™ (DMP) beinhaltet. Mit seinem dedizierten I²C-Sensor-Bus liefert der MPU-9250 direkt vollständige 9-Achsen-MotionFusion™-Ausgabedaten.
Der MPU-9250 ist zudem so konzipiert, dass er über seinen zusätzlichen I²C-Anschluss mit mehreren nicht-inertialen digitalen Sensoren, wie beispielsweise Drucksensoren, kommunizieren kann. Der MPU-9250 verfügt über drei 16-Bit-Analog-Digital-Wandler (ADCs) zur Digitalisierung der Gyroskop-Ausgänge, drei 16-Bit-ADCs zur Digitalisierung der Beschleunigungsmesser-Ausgänge und drei 16-Bit-ADCs zur Digitalisierung der Magnetometer- Ausgänge, siehe Abbildung 5. Zur präzisen Erfassung sowohl schneller als auch langsamer Bewegungen verfügen die Bauteile über einen vom Anwender programmierbaren Gyroskop-Vollbereich von ±250, ±500, ±1000 und ±2000°/s (dps) sowie einen vom Anwender programmierbaren Beschleunigungssensor- Vollbereich von ±2 g, ±4 g, ±8 g und ±16 g sowie einen Magnetometer-Vollbereich von ±4800 μT. Zu den weiteren branchenführenden Merkmalen zählen programmierbare digitale Filter, ein Präzisions-Taktgeber mit einer Abweichung von 1 % im Temperaturbereich von -40 °C bis 85 °C, ein integrierter Temperatursensor sowie programmierbare Interrupts. Das Gerät verfügt über serielle I²C- und SPI-Schnittstellen, einen VDD-Betriebsbereich von 2,4 V bis 3,6 V sowie eine separate digitale E/A-Versorgung (VDDIO) von 1,71 V bis VDD. Die Kommunikation mit allen Registern des Bausteins erfolgt entweder über I²C mit 400 kHz oder über SPI mit 1 MHz. Für Anwendungen, die eine schnellere Kommunikation erfordern, können die Sensor- und Interrupt-Register über SPI mit 20 MHz ausgelesen werden.
Funktionsweise der 3 Sensoren
Beschleunigungssensor (3-Achsen-Accelerometer):
Dieser arbeitet mit MEMS Technik einer Technology, bei der im Chip kleine federnde aufgehängte Silizium-Massen durch die Beschleunigung und die Erdbeschleunigung verschoben werden und deren Verschiebung gemessen werden kann z.B. durch die Messung sich verändernder Kapazitäten an Kammstruckturen, welche zwischen der Masse und dem starren äußeren Körper befinden, und deren Kapazität sich durch die Verschiebung wie bei einem klassischen Plattenkondensator ändert.
Gyroskop (3-Achsen-Gyro):
Hierbei wird die Corioliskraft genutzt. Auch hier kommen wieder MEMS zum Einsatz. Es wird die Rotation gemessen in dem man die Vibrationen quer zu ihrer Antriebsrichtung erfasst. Die Abbildung 4 zeigt wie mithilfe eines MEMS verschiedene Richtungen erfasst werden können, weiter Informationen dazu in Medium:Rapid Prototyping of Inertial MEMS Devices through.pdf.
Magnetometer (3-Achsen-Kompass):
Beim Magnetometer werden Hall-Effekt-Sensoren genutzt, mit denen man die Magnetfeldstärke und die Richtung erfassen kann. Zu beachten ist, das die Achsen des Magnetometers in unterschiedliche Richtungen ausgerichtet sind im Vergleich zum Beschleunigungssensor und des Gyros siehe Abbildung 7. Durch die Integration dreier Sensoren können die negativen Eigenschaften der einzelnen Sensoren kompensiert werden. So kann der Magnetfeldsensor die Drift des Gyroskops kompensieren werden und die Ausrichtung des Sensors im Raum bestimmt werden, solange keine magnetischen Gegenstände wie Metallteile, Magnete oder Elektromagneten wie z.B. Motoren in der Nähe sind. Daher sollten bei Verwendung des Sensors alle Sensoren beim Starten kalibriert werden, z.B. wie beim Handy der Magnetfeldsensor kalibriert wird über das Bewegen des Sensors in einer achtförmigen Schleife oder der Bestimmung des Start-Offset des Gyros.

Praktisches Beispiel zum Ausdrucken am 3D Drucker eines MEMS Gyros bei Printables von dona97m siehe Abbildung 3.


Literatur
Beispiel des Aufbaus und der Auslegung eines MEMS Gyros. https://www.researchgate.net/publication/353487249_Rapid_Prototyping_of_Inertial_MEMS_Devices_through_Structural_Optimization
Software
Arduino
AlphaBot
In der Abbildung 2 des AlphaBots sieht man den MontagePunkt des MPU-9250, sowie dessen Ausrichtung der Messachsen. X zeigt in Fahrtrichtung des Linienverfolgers.

Zweiter I²C-Bus Arduino UNO R4 Wifi
https://docs.arduino.cc/tutorials/uno-r4-wifi/qwiic/
I²C-Scanner
Prüfen Sie welche Sensoren am I2C-Bus angeschlossen sind.
| DemoI2C_Scanner.ino |
#include <Wire.h>
void setup()
{
Serial.begin(115200);
Wire.begin();
Serial.println("I2C Scan");
for(byte address=1; address<127; address++)
{
Wire.beginTransmission(address);
if(Wire.endTransmission()==0)
{
Serial.print("Gefunden: 0x"); // 0x71 MPU9250 auf einem GY-6500/GY-9250-Board
Serial.println(address, HEX);
}
}
}
void loop(){}
|
URL: https://svn.hshl.de/svn/Informatikpraktikum_1/trunk/Arduino/ArduinoLibOrdner/ArduinoUnoR3/examples/DemoI2C_Scanner/DemoI2C_Scanner.ino
Erwartetes Ergebnis
I2C Scan Gefunden: 0x68
0x68 ist die I²C-Adresse des Sensors.
Prüfen welcher Chip verbaut wurde
Bei diesen Modulen kommt es vor, dass ein Board als MPU-9250 verkauft wird, aber tatsächlich ein MPU6500 bestückt ist.
Lesen Sie das Register 0x75 per I²C aus.
| Chip | WHO_AM_I |
|---|---|
| MPU-6500 | 0x70
|
| MPU-9250 | 0x71
|
| DemoWhoAmI.ino |
#include <Wire.h>
void setup() {
Serial.begin(115200);
while (!Serial);
Wire.begin(); // I²C initialisieren
Wire.beginTransmission(0x68);
Wire.write(0x75); // WHO_AM_I-Register
Wire.endTransmission(false);
Wire.requestFrom(0x68, 1);
if (Wire.available()) {
byte id = Wire.read();
Serial.print("WHO_AM_I = 0x");
Serial.println(id, HEX);
if (id == 0x71)
Serial.println("MPU-9250 erkannt");
else if (id == 0x70)
Serial.println("MPU-6500 erkannt");
else
Serial.println("Unbekannter Sensor");
} else {
Serial.println("Keine Antwort vom Sensor.");
}
}
void loop() {
}
|
URL: https://svn.hshl.de/svn/Informatikpraktikum_1/trunk/Arduino/ArduinoLibOrdner/ArduinoUnoR3/examples/DemoWhoAmI/DemoWhoAmI.ino
Arduino-Bibliothek installieren
MPU9250_asukiaaa
| Demo | Funktion |
|---|---|
| DemoUnoR4Wifi.ino | Demo zum Senden von Sensordaten via Wifi für die Arduino IDE |
| DemoUnoR4Wifi.m | Demo zum Empfangen von Sensordaten via Wifi mit MATLAB® |
| GetDate.ino | Demo zum Auslesen der IMU-Daten des Sensors MPU 9250 |
| E15_RadInkrementalgeberFahrt.ino | Demo zum Ansteuern der Motoren und auslesen der Odometrie des AlphaBot |
| DemoUnoR4Wifi.ino |
clear all; clc;
port = 7000; % UDP Port, auf dem MATLAB lauscht
u = udpport("IPV4", "LocalPort", port);
disp("Warte auf UDP-Daten vom Arduino ...")
while true
nBytes = u.NumBytesAvailable;
if nBytes > 0 % Prüfen, ob Daten vorhanden sind
data = read(u, nBytes, "string");
disp(data)
end
end
|
| GetDate.ino aus der Bibliothek MPU9250_asukiaaa | ||
#include <MPU9250_asukiaaa.h>
#ifdef _ESP32_HAL_I2C_H_
#define SDA_PIN 21
#define SCL_PIN 22
#endif
MPU9250_asukiaaa mySensor;
float aX, aY, aZ, aSqrt, gX, gY, gZ, mDirection, mX, mY, mZ;
void setup() {
Serial.begin(115200);
while(!Serial);
Serial.println("started");
#ifdef _ESP32_HAL_I2C_H_ // For ESP32
Wire.begin(SDA_PIN, SCL_PIN);
mySensor.setWire(&Wire);
#endif
mySensor.beginAccel();
mySensor.beginGyro();
mySensor.beginMag();
// You can set your own offset for mag values
// mySensor.magXOffset = -50;
// mySensor.magYOffset = -55;
// mySensor.magZOffset = -10;
}
void loop() {
uint8_t sensorId;
int result;
result = mySensor.readId(&sensorId);
if (result == 0) {
Serial.println("sensorId: " + String(sensorId));
} else {
Serial.println("Cannot read sensorId " + String(result));
}
result = mySensor.accelUpdate();
if (result == 0) {
aX = mySensor.accelX();
aY = mySensor.accelY();
aZ = mySensor.accelZ();
aSqrt = mySensor.accelSqrt();
Serial.println("accelX: " + String(aX));
Serial.println("accelY: " + String(aY));
Serial.println("accelZ: " + String(aZ));
Serial.println("accelSqrt: " + String(aSqrt));
} else {
Serial.println("Cannod read accel values " + String(result));
}
result = mySensor.gyroUpdate();
if (result == 0) {
gX = mySensor.gyroX();
gY = mySensor.gyroY();
gZ = mySensor.gyroZ();
Serial.println("gyroX: " + String(gX));
Serial.println("gyroY: " + String(gY));
Serial.println("gyroZ: " + String(gZ));
} else {
Serial.println("Cannot read gyro values " + String(result));
}
result = mySensor.magUpdate();
if (result != 0) {
Serial.println("cannot read mag so call begin again");
mySensor.beginMag();
result = mySensor.magUpdate();
}
if (result == 0) {
mX = mySensor.magX();
mY = mySensor.magY();
mZ = mySensor.magZ();
mDirection = mySensor.magHorizDirection();
Serial.println("magX: " + String(mX));
Serial.println("maxY: " + String(mY));
Serial.println("magZ: " + String(mZ));
Serial.println("horizontal direction: " + String(mDirection));
} else {
Serial.println("Cannot read mag values " + String(result));
}
Serial.println("at " + String(millis()) + "ms");
Serial.println(""); // Add an empty line
delay(500);
}
|
| E15_RadInkrementalgeberFahrt.ino |
/* Bibliotheken einbinden */
#include "AlphaBot.h"
/* Globale KONSTANTEN deklarieren */
AlphaBot R2D2 = AlphaBot(); // Instanz des Alphabot wird erzeugt. */
const byte PORT_ENC_L_u8 = 2; // Die linke Lichtschranke (CNTL) liegt an Arduino D2
const byte PORT_ENC_R_u8 = 3; // Die rechte Lichtschranke (CNTR) liegt an Arduino D3
const byte ANZAHL_INCREMENTE_u8 = 40; // Die Encoderscheibe hat 20 Löcher und somit 40 Zustände
const int MOTOR_POWER_s16 = 80; // Motorleistung
const unsigned long BAUDRATE_u32 = 9600; // Serielle Übertragungsgeschwindigkeit in Baud
const unsigned long DELAY_MS_u32 = 1000; // Delay in ms
/* Globale Variablen */
volatile byte valEncL_u8 = 0; // https://www.arduino.cc/reference/de/language/variables/data-types/byte/
volatile byte valEncR_u8 = 0; // Inkrementzähler
volatile long int RadumdrehungenL_s32 = 0; // https://www.arduino.cc/reference/de/language/variables/data-types/long/
volatile long int RadumdrehungenR_s32 = 0; // Zähler für die kompletten Radumdrehungen
/* Einmalige Systeminitialisierung */
void setup() {
Serial.begin(BAUDRATE_u32); // Seriellen Monitor starten
pinMode(PORT_ENC_L_u8, INPUT); // Eingangsport D2 definieren
pinMode(PORT_ENC_R_u8, INPUT); // Eingangsport D3 definieren
attachInterrupt(0, updateEncoderL, CHANGE); // 0: D2 Auslösen des Interrupts bei Signalwechsel
attachInterrupt(1, updateEncoderR, CHANGE); // 1: D3 https://www.arduino.cc/reference/de/language/functions/external-interrupts/attachinterrupt/
}
/* Zyklusschleife */
void loop() {
/* Ausgaben im Seriellen Monitor */
Serial.print(valEncL_u8);
Serial.print(" :-: ");
Serial.print(valEncR_u8);
Serial.print(" :-: ");
Serial.print(RadumdrehungenL_s32);
Serial.print(" :-: ");
Serial.print(RadumdrehungenR_s32);
Serial.print("\n");
delay(DELAY_MS_u32);
R2D2.MotorRun(MOTOR_POWER_s16, MOTOR_POWER_s16); // Fahrt starten
delay(DELAY_MS_u32); // Fahrzeit
R2D2.Brake(); // Alle Motoren stoppen
}
/* Unterfunktionen */
void updateEncoderL(){ // Inkrementalgeber Links
valEncL_u8++;
if (valEncL_u8 > ANZAHL_INCREMENTE_u8)// 40 Zustandswechsel = 1 Radumdrehung
{
valEncL_u8 = 0; // Reset Inkrementzähler
RadumdrehungenL_s32++; // Umdrehungen inkrementieren
}
}
void updateEncoderR(){ // Inkrementalgeber Rechts
valEncR_u8++;
if (valEncR_u8 > ANZAHL_INCREMENTE_u8)// 40 Zustandswechsel = 1 Radumdrehung
{
valEncR_u8 = 0; // Reset Inkrementzähler
RadumdrehungenR_s32++; // Umdrehungen inkrementieren
}
}
|
Weitere AlphaBot und Arduino Demos finden Sie im SVN-Repositorium
https://svn.hshl.de/svn/Informatikpraktikum_1/trunk/Arduino/ArduinoLibOrdner/
MATLAB®
Simulink
Messung
Video
Datenblätter
- InvenSense: Datenblatt MPU-9250 Rev. 1.4
- InvenSense: Datenblatt MPU-9250 Rev. 1.1
- Erklärung des Sensors Teil 1 wolles-elektronikkiste.de
- Erklärung des Sensors Teil 2 wolles-elektronikkiste.de
→ zurück zum Hauptartikel: Sensor-Baukasten | HSHL-Mechatronik-Baukasten