View All

Facebook Timeline

Module MPU-6050 et Arduino : Une question d'equilibre

Posted On: févr. 17, 2021

Seen by: 18072

Categories: ROBOTS

Author: Christian Joseph

Tags: mpu6050 , arduino , robot , spiderbot , mpu6500

Si vous avez déjà fait du surf (pas moi) ou du skate board (moi oui et je me suis viandé pas mal de fois !), alors vous savez que l’équilibre dans ces sports est primordiale. Le mpu6050 hashtag 6500 hashtag 9250 est un module accéléromètre gysrocope qui peut donner de l’équilibre à vos robots (Oui je vois tout de suite les supporteurs marseillais me suggérer d’en offrir un à Neymar ! HAHAHA très drôle !)

1 - Présentation :

Les MPU 6050/6500/9250 sont des modules accéléromètres gyroscopes et magnétomètres (boussole pour ceux qui n’ont pas compris – uniquement le 9250).
Mais pour une raison qui m’échappe, ils font aussi office de capteur de température. (note pour moi-même : En offrir plein aux joueurs de l’OM pour prise de température avant et après chaque match dans le…enfin bref !)

 Première question: qu’est-ce c’est un gyroscope..non ! qu’est ce qui est…euh non plus ! que ce ce un gyroscope….arggh !
Bon en bon français ça donne : c’est quoi un gyroscope ? (eh ben voilà !)


Alors, d’après le philosophe internetius wikipediatius, « Un gyroscope (du grec « qui observe la rotation ») est un appareil qui exploite le principe de la conservation du moment cinétique en physique  (ou encore stabilité gyroscopique ou effet gyroscopique). Cette loi fondamentale de la mécanique veut qu'en l'absence de couple appliqué à un solide en rotation autour d'un de ses axes principaux, celui-ci conserve son axe de rotation invariable. Lorsqu'un couple est appliqué à l'appareil, il provoque une précession ou une nutation du solide en rotation. »


Alors si vous avez lu toute la définition (pas moi) et que vous n’avez rien compris (moi aussi), alors rassurez-vous  cela veut dire que vous êtes des gens normaux ! Mais pour ne pas dormir bête ce soir, on qualifiera un gyroscope de capteur de position angulaire sur 3 axes (x,y,z).


Nous avons par exemple  un gyroscope dans notre smartphone et qui est utilisé par beaucoup d’applications et de jeux que mon finisseur professionnel de batterie agissant en la qualité de mon fils de 11 ans William affectionne tant.
 


Voici une représentation des axes x,y,z :

Repère x y z
 
En clair, lorsque vous inclinez votre smartphone de gauche à droite, vous modifiez par exemple l’angle de l’axe X. Si vous l’inclinez d’avant en arrière, vous modifiez l’ange de l’axe Y, et si vous le déplacez de haut en bas vous modifiez l’axe Z.

Le gyrosccope est aussi présent dans les drônes et sert à assurer la stabilité de l'appareil en plein vol.

Deuxième question: C’est quoi un accéléromètre ? (haha cette fois-ci je mais pas trompez !)
Un accéléromètre comme son nom l’indique sert à mesurer l’accélération d’un corps ( comme l’accélération de Mbappé face à la défense Marseillaise incapable de le rattraper).
Le compteur de vitesse d’une voiture en est le parfait exemple et permet de calculer l’accélération d’une voiture qui passe de 0 à 100 km /h en 3 secondes (comme la Ferrari de Mbappé qu’il ne peut toujours pas conduire vu qu’il n’as pas le permis !)


2 - Montage:

Une carte Arduino Uno avec quelques câbles et un module MPU6050 ou 6500, ou encore 9250 suffirait.

Montage Arduino Uno et module MPU6050

3 - Programmation :

#include "Wire.h"

const int MPU_addr=0x68; int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;

int minVal=265; int maxVal=402;

double x; double y; double z;

