Programme gyroscope
Programme gyroscope
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 << | 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 << | 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 << | 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.
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 << | 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 << | 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 << | 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.
Re: Programme gyroscope
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).
et qu'est-ce qu'on écrit ?
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:
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
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:
Dernière chose, je peux essayer d'expliquer la fonction
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 : on envoie sur le fil de données un byte qui contient une adresse de registre.
c'est ce que veut dire le
A ce moment là, l'esclave met à disposition le registre choisi, et est en attente jusqu'à ce qu'il reçoive une requête.
Après on attend juste la réponse aussi longtemps qu'il faut et on la retourne grâce à :
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
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);
Code : Tout sélectionner
Wire.write(0b00001111);
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();
}
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();
}
Code : Tout sélectionner
if (echelle==500)
{
Wire.beginTransmission(L3G4200D_Adresse);
Wire.write(CTRL_REG4);
Wire.write(0b00010000);
Wire.endTransmission();
}
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;
}
On demande à la carte arduino de parler à cet esclave en lui donnant son adresse.
ensuite
Code : Tout sélectionner
wire.write(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);
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
Re: Programme gyroscope
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é.
Prépa, école, M2, thèse (optique/images) ->ingé dans le privé.
Re: Programme gyroscope
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.
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.
Re: Programme gyroscope
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.
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é.
Prépa, école, M2, thèse (optique/images) ->ingé dans le privé.
Re: Programme gyroscope
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
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
Re: Programme gyroscope
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).
Re: Programme gyroscope
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).
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).
Re: Programme gyroscope
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 .. )
Re: Programme gyroscope
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.
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é.
Prépa, école, M2, thèse (optique/images) ->ingé dans le privé.