Programme gyroscope

Une petite question sur votre TIPE...

Messages : 0

Inscription : 28 nov. 2015 14:29

Profil de l'utilisateur : Élève de lycée

Programme gyroscope

Message par Mehdi368 » 09 avr. 2018 23:55

Bonsoir,

Dans le cadre de l'élaboration d'un système d'acquisition d'angle, j'ai jugé bon d'utiliser un gyroscope qui ne donne pas un angle mais une accélération angulaire. Hors, je sais très bien qu'il suffit d'intégrer les valeurs d'accélérations que le gyro fournit, cependant, la difficulté est que je n'arrive pas à déchiffrer le programme fourni avec le composant et donc d'écrire quelque chose qui réalisera une acquisition angulaire. Est ce que quelqu'un pourrait m'éclairer ou me guider sur l'écriture du programme car je suis totalement perdu.

N.B. : Je n'ai besoin d'une acquisition que selon un seul axe !

Voici le programme : Attention, c'est assez long ..


/************************************************************************
*
* Test of the Pmod
*
*************************************************************************
* Description: Pmod_GYRO
* The 3 components X, Y, and Z of the gyroscope
* are displayed in the serial monitor
*
* Material
* 1. Arduino Uno
* 2. Pmod GYRO
*
************************************************************************/

// Déclaration des adresses du module
#define L3G4200D_Adresse 0x69 // adress of L3G4200D
#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24
#define REGISTRE_MSB_X 0x29 // MSB axe X
#define REGISTRE_LSB_X 0x28 // LSB axe X
#define REGISTRE_MSB_Y 0x2B // MSB axe Y
#define REGISTRE_LSB_Y 0x2A // LSB axe Y
#define REGISTRE_MSB_Z 0x2D // MSB axe Z
#define REGISTRE_LSB_Z 0x2C // LSB axe Z

// call library
#include <Wire.h>

int composante_X;
int composante_Y;
int composante_Z;

byte composante_MSB_X;
byte composante_LSB_X;
byte composante_MSB_Y;
byte composante_LSB_Y;
byte composante_MSB_Z;
byte composante_LSB_Z;

void setup(void)
{
Serial.begin(9600); // initialization of serial communication
Wire.begin(); // initialization of I2C communication
Init_L3G4200D(2000);
delay(1000);
}

void loop()
{
Lecture_Module();

Serial.print("X="); // Display of components in the serial monitor
Serial.print (composante_X);
Serial.print('\t'); // tabulation
Serial.print("Y=");
Serial.print (composante_Y);
Serial.print('\t');
Serial.print("Z=");
Serial.print (composante_Z);
Serial.println("");
delay(500);
}

// initialization of L3G4200D
void Init_L3G4200D(int echelle)
{
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG1);
Wire.write(0b00001111);
Wire.endTransmission();
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG2);
Wire.write(0b00000000);
Wire.endTransmission();
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG3);
Wire.write(0b00001000);
Wire.endTransmission();
if (echelle==250)
{
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG4);
Wire.write(0b00000000);
Wire.endTransmission();
}
if (echelle==500)
{
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG4);
Wire.write(0b00010000);
Wire.endTransmission();
}
else
{
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG4);
Wire.write(0b00110000);
Wire.endTransmission();
}
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG5);
Wire.write(0b00000000);
Wire.endTransmission();
}

// Reading values X, Y et Z
void Lecture_Module()
{
composante_MSB_X=Lecture_Registre(REGISTRE_MSB_X); // lecture MSB_X
composante_LSB_X=Lecture_Registre(REGISTRE_LSB_X); // lecture LSB_X
composante_X=((composante_MSB_X << 8) | composante_LSB_X); // Component reconstruction_X
composante_MSB_Y=Lecture_Registre(REGISTRE_MSB_Y); // lecture MSB_Y
composante_LSB_Y=Lecture_Registre(REGISTRE_LSB_Y); // lecture LSB_Y
composante_Y=((composante_MSB_Y << 8) | composante_LSB_Y); // Component reconstruction_Y
composante_MSB_Z=Lecture_Registre(REGISTRE_MSB_Z); // lecture MSB_Z
composante_LSB_Z=Lecture_Registre(REGISTRE_LSB_Z); // lecture LSB_Z
composante_Z=((composante_MSB_Z << 8) | composante_LSB_Z); // Component reconstruction_Z
}