void setup(){
Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B);
Wire.write(0);
Wire.endTransmission(true);
Serial.begin(9600);
}
void loop(){
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true);
AcX=Wire.read()<<8|Wire.read();
AcY=Wire.read()<<8|Wire.read();
AcZ=Wire.read()<<8|Wire.read();
int xAng = map(AcX,minVal,maxVal,-90,90);
int yAng = map(AcY,minVal,maxVal,-90,90);
int zAng = map(AcZ,minVal,maxVal,-90,90);

x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI);
z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);

Serial.print("AngleX= "); Serial.println(x);

Serial.print("AngleY= "); Serial.println(y);

Serial.print("AngleZ= "); Serial.println(z); Serial.println("-----------------------------------------");
delay(400);
}

Arduino Moniteur serie MPU6050

Mais comme nous aimons faire dans le fun chez Eagle Robotics, nous allons utiliser le shield Joystick designed by Eagle Robotics, lequel dispose d’un joystick, de 4 boutons, un port pour module Bluetooth, un port pour écran Oled 0.96 pouces, et enfin un port pour module accéléromètre gyroscope MPU6050/6500/9250.
En clair pourquoi se contenter du beurre quand on peut avoir l’argent du beurre aussi. (ou pourquoi faire simple quand on peut se compliquer la tâche)
Nous allons donc réaliser un programme qui va lire la donnée des angles x, y, et z et l’afficher dans un premier temps sur l’écran 0.96 pouces.

#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"


#define SCREEN_WIDTH 128 // Largeur de l'écran OLED en pixels
#define SCREEN_HEIGHT 64 // Hauteur de l'écran OLED en pixels

// Declaration de l'écran SSD1306 connecté en I2C (pins SDA, SCL)
#define OLED_RESET 4  
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


const int MPU_addr=0x68; // Adresse I2C du MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
double x; double y; double z;
int minVal=265; int maxVal=402;
void setup() {

Serial.begin(9600);

Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B); 
Wire.write(0); // Reveil du MPU-6050
Wire.endTransmission(true);
// accès à l'écran
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // ou 0x3D 
Serial.println(F("connection impossible"));
for(;;);
}

}

void loop() {

adxl();

delay(40);
}

void adxl(){
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true);
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
Serial.print("AcX = "); Serial.print(AcX);
Serial.print(" | AcY = "); Serial.print(AcY);
Serial.print(" | AcZ = "); Serial.print(AcZ);
Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53); //Température en degrés celcius
Serial.print(" | GyX = "); Serial.print(GyX);
Serial.print(" | GyY = "); Serial.print(GyY);
Serial.print(" | GyZ = "); Serial.println(GyZ);
int xAng = map(AcX,minVal,maxVal,-90,90);
int yAng = map(AcY,minVal,maxVal,-90,90);
int zAng = map(AcZ,minVal,maxVal,-90,90);
x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI);
z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);

//Affichage du résultat sur l'écran 0.96 pouces
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println(F("X"));
display.setCursor(50,0);
display.println(x);
display.setCursor(0,20);
display.println(F("Y"));
display.setCursor(50,20);
display.println(y);
display.setCursor(0,40);
display.println(F("Z"));
display.setCursor(50,40);
display.println(z);
display.display();
delay(300);
}

Voici le résultat:

MPU6050 et écran 0.96 oled arduino

Bien! maintenant on refait la même chose mais en mieux: on va commander un robot à l'aide de notre module MPU6050 et du Bluetooth. Tiens par exemple le fameux Spiderbot V12 Android qui est un robot à la base prévu pour être piloté par un smartphone Android via une application (la notre Off course). Mais pour l'occasion nous avons creé un liaison automatique  dès la mise sous tension entre le module HC05 du shield Joystick Eagle et le module bluetooth du robot. Du coup le robot est maintenant pilotable à partir du shield joystick, mais aussi à partir de l'application Android sur smartphone: Oh Wait a minute! we just create a new product. In French ça donne: Oulala nous venons de créer un nouveau produit!

