Fabrication industrielle
Internet des objets industriel | Matériaux industriels | Entretien et réparation d'équipement | Programmation industrielle |
home  MfgRobots >> Fabrication industrielle >  >> Manufacturing Technology >> Processus de fabrication

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

Introduction

Dans ce tutoriel, nous allons apprendre à utiliser le capteur MPU6050 Accéléromètre et Gyroscope avec Arduino. D'abord, j'expliquerai comment fonctionne le MPU6050 et comment lire ses données, puis nous ferons deux exemples pratiques.

Vous pouvez regarder la vidéo suivante ou lire le tutoriel écrit ci-dessous.

Vue d'Ensemble

Dans le premier exemple, en utilisant l'environnement de développement Processing, nous ferons une visualisation 3D de l'orientation du capteur. Dans le second, nous réaliserons une plateforme auto-stabilisée simple ou un Gimbal DIY. Basé sur l'orientation du MPU6050 et ses données fusionnées accéléromètre/gyroscope, nous contrôlons trois servos qui maintiennent la plateforme à l'horizontale.

Comment Ça Marche

Le MPU6050 IMU intègre sur une seule puce un accéléromètre 3 axes et un gyroscope 3 axes.

Le gyroscope mesure la vitesse de rotation ou le taux de changement de position angulaire dans le temps, selon les axes X, Y et Z. Il utilise la technologie MEMS et l'effet Coriolis. Pour plus de détails, consultez mon tutoriel "Comment Fonctionnent les Capteurs MEMS". Les sorties du gyroscope sont en degrés par seconde ; pour obtenir la position angulaire, il suffit d'intégrer la vitesse angulaire.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

De son côté, l'accéléromètre du MPU6050 mesure l'accélération comme expliqué dans la vidéo précédente pour l'ADXL345. En résumé, il mesure l'accélération gravitationnelle sur les 3 axes et avec un peu de trigonométrie, on calcule l'angle d'inclinaison du capteur. En fusionnant (combinant) les données accéléromètre et gyroscope, on obtient une information très précise sur l'orientation du capteur.

Le MPU6050 IMU est aussi appelé dispositif de suivi de mouvement 6 axes ou 6 DoF (6 Degrés de Liberté), à cause de ses 6 sorties : 3 accéléromètre + 3 gyroscope.

Arduino et MPU6050

Voyons comment connecter et lire les données du MPU6050 avec Arduino. On utilise le protocole I2C, donc seulement 2 fils pour la communication, plus 2 pour l'alimentation.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

Composants Nécessaires

  • MPU6050 IMU – Amazon / Banggood / AliExpress
  • Carte Arduino
  • Plaque d'essai et fils de connexion

Code Arduino MPU6050

Voici le code Arduino pour lire les données du MPU6050. Description détaillée ci-dessous.

/* Arduino et MPU6050 Accéléromètre et Gyroscope par Dejan, https://howtomechatronics.com */
#include <Wire.h>
const int MPU = 0x68; // Adresse I2C MPU6050
float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;
float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ;
float roll, pitch, yaw;
float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY, GyroErrorZ;
float elapsedTime, currentTime, previousTime;
int c = 0;

void setup() {
  Serial.begin(19200);
  Wire.begin();
  Wire.beginTransmission(MPU);
  Wire.write(0x6B); // Registre 6B (PWR_MGMT_1)
  Wire.write(0x00); // Reset - met 0 dans registre 6B
  Wire.endTransmission(true);
  
  /* // Configuration sensibilité accéléromètre (défaut ±2g)
  Wire.beginTransmission(MPU);
  Wire.write(0x1C); // Registre ACCEL_CONFIG (1C hex)
  Wire.write(0x10); // ±8g full scale
  Wire.endTransmission(true);
  
  // Configuration sensibilité gyroscope (défaut ±250°/s)
  Wire.beginTransmission(MPU);
  Wire.write(0x1B); // Registre GYRO_CONFIG (1B hex)
  Wire.write(0x10); // 1000°/s full scale
  Wire.endTransmission(true);
  delay(20); */
  
  // Appeler cette fonction pour obtenir les valeurs d'erreur de votre module
  calculate_IMU_error();
  delay(20);
}

