Accueil > ARDUINO > Capteurs > accéléromètre et gyroscope MPU6050

accéléromètre et gyroscope MPU6050

lundi 30 novembre 2015, par thebault

La capteur MPU6050 contient à la fois un accéléromètre 3 axes et un gyroscope 3 axes qui communique via i2c (datasheet). Dans cet article, je vais me limiter à déterminer l’angle de rotation autour de l’axe Y.

JPEG - 40.2 ko

Les branchements

JPEG - 366.7 ko

Récupérer les données "bruts" du capteur.

Sur la page http://playground.arduino.cc/Main/MPU-6050, on a un exemple d’utilisation de la bibliothèque wire.h (i2c) pour récupérer ces données (voir "short example sketch").
Dans la suite de l’article, je vais plutôt utiliser la bibliothèque développée par Jeff Rowberg. Son projet complet est accessible à cette adresse http://www.i2cdevlib.com/.
Pour poursuivre, il faut donc installer les bibliothèque "i2c" et "MPU6050" sous licence MIT qui se trouvent à l’adresse : https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/I2Cdev et https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050

Télécharger et décompresser dans ../Arduino/librairies les 2 fichiers suivants :

Zip - 15.1 ko
I2Cdev.zip
Zip - 30.6 ko
MPU6050.zip

On utilise le programme suivant pour récupérer les données (les datas s’affichent toutes les 100 ms sur le terminal série) :

  1. #include "Wire.h" // Arduino Wire library
  2. #include "I2Cdev.h" //bibliothèque I2Cdev à installer
  3. #include "MPU6050.h" //bibliothèque MPU6050 à installer
  4. // AD0 low = 0x68 (default for InvenSense evaluation board)
  5. // AD0 high = 0x69
  6. MPU6050 accelgyro;
  7.  
  8. int16_t ax, ay, az; //mesures brutes
  9. int16_t gx, gy, gz;
  10.  
  11. void setup() {
  12. Wire.begin(); // bus I2C
  13. Serial.begin(9600); // liaison série
  14. while (!Serial) {
  15. ; // wait for serial port to connect. Needed for native USB (LEONARDO)
  16. }
  17. accelgyro.initialize(); // initialize device
  18. }
  19.  
  20. void loop() {
  21. accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  22. // On peut aussi utiliser ces méthodes
  23. //accelgyro.getAcceleration(&ax, &ay, &az);
  24. //accelgyro.getRotation(&gx, &gy, &gz);
  25.  
  26. // Affichage accel/gyro x/y/z
  27. Serial.print("a/g:\t");
  28. Serial.print(ax);
  29. Serial.print("\t");
  30. Serial.print(ay);
  31. Serial.print("\t");
  32. Serial.print(az);
  33. Serial.print("\t");
  34. Serial.print(gx);
  35. Serial.print("\t");
  36. Serial.print(gy);
  37. Serial.print("\t");
  38. Serial.print(gz);
  39. Serial.println("\t");
  40. delay(100);
  41. }

Télécharger

Déterminer l’angle d’inclinaison autour de l’axe Y à partir du gyroscope.

Le gyroscope nous donne la vitesse angulaire en rad/s. On a donc la relation suivante (Gy, vitesse de rotation autour de l’axe Y, angle=angle d’inclinaison) :

     d(angle)
Gy= --------- d'où d(angle)=Gy.dt donc
      dt

angle("actuel")=angle("précédent")+Gy.dt