Et maintenant le code!

Programme côté Shield:

#include "SPI.h"
#include "Wire.h"
#include "Adafruit_GFX.h"
#include "Adafruit_SSD1306.h"
#include "SoftwareSerial.h"

#define SCREEN_WIDTH 128 // Largeur de l'écran OLED en pixels
#define SCREEN_HEIGHT 64 // Hauteur de l'écran OLED en pixels

// Déclaration de l'écran SSD1306 connecté en I2C (pins SDA, SCL)
#define OLED_RESET 4 // 
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

SoftwareSerial BT (7,8);
const int MPU_addr=0x68; // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
double x; double y; double z; double w;
int minVal=265; int maxVal=402;
char a; // Donnée si on veut recevoir de la donnée Bluetooth

void setup() {


BT.begin(9600); //Activation du Bluetooth

Serial.begin(9600); // Activation du Port série

Wire.begin(); // Activation du MPU6050
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B); 
Wire.write(0); 
Wire.endTransmission(true);


// Activation du Display
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // ou Adresse 0x3D
Serial.println(F("Connection impossible"));
for(;;); 
}

}

void loop() {


Wire.beginTransmission(MPU_addr);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true);
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
int xAng = map(AcX,minVal,maxVal,-90,90);
int yAng = map(AcY,minVal,maxVal,-90,90);
int zAng = map(AcZ,minVal,maxVal,-90,90);
x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI);
z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println(F("X"));
display.setCursor(50,0);
display.println(x);
display.setCursor(0,20);
display.println(F("Y"));
display.setCursor(50,20);
display.println(y);
display.setCursor(0,40);
display.println(F("Z"));
display.setCursor(50,40);
display.println(z);
display.display();
delay(300);
w = x + y + z;
if( w >= 50 && w <= 80){
Serial.print(w);
Serial.println("mode droite");
BT.write('r');
while(w >= 50 && w <= 80){
delay(1);
adxl();
}
Serial.println("exit de droite");
BT.write('s');
}
else if (w >= 190 && w <= 260){
Serial.print(w);
Serial.println("mode arriere");
BT.write('b');
while(w >= 190 && w <= 260){
delay(1);
adxl();
}
Serial.println("exit de arriere");
BT.write('s');
}
else if (w >= 280 && w <= 350){
Serial.print(w);
Serial.println("mode gauche");
BT.write('l');
while(w >= 280 && w <= 350){
delay(1);
adxl();
}
Serial.println("exit de gauche");
BT.write('s');
}
else if (w >= 680 && w <= 720){
Serial.print(w);
Serial.println("mode avant");
BT.write('f');
while(w >= 680 && w <= 720){
delay(1);
adxl();
}
Serial.println("exit de avant");
BT.write('s');
}
else {
Serial.print(w);
Serial.println("mode stop");
}

delay(40);
}

void adxl(){
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true);
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)

int xAng = map(AcX,minVal,maxVal,-90,90);
int yAng = map(AcY,minVal,maxVal,-90,90);
int zAng = map(AcZ,minVal,maxVal,-90,90);
x= RAD_TO_DEG * (atan2(-yAng, -zAng)+PI);
y= RAD_TO_DEG * (atan2(-xAng, -zAng)+PI);
z= RAD_TO_DEG * (atan2(-yAng, -xAng)+PI);
display.clearDisplay();
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0,0);
display.println(F("X"));
display.setCursor(50,0);
display.println(x);
display.setCursor(0,20);
display.println(F("Y"));
display.setCursor(50,20);
display.println(y);
display.setCursor(0,40);
display.println(F("Z"));
display.setCursor(50,40);
display.println(z);
display.display();
delay(300);
w = x + y + z;
}

Le résultat est visible ici: https://www.youtube.com/watch?v=Byz3FzyQ314

Pour toutes questions relatives à ce post, votre meilleur pote "J'ai besoin d'aide svp" est toujours disponible pour vous sur Projet@eagle-robotics.com.