void loop() {
  // === Lecture accéléromètre ===
  Wire.beginTransmission(MPU);
  Wire.write(0x3B); // Registre ACCEL_XOUT_H
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6, true); // Lit 6 registres (2 par axe)
  
  // Pour plage ±2g, diviser valeurs brutes par 16384 (datasheet)
  AccX = (Wire.read() << 8 | Wire.read()) / 16384.0;
  AccY = (Wire.read() << 8 | Wire.read()) / 16384.0;
  AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0;
  
  // Calcul Roll et Pitch depuis données accéléromètre
  accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58; // AccErrorX ~(0.58)
  accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58; // AccErrorY ~(-1.58)
  
  // === Lecture gyroscope ===
  currentTime = millis();
  elapsedTime = (currentTime - previousTime) / 1000.0; // En secondes
  
  Wire.beginTransmission(MPU);
  Wire.write(0x43); // Registre GYRO_XOUT_H
  Wire.endTransmission(false);
  Wire.requestFrom(MPU, 6, true);
  
  // Pour plage 250°/s, diviser par 131.0 (datasheet)
  GyroX = (Wire.read() << 8 | Wire.read()) / 131.0;
  GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
  GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
  
  // Correction avec erreurs calculées
  GyroX = GyroX + 0.56; // GyroErrorX ~(-0.56)
  GyroY = GyroY - 2;    // GyroErrorY ~(2)
  GyroZ = GyroZ + 0.79; // GyroErrorZ ~(-0.8)
  
  // Intégration : deg/s * s = deg
  gyroAngleX = gyroAngleX + GyroX * elapsedTime;
  gyroAngleY = gyroAngleY + GyroY * elapsedTime;
  yaw = yaw + GyroZ * elapsedTime;
  
  // Filtre complémentaire : fusion accéléromètre + gyroscope
  roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
  pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;
  
  // Affichage sur moniteur série
  Serial.print(roll);
  Serial.print("/");
  Serial.print(pitch);
  Serial.print("/");
  Serial.println(yaw);
}

void calculate_IMU_error() {
  // Calcule les erreurs accéléromètre et gyroscope. À appeler dans setup().
  // Placer l'IMU à plat pour obtenir les bonnes valeurs de correction.
  
  // Lecture accéléromètre 200 fois
  while (c < 200) {
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 6, true);
    AccX = (Wire.read() << 8 | Wire.read()) / 16384.0;
    AccY = (Wire.read() << 8 | Wire.read()) / 16384.0;
    AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0;
    
    AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
    AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
    c++;
  }
  AccErrorX = AccErrorX / 200;
  AccErrorY = AccErrorY / 200;
  c = 0;
  
  // Lecture gyroscope 200 fois
  while (c < 200) {
    Wire.beginTransmission(MPU);
    Wire.write(0x43);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 6, true);
    GyroX = Wire.read() << 8 | Wire.read();
    GyroY = Wire.read() << 8 | Wire.read();
    GyroZ = Wire.read() << 8 | Wire.read();
    
    GyroErrorX = GyroErrorX + (GyroX / 131.0);
    GyroErrorY = GyroErrorY + (GyroY / 131.0);
    GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
    c++;
  }
  GyroErrorX = GyroErrorX / 200;
  GyroErrorY = GyroErrorY / 200;
  GyroErrorZ = GyroErrorZ / 200;
  
  // Affichage erreurs sur moniteur série
  Serial.print("AccErrorX: "); Serial.println(AccErrorX);
  Serial.print("AccErrorY: "); Serial.println(AccErrorY);
  Serial.print("GyroErrorX: "); Serial.println(GyroErrorX);
  Serial.print("GyroErrorY: "); Serial.println(GyroErrorY);
  Serial.print("GyroErrorZ: "); Serial.println(GyroErrorZ);
}

Description du Code

On inclut Wire.h pour la communication I2C et on définit les variables pour stocker les données.

Dans setup(), on initialise la bibliothèque Wire et on réinitialise le capteur via le registre de gestion d'alimentation (Power Management). Il faut consulter la datasheet pour l'adresse du registre.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

On peut aussi sélectionner la plage de sensibilité (Full-Scale Range) pour l'accéléromètre et le gyroscope via leurs registres de configuration. Pour cet exemple, on utilise les défauts : ±2g pour l'accéléromètre et 250°/s pour le gyroscope, donc cette partie est commentée.

// Configure Accelerometer Sensitivity - Full Scale Range (default +/- 2g)
Wire.beginTransmission(MPU);
Wire.write(0x1C); // ACCEL_CONFIG register
Wire.write(0x10); // ±8g full scale range
Wire.endTransmission(true);
// Configure Gyro Sensitivity - Full Scale Range (default +/- 250deg/s)
Wire.beginTransmission(MPU);
Wire.write(0x1B); // GYRO_CONFIG register
Wire.write(0x10); // 1000deg/s full scale
Wire.endTransmission(true);

Dans loop(), on commence par lire l'accéléromètre. Les données de chaque axe sont sur 2 octets/registres. Les adresses sont dans la datasheet.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

Pour tout lire, on commence au premier registre et avec requestFrom() on demande 6 registres (X, Y, Z). On lit chaque registre et comme les sorties sont en complément à deux, on les combine correctement.

Wire.beginTransmission(MPU);
Wire.write(0x3B); // ACCEL_XOUT_H
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0;
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0;
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0;

