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 | 3 V bis 5 V |
| 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 | SCL | weiß | SCL |
| 4 | SDA | I2C Datenleitung | 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
Das MPU-9250 ist ein Multi-Chip-Modul (MCM), das aus zwei Chips besteht, die in einem einzigen QFN-Gehäuse integriert sind. 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 Motion Processor™ (DMP). Mit seinem dedizierten I²C-Sensor-Bus liefert der MPU-9250 direkt vollständige 9-Achsen-MotionFusion™- Ausgabedaten. Das MotionTracking-Gerät MPU-9250 mit seiner 9-Achsen-Integration, On-Chip-MotionFusion™. 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. 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. Durch den Einsatz seiner patentierten und in der Serienfertigung bewährten CMOS-MEMS-Fertigungsplattform, die MEMS- Wafer durch Wafer-Level-Bonding mit der zugehörigen CMOS-Elektronik integriert, hat InvenSense die Gehäusegröße auf eine Grundfläche und Dicke von 3 × 3 × 1 mm reduziert, um ein sehr kleines und dennoch leistungsstarkes, kostengünstiges Gehäuse anzubieten. Das Bauteil bietet eine hohe Robustheit durch eine Stoßfestigkeit von 10.000 g
Die 3 Sensoren arbeiten folgendermaßen.
Beschleunigungssensor (3-Achsen-Accelerometer): Dieser arbeitet mit MEMS Technik einer Technology, bei der im Chip kleine federnt aufgehänge Silizium-Massen durch die Beschleunigung und die Erdbeschleunigung verschoben werden und deren Verschiebung gemessen werden.
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 mist.
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.

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