Dans le programme suivant, le dt est fixé à 10ms=0,01s (cf tempo en fin de programme).
Si on lit la documentation, page 12, on voit qu’il faut diviser la valeur lue pour Wy par 131 pour obtenir la vitesse en °/s. Par conséquent, l’équation finale de l’angle est donc : angle=angle+Gy*0.01/131

  1. #include "Wire.h" // Arduino Wire library
  2. #include "I2Cdev.h" //Installer ces 2 librairies
  3. #include "MPU6050.h"
  4.  
  5. MPU6050 accelgyro;
  6.  
  7. int16_t ax, ay, az; //mesures brutes
  8. int16_t gx, gy, gz;
  9. float angle=0;
  10.  
  11. void setup() {
  12. Wire.begin(); //I2C bus
  13. //Serial.begin(9600);
  14. Serial.begin(9600);
  15. while (!Serial) {
  16. ; // wait for serial port to connect. Needed for native USB (LEONARDO)
  17. }
  18. // initialize device
  19. accelgyro.initialize();
  20. }
  21.  
  22. void loop() {
  23. accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  24. angle=angle+float(gy)*0.01/131; // 131 cf doc MPU6050 et 0.01=dt en s
  25.  
  26. Serial.println(angle);
  27. delay(10);
  28. }

Télécharger

Malheureusement, au fur et à mesure, le gyroscope dérive et n’est donc pas fiable. Il suffit de partir d’un angle=0°, tourner le capteur de 90° et revenir ... on n’obtient pas 0 !

Déterminer l’angle d’inclinaison autour de l’axe Y à partir de l’accéléromètre.

L’accéléromètre permet d’obtenir l’angle à partir de la mesure du vecteur de pesanteur. Voir schéma :

JPEG - 43.6 ko

Dans le programme suivant, on va utiliser la bibliothèque "math.h" pour pouvoir utiliser la fonction "arctan". Le programme arduino est le suivant :

  1. #include "Wire.h" // Arduino Wire library
  2. #include "I2Cdev.h" //Installer ces 2 librairies
  3. #include "MPU6050.h"
  4. #include "math.h"
  5.  
  6. // AD0 low = 0x68 (default for InvenSense evaluation board)
  7. // AD0 high = 0x69
  8. MPU6050 accelgyro;
  9.  
  10. int16_t ax, ay, az; //mesures brutes
  11. int16_t gx, gy, gz;
  12. float angle=0;
  13.  
  14. void setup() {
  15. Wire.begin(); //I2C bus
  16. //Serial.begin(9600);
  17. Serial.begin(9600);
  18. while (!Serial) {
  19. ; // wait for serial port to connect. Needed for native USB (LEONARDO)
  20. }
  21.  
  22. // initialize device
  23. accelgyro.initialize();
  24. }
  25.  
  26. void loop() {
  27. accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  28. angle= atan2((double)ax,(double)az )*180/PI; // 180/PI permet d'avoir la valeur en °
  29. Serial.println(angle);
  30. delay(10);
  31. }

Télécharger


Problème : l’accéléromètre est sensible à la moindre vibration. Ainsi, apparaissent des mesures "parasites".

Mesurer l’angle en combinant le gyropode et l’accéléromètre avec un "filtre complémentaire"

On a vu précédemment que le gyroscope dérive et l’accéléromètre présente des mesures brusques "parasites". On va donc combiner les 2 en se débarrassant des variations "lentes" du gyroscope (filtre passe haut) et des variations "rapides" de l’accéléromètre (filtre passe-bas). Pour cela, on utilise un "filtre complémentaire".
Explications sur le filtre complémentaire :http://www.pieter-jan.com/node/11

Ainsi, l’équation de l’angle va être : angle=0,98x(angle +Gy*0.01/131 ) + 0,02x(angle de l’accéléromètre en °)

On peut affiner les coefficients 0,98 et 0,02 du moment que leur somme reste égale à 1

Le programme arduino :

  1. #include "Wire.h" // Arduino Wire library
  2. #include "I2Cdev.h" //Installer ces 2 librairies
  3. #include "MPU6050.h"
  4. #include "math.h"
  5.  
  6. // AD0 low = 0x68 (default for InvenSense evaluation board)
  7. // AD0 high = 0x69
  8. MPU6050 accelgyro;
  9.  
  10. int16_t ax, ay, az; //mesures brutes
  11. int16_t gx, gy, gz;
  12. uint8_t Accel_range;
  13. uint8_t Gyro_range;
  14. float angle=0;
  15.  
  16. void setup() {
  17. Wire.begin(); //I2C bus
  18. Serial.begin(9600);
  19. while (!Serial) {
  20. ; // wait for serial port to connect. Needed for native USB (LEONARDO)
  21. }
  22.  
  23. // initialize device
  24. Serial.println("Initialisation I2C...");
  25. accelgyro.initialize();
  26.  
  27. // verify connection
  28. Serial.println("Test de la conection du dispositif ...");
  29. Serial.println(accelgyro.testConnection() ? "MPU6050 connection reussie" : "MPU6050 connection echec");
  30. delay(1000);
  31. }
  32.  
  33. void loop() {
  34. accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
  35. angle=0.98*(angle+float(gy)*0.01/131) + 0.02*atan2((double)ax,(double)az)*180/PI;
  36. Serial.println(angle);
  37. delay(10);
  38. }

Télécharger


Connecter 2 capteurs MPU6050 sur le bus i2c

On peut mettre 2 capteurs sur le bus i2c. Pour cela, il suffit d’agir sur la broche AD0 :
- si AD0=0 (ou laissé en l’air) : l’adresse du capteur en hexadécimal est 0x68,
- si AD0=1, l’adresse du capteur en hexadécimal est 0x69

Ainsi, si l’on souhaite utiliser 2 capteurs, on les relier a sur le bus i2c de la façon suivante :

JPEG - 578.7 ko

Le programme arduino.

On crée 2 instances de l’objet MPU6050 :

  • accelgyro1(0x68)
  • accelgyro2(0x69)
  1. #include "Wire.h" // Arduino Wire library
  2. #include "I2Cdev.h" //Installer ces 2 librairies
  3. #include "MPU6050.h"
  4. #include "math.h"
  5.  
  6. // AD0 low = 0x68 (default for InvenSense evaluation board)
  7. // AD0 high = 0x69
  8. MPU6050 accelgyro1(0x68);
  9. MPU6050 accelgyro2(0x69);
  10.  
  11. int16_t ax, ay, az; //mesures brutes capteur 1
  12. int16_t gx, gy, gz;
  13. int16_t ax2, ay2, az2; //mesures brutes capteur 2
  14. int16_t gx2, gy2, gz2;
  15. float angle1 = 0;
  16. float angle2 = 0;
  17.  
  18.  
  19. void setup() {
  20. Wire.begin(); //I2C bus
  21. Serial.begin(9600);
  22. while (!Serial) {
  23. ; // wait for serial port to connect. Needed for native USB (LEONARDO)
  24. }
  25.  
  26. // initialize device
  27. Serial.println("Initialisation I2C...");
  28. accelgyro1.initialize();
  29. accelgyro2.initialize();
  30.  
  31. // verify connection
  32. Serial.println("Test de la conection du dispositif ...");
  33. Serial.println(accelgyro1.testConnection() ? "MPU6050 n°1 connection reussie" : "MPU6050 n°1 connection echec");
  34. Serial.println(accelgyro2.testConnection() ? "MPU6050 n°2 connection reussie" : "MPU6050 n°2 connection echec");
  35.  
  36. delay(1000);
  37. }
  38.  
  39. void loop() {
  40.  
  41. accelgyro1.getMotion6(&ax1, &ay1, &az1, &gx1, &gy1, &gz1);
  42. angle1 = 0.98 * (angle1 + float(gy1) * 0.01 / 131) + 0.02 * atan2((double)ax1, (double)az1) * 180 / PI;
  43.  
  44. accelgyro2.getMotion6(&ax2, &ay2, &az2, &gx2, &gy2, &gz2);
  45. angle2 = 0.98 * (angle2 + float(gy2) * 0.01 / 131) + 0.02 * atan2((double)ax2, (double)az2) * 180 / PI;
  46.  
  47. Serial.print(angle1);
  48. Serial.print("\t");
  49. Serial.println(angle2);
  50. delay(10);
  51. }

Télécharger

Si on ouvre le terminal série, on obtient les 2 angles qui s’affichent :

JPEG - 128.2 ko
SPIP | | Plan du site | Suivre la vie du site RSS 2.0
Habillage visuel © digitalnature sous Licence GPL