Pour obtenir des valeurs de -1g à +1g (adaptées au calcul d'angles), on divise par la sensibilité choisie.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

Avec ces deux formules, on calcule les angles de roulis (roll) et tangage (pitch) depuis les données accéléromètre.

accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58;
accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58;

Ensuite, même méthode pour le gyroscope.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

On lit les 6 registres gyroscope, on combine les données et on divise par la sensibilité pour obtenir degrés/seconde.

currentTime = millis();
elapsedTime = (currentTime - previousTime) / 1000.0;
Wire.beginTransmission(MPU);
Wire.write(0x43); // GYRO_XOUT_H
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
GyroX = (Wire.read() << 8 | Wire.read()) / 131.0;
GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

On corrige les sorties avec les petites valeurs d'erreur calculées (expliquées après). Comme les sorties sont en °/s, on les multiplie par le temps pour obtenir des degrés. Le temps est capturé avant chaque itération avec millis().

GyroX = GyroX + 0.56;
GyroY = GyroY - 2;
GyroZ = GyroZ + 0.79;
gyroAngleX = gyroAngleX + GyroX * elapsedTime;
gyroAngleY = gyroAngleY + GyroY * elapsedTime;
yaw = yaw + GyroZ * elapsedTime;

Enfin, on fusionne accéléromètre et gyroscope avec un filtre complémentaire. On prend 96% du gyroscope (très précis, pas affecté par forces externes) et 4% de l'accéléromètre (pour corriger la dérive du gyroscope à long terme).

roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;

Pour le Yaw (lacet), on ne peut pas utiliser l'accéléromètre, donc pas de filtre complémentaire possible.

Avant les résultats, expliquons comment obtenir les valeurs de correction d'erreur. On appelle calculate_IMU_error() dans le setup avec le capteur à plat et immobile. On fait 200 lectures pour chaque sortie, on les somme et divise par 200. Comme le capteur est à plat, les valeurs attendues sont 0. On obtient ainsi l'erreur moyenne du capteur.

void calculate_IMU_error() {
  while (c < 200) {
    Wire.beginTransmission(MPU);
    Wire.write(0x3B);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 6, true);
    AccX = (Wire.read() << 8 | Wire.read()) / 16384.0;
    AccY = (Wire.read() << 8 | Wire.read()) / 16384.0;
    AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0;
    AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
    AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
    c++;
  }
  AccErrorX = AccErrorX / 200;
  AccErrorY = AccErrorY / 200;
  c = 0;
  
  while (c < 200) {
    Wire.beginTransmission(MPU);
    Wire.write(0x43);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU, 6, true);
    GyroX = Wire.read() << 8 | Wire.read();
    GyroY = Wire.read() << 8 | Wire.read();
    GyroZ = Wire.read() << 8 | Wire.read();
    GyroErrorX = GyroErrorX + (GyroX / 131.0);
    GyroErrorY = GyroErrorY + (GyroY / 131.0);
    GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
    c++;
  }
  GyroErrorX = GyroErrorX / 200;
  GyroErrorY = GyroErrorY / 200;
  GyroErrorZ = GyroErrorZ / 200;
  
  Serial.print("AccErrorX: "); Serial.println(AccErrorX);
  Serial.print("AccErrorY: "); Serial.println(AccErrorY);
  Serial.print("GyroErrorX: "); Serial.println(GyroErrorX);
  Serial.print("GyroErrorY: "); Serial.println(GyroErrorY);
  Serial.print("GyroErrorZ: "); Serial.println(GyroErrorZ);
}

On affiche les valeurs sur le moniteur série, puis on les implémente dans le code pour corriger roll, pitch et les 3 axes gyroscope.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

Enfin, avec Serial.print on affiche Roll, Pitch, Yaw pour vérifier le bon fonctionnement.

Suivi d'Orientation MPU6050 – Visualisation 3D

Pour la visualisation 3D, il suffit de recevoir les données envoyées par l'Arduino sur le port série dans l'environnement Processing. Voici le code Processing complet :

/* Arduino et MPU6050 IMU - Visualisation 3D par Dejan, https://howtomechatronics.com */
import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;

Serial myPort;
String data="";
float roll, pitch, yaw;

void setup() {
  size(2560, 1440, P3D);
  myPort = new Serial(this, "COM7", 19200);
  myPort.bufferUntil('\n');
}

void draw() {
  translate(width/2, height/2, 0);
  background(233);
  textSize(22);
  text("Roll: " + int(roll) + " Pitch: " + int(pitch), -100, 265);
  
  rotateX(radians(-pitch));
  rotateZ(radians(roll));
  rotateY(radians(yaw));
  
  textSize(30);
  fill(0, 76, 153);
  box(386, 40, 200);
  
  textSize(25);
  fill(255, 255, 255);
  text("www.HowToMechatronics.com", -183, 10, 101);
}