// Reading a register from the module L3G4200D
int Lecture_Registre(byte registre)
{
int v;
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(registre);
Wire.endTransmission();
Wire.requestFrom(L3G4200D_Adresse, 1);
while(!Wire.available());
v = Wire.read();
return v;
}


Cordialement.

Messages : 3823

Inscription : 17 avr. 2012 21:19

Profil de l'utilisateur : Élève de lycée

Re: Programme gyroscope

Message par bullquies » 10 avr. 2018 02:58

tu es sûr que tu veux te lancer dans la compréhension du fonctionnement d'un microcontrolleur ?

Est-ce que tu arrives déjà à faire tourner ça avec le matériel que tu as déjà ou tu bloques à ce niveau là ?

Déjà 1/ est-ce que tu sais ce que c'est le protocole de communication i2c ? Si tu as vu le branchement à faire n'oublie pas d'ajouter les résistances de pull-up sur SDA et SCL

2/ tu vas bien t'amuser. Pour comprendre le code, il faut aller voir la datasheet du capteur (et non plus la datasheet de la carte que tu veux utiliser) https://cdn.sparkfun.com/datasheets/Sen ... 265057.pdf

Vas voir la table 18 à la page 27

Dans la colonne "Register address", au format hexadecimal (hex), tu as les adresses des différents registres. A côté le type de registre (read, write ou read+w: r, w, rw)

Ensuite tu vas voir dans la description des registres juste après (page 29)

Par exemple dans le code qui t'es fournit, tu vois qu'on écrit sur le registre CTRL_REG1 (à l'adresse 0x20).

Code : Tout sélectionner

Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG1);
et qu'est-ce qu'on écrit ?

Code : Tout sélectionner


Wire.write(0b00001111);
Donc 00001111 en binaire.

Donc tu vas voir encore une fois sur la table correspondante et tu vois quelles paramètres ça modifie. En particulier je vois que les trois derniers bits activent respectivement les axes X Y et Z. Peut-être que là tu devras modifer qqch pour n'activer qu'un des axes.

Je vais faire un autre exemple simple parce que c'est le plus clair:

Code : Tout sélectionner

if (echelle==250)
{
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG4);
Wire.write(0b00000000);
Wire.endTransmission();
}
if (echelle==500)
{
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG4);
Wire.write(0b00010000);
Wire.endTransmission();
}
Bon je suis pas rentré dans le détail du mems mais si je vais voir à quoi correspondent les bits écrits dans CTRL_REG4 sur la datasheet (table 30 et table 31 page 32), je vois que ça parle de "scale selection", choix d'échelle. Et je vois que la paire de bits FS1 et FS0 permet de changer cette échelle. Si les bits valent 00, on a 250dps. Si les bits sont à 01 -> 500dps. 10 -> 2000dps. 11 -> 2000dps.

Supposons que je veuille pas toucher les autres paramètres (BDU, BLE, STE, SIM), je les laisse donc aux valeurs par défaut 0 ou 00.

donc si je veux une échelle à 250 je lis qu'il faut mettre les bits FS1 et FS0 à 00. donc dans le registre 4 j'écris (d'où le "write()") 00000000 en binaire. Le code correspondant c'est donc

Code : Tout sélectionner

if (echelle==250)
{
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG4);
Wire.write(0b00000000);
Wire.endTransmission();
}
si je veux une échelle à 500 je lis qu'il faut mettre les bits FS1 et FS0 à 01. Donc je balance 00010000 dans le registre, soit:

Code : Tout sélectionner

if (echelle==500)
{
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG4);
Wire.write(0b00010000);
Wire.endTransmission();
}
Dernière chose, je peux essayer d'expliquer la fonction

Code : Tout sélectionner

// Reading a register from the module L3G4200D
int Lecture_Registre(byte registre)
{
int v;
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(registre);
Wire.endTransmission();
Wire.requestFrom(L3G4200D_Adresse, 1);
while(!Wire.available());
v = Wire.read();
return v;
}
Donc L3G4200D_Adresse (qui vaut 0b1101001 ou 0x69) est fournie par le constructeur. Voir toujours ici https://cdn.sparkfun.com/datasheets/Sen ... 265057.pdf 5.1.1 "i2c operation". C'est la slave address.

On demande à la carte arduino de parler à cet esclave en lui donnant son adresse.

ensuite

Code : Tout sélectionner

wire.write(registre)
: on envoie sur le fil de données un byte qui contient une adresse de registre.

c'est ce que veut dire le
The I2C embedded in the L3G4200D behaves like a slave device, and the following protocol
must be adhered to. After the START (ST) condition, a slave address is sent. Once a slave
acknowledge (SAK) has been returned, an 8-bit sub-address is transmitted.


A ce moment là, l'esclave met à disposition le registre choisi, et est en attente jusqu'à ce qu'il reçoive une requête.

Code : Tout sélectionner

Wire.requestFrom(L3G4200D_Adresse, 1);
Après on attend juste la réponse aussi longtemps qu'il faut et on la retourne grâce à :

Code : Tout sélectionner

while(!Wire.available());
v = Wire.read();
return v;



Voilà à toi de comprendre rapidement comment marche une communication i2c. Essaye un code simple pour te familiariser si possible.

Ensuite tu vas devoir lire un peu la datasheet du capteur et du microcontrolleur pour comprendre quelle données et quels paramètres sont enregistrés dans quel registre et les modifier à ta volonté.

Désolé j'ai sommeil donc si c'est pas très clair pose des questions, je répondrai plus tard :)
The Axiom of Choice is obviously true, the Well-Ordering Principle is obviously false, and nobody knows about Zorn's Lemma. - Jerry Bona

Messages : 9679

Inscription : 30 juil. 2008 16:59

Profil de l'utilisateur : Élève de lycée

Re: Programme gyroscope

Message par fakbill » 11 avr. 2018 17:53

Intégrer deux fois une acceleration pour obtenir une position est rarement une bonne chose pour une raison évidente, laquelle?
Pas prof.
Prépa, école, M2, thèse (optique/images) ->ingé dans le privé.

Messages : 0

Inscription : 28 nov. 2015 14:29

Profil de l'utilisateur : Élève de lycée

Re: Programme gyroscope

Message par Mehdi368 » 12 avr. 2018 00:25

Bonsoir !

Merci pour vos réponses, pour le code c'est un peu fastidieux à comprendre, cependant, existe-t-il une commande en fait pour intégrer deux fois ?

Il est vrai qu'il y'aura des constantes qui vont sortir de l'intégration, mais je pense qu'avec un bon paramétrage on peut faire une bonne acquisition angulaire à partir de l'accélération (du moins c'est ce que m'a conseillé mon prof de SI, autrement, je devais me débrouiller avec une masse).

Cordialement.

Messages : 9679

Inscription : 30 juil. 2008 16:59

Profil de l'utilisateur : Élève de lycée

Re: Programme gyroscope

Message par fakbill » 12 avr. 2018 15:20

Non, il n’y a pas de commande toute faite sur ce genre de matos pour intégrer deux fois. Le penser montre que tu n’as pas compris ce qu’est ce genre de matos. C’est un microcontroleur auquel tu parles via un langage *bas niveau*
Pour le reste, non les constantes ne sont pas le problème. Le problème c’est la dérive.
Par exemple, sans le bouger, ton gyro doit sortir une accélération nulle. En pratique, il va toujours sortir une accélération pas exactement nulle et l’erreur va grandir au cours du temps. Intègre ça deux fois et tu trouveras n’importe quoi (sauf si ton gyro est très très bon). La seule solution viable est de recaler très souvent.
Pas prof.
Prépa, école, M2, thèse (optique/images) ->ingé dans le privé.

Messages : 16

Inscription : 01 août 2011 21:09

Profil de l'utilisateur : Élève de lycée

Re: Programme gyroscope

Message par Hazherty » 12 avr. 2018 15:26

Une constante, à la rigueur, on peut faire avec.

Le problème, ce sont les erreurs générées. Ton accélération mesurée, puis ton calcul de vitesse seront forcément incertain, et tu vas intégrer ensuite ces erreurs pour obtenir la position. Ça va générer une dérive temporelle en position.

Le paramétrage peut être très bon, il va juste retarder l'échéance. Selon ton système et la qualité du réglage, il peut mettre 2s ou 30min à dériver.

Il existe un moyen assez simple d'encadrer la dérive angulaire (pour peu que ton machin tourne sur un seul axe).

EDIT : cramé par fakbill :mrgreen:

Messages : 0

Inscription : 28 nov. 2015 14:29

Profil de l'utilisateur : Élève de lycée

Re: Programme gyroscope

Message par Mehdi368 » 13 avr. 2018 08:00

Merci de me montrer ce problème. Il est vrai que à chaque fois que je lance le programme j'ai des valeurs non nulle, je pensais que c'était des vibrations qu'il arrivait à percevoir. D'après mon prof de SI c'est du matos de qualité, on peut donc dire qu'il peut marcher sans trop se gourrer pendant 15 min. Je pourrais éteindre puis le rallumer sur une période qui feras qu'il n'auras pas trop ce souci. Vous en pensez quoi ? ( Bien-sûr recadrer reste une solution qui me convient).

Messages : 16

Inscription : 01 août 2011 21:09

Profil de l'utilisateur : Élève de lycée

Re: Programme gyroscope

Message par Hazherty » 13 avr. 2018 08:21

Le problème vient plus de la méthode. Tu vas te baser sur l'angle calculé en $ t_{n-1} $ pour obtenir l'angle en $ t_n $. Les erreurs cumulées vont se retrouver dans la suite, même si tu reset le gyroscope et que, pendant un certain temps, tu vas accumuler peu d'erreur en plus.

Pour palier à ce problème, il te faut une redondance d'information. Donc un autre système de mesure d'angle, indépendant du gyroscope, potentiellement moins précis sur $ [0, 2\pi[ $, mais qui peut te donner quelques valeurs d'angles connues de façon "sûre" (sans dérive).

Messages : 0

Inscription : 28 nov. 2015 14:29

Profil de l'utilisateur : Élève de lycée

Re: Programme gyroscope

Message par Mehdi368 » 13 avr. 2018 14:27

Il me semble que je peux utiliser un système "mécanique" qui mesurera en faite l'angle par rapport à g. Mais c'est assez laborieux à faire (on a écarté ça avec mon prof encadrant .. )

Messages : 9679

Inscription : 30 juil. 2008 16:59

Profil de l'utilisateur : Élève de lycée

Re: Programme gyroscope

Message par fakbill » 13 avr. 2018 15:39

Tu peux également faire l'expérience en ayant conscience du probleme mais sans rien faire pour le "corriger".
Tu verras bien ce que ça donne.
Il n'y a pas de solution miracle à ce probleme.
Cependant, sache que c'est, en general, un mauvaise idée de mesurer Xpointpoint pour connaitre X. Si on peut, on fait autrement.
Pas prof.
Prépa, école, M2, thèse (optique/images) ->ingé dans le privé.

Répondre