void serialEvent(Serial myPort) {
  data = myPort.readStringUntil('\n');
  if (data != null) {
    data = trim(data);
    String items[] = split(data, '/');
    if (items.length > 1) {
      roll = float(items[0]);
      pitch = float(items[1]);
      yaw = float(items[2]);
    }
  }
}

On lit les données entrantes de l'Arduino et on les met dans les variables Roll, Pitch, Yaw. Dans la boucle draw(), on utilise ces valeurs pour faire pivoter l'objet 3D (ici un pavé coloré avec texte).

Si on lance le sketch, on voit comme le MPU6050 suit bien l'orientation. L'objet 3D suit précisément et de façon réactive.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

Le seul inconvénient : le Yaw dérive avec le temps car pas de filtre complémentaire possible. Pour améliorer, il faut un capteur supplémentaire : généralement un magnétomètre pour correction à long terme de la dérive Yaw du gyroscope. Cependant, le MPU6050 a une fonctionnalité appelée Digital Motion Processor (DMP) pour calculs embarqués, capable d'éliminer la dérive Yaw.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

Même exemple 3D avec le DMP activé. Le suivi d'orientation est maintenant précis, sans dérive Yaw. Le processeur embarqué calcule aussi les Quaternions pour représenter orientations et rotations en 3D, évitant le blocage de Gimbal (Gimbal lock) des angles d'Euler.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

Cependant, récupérer ces données est plus complexe. Il faut connecter un fil supplémentaire à une broche numérique Arduino (broche d'interruption) pour lire ce type de données du MPU6050.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

Le code est plus complexe, donc on utilise la bibliothèque i2cdevlib de Jeff Rowberg (disponible sur GitHub, lien dans l'article web).

Une fois la bibliothèque installée, on ouvre l'exemple MPU6050_DMP6 qui est bien commenté ligne par ligne.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

On peut sélectionner le type de sortie : quaternions, angles d'Euler, yaw/pitch/roll, valeurs d'accélération, ou quaternions pour visualisation 3D. La bibliothèque inclut aussi un sketch Processing pour la 3D. Je l'ai modifié pour avoir la forme de pavé. Voici le code Processing pour la sortie "OUTPUT_TEAPOT" :

/* Arduino et MPU6050 IMU - Visualisation 3D par Dejan, https://howtomechatronics.com */
import processing.serial.*;
import java.awt.event.KeyEvent;
import java.io.IOException;

Serial myPort;
String data="";
float roll, pitch, yaw;

void setup() {
  size(2560, 1440, P3D);
  myPort = new Serial(this, "COM7", 19200);
  myPort.bufferUntil('\n');
}

void draw() {
  translate(width/2, height/2, 0);
  background(233);
  textSize(22);
  text("Roll: " + int(roll) + " Pitch: " + int(pitch), -100, 265);
  
  rotateX(radians(-pitch));
  rotateZ(radians(roll));
  rotateY(radians(yaw));
  
  textSize(30);
  fill(0, 76, 153);
  box(386, 40, 200);
  
  textSize(25);
  fill(255, 255, 255);
  text("www.HowToMechatronics.com", -183, 10, 101);
}

void serialEvent(Serial myPort) {
  data = myPort.readStringUntil('\n');
  if (data != null) {
    data = trim(data);
    String items[] = split(data, '/');
    if (items.length > 1) {
      roll = float(items[0]);
      pitch = float(items[1]);
      yaw = float(items[2]);
    }
  }
}

Ici, avec serialEvent(), on reçoit les quaternions de l'Arduino et dans draw() on les utilise pour faire pivoter l'objet 3D. On voit comme les quaternions sont efficaces pour la rotation 3D.

Pour ne pas surcharger ce tutoriel, j'ai mis le second exemple (Gimbal DIY / Plateforme auto-stabilisée) sur un article séparé.

Maîtriser le MPU6050 : Tutoriel Accéléromètre et Gyroscope pour Arduino

N'hésitez pas à poser vos questions dans les commentaires et consultez ma collection de projets Arduino.

Processus de fabrication

  1. Créer un verrou RFID sécurisé avec Arduino – Guide étape par étape
  2. Créer des animations et jeux sur LCD avec Arduino UNO
  3. Arduino et MPU6050 : Contrôle précis de servo-moteur avec SG90 et MG996R
  4. Contrôle Arduino UNO depuis Python 3 – Communication Série et Démo LED
  5. Construire une Radio FM Compacte avec Arduino Nano et RDA5807M
  6. Calculer les angles d'inclinaison à partir de l'accélération MPU6050 avec Arduino Nano et Visuino
  7. Enregistreur de Données Environnementales Arduino avec Carte SD et RTC
  8. Construisez un mini piano avec Arduino UNO – Tutoriel pas à pas
  9. Tutoriel Arduino Débutant 01 : Démarrez votre Premier Projet