G-Force

Bonsoir à tous!

J'ai dans l'idée de me faire un accéléromètre pour mesurer la force G de ma voiture. Le contrôleur que je vais utiliser est l'Arduino Nano et j'ai commandé ce module pour mesurer l'accélération : https://www.amazon.ca/gp/product/B07P5YZ7ZD/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1 . J'ai déjà fait une partie du code (principalement l'affichage des valeurs sur le LCD et dans le moniteur série). Je n'ai pas toujours reçu mes pièces donc je me prends d'avance. J'ai fouillé un peu pour trouver comment analyser mes valeurs analogiques mais je n'ai rien trouvé de simple. J'aimerais donc avoir quelques pistes de solutions. Voici la partie de code que j'ai fait

[code]
//-------------------------------------------------------------LCD----------------------------------------------------------------------------
#include <LiquidCrystal.h>
const int rs = 12, en = 11, d4 = 6, d5 = 5, d6 = 4, d7 = 3;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
//-------------------------------------------------------Accelerometer-------------------------------------------------------------------------
const int INT = 2 ;
//----------------------------------------------------------Bouton----------------------------------------------------------------------------
const int Bouton = 3 ;
int BoutonState = 0 ;
//----------------------------------------------------------Mémoires--------------------------------------------------------------------------
int MEM1 = 0 ;
int MEM2 = 0 ;
int MEM3 = 0 ;
//-----------------------------------------------------------Setup-------------------------------------------------------------------------------
void setup() {
Serial.begin(9600);
lcd.begin(16,2);
lcd.setCursor(0, 0); 
lcd.print("Initialization...");
pinMode (INT,OUTPUT) ;
pinMode (Bouton,INPUT) ;
int MEM3 = 1 ;
}
//--------------------------------------------------------EndSetup-----------------------------------------------------------------------------
//---------------------------------------------------------Loop--------------------------------------------------------------------------------
void loop() {
//----------------------------------------------------Data Acquisition--------------------------------------------------------------------------
//------------------------------------------------------------Menus-----------------------------------------------------------------------------
if (BoutonState = HIGH and MEM3){
MEM1=1;
MEM3=0;
}
if (BoutonState = HIGH and MEM1){
MEM1=2;  
MEM1=0;
}
if (BoutonState = HIGH and MEM2){
MEM1=3;  
MEM2=0;
}
//------------------------------------------------------Data Showing----------------------------------------------------------------------------
Serial.print("X G-Force : ") ;
Serial.print(XGForce) ;
Serial.print("        Max X G-Force : ") ;
Serial.print(MaxXGForce) ;
Serial.print("        Y G-Force : ") ;
Serial.print(YGForce) ;
Serial.print("        Max Y G-Force : ") ;
Serial.print(MaxYGForce) ;
Serial.print("        Z G-Force : ") ;
Serial.print(ZGForce) ;
Serial.print("        Max Z G-Force : ") ;
Serial.print(MaxZGForce) ;
Serial.print("        Max Y G-Force : ") ;
Serial.print(MaxYGForce) ;
Serial.print("        Z G-Force : ") ;
Serial.print(ZGForce) ;
Serial.print("        Max Z G-Force : ") ;
Serial.println(MaxZGForce) ;

if (not MEM1 and not MEM2 and MEM3){
lcd.clear () ;
lcd.setCursor(0,0) ;
lcd.print("X G-Force : ") ;
lcd.print(XGForce) ;
lcd.setCursor(0,1) ;
lcd.print("Max X G-Force : ") ;
lcd.println(MaxXGForce) ;
delay(50);
}
if (MEM1 and not MEM2 and not MEM3){
lcd.clear () ;
lcd.setCursor(0,0) ;
lcd.print("Y G-Force : ") ;
lcd.print(YGForce) ;
lcd.setCursor(0,1) ;
lcd.print("Max Y G-Force : ") ;
lcd.println(MaxYGForce) ;
delay(50);
}
if (not MEM1 and MEM2 and not MEM3){
lcd.clear () ;
lcd.setCursor(0,0) ;
lcd.print("Z G-Force : ") ;
lcd.print(ZGForce) ;
lcd.setCursor(0,1) ;
lcd.print("Max Z G-Force : ") ;
lcd.println(MaxZGForce) ;
delay(50);
}

int SCL = analogRead(A5);
int SDA = analogRead(A4);
int BoutonState = digitalRead(Bouton);

}
}
//--------------------------------------------------------EndLoop-----------------------------------------------------------------------------------

[/code]

Attention une affectation c’est = alors que pour un test d’égalité c’est == qu’il faut utiliser

 if (BoutonState [color=red]=[/color] HIGH and MEM3){

Il faudrait des else entre ces if sinon... (faites le code à la main pour voir ce qu’il se passe)

Vous avez une variable globale int BoutonState = 0 ;qui est celle utilisée tout au long de la loop sans avoir lu la pin du bouton, puis Vous re-déclarez cette variable en local et lisez BoutonState à la fin de la loop.. lire ce qu’est la portée d’une variable.

Évitez d’utiliser SCL et SDA comme nom de variables, ce sont des noms pour la communication en I2C:
SDA (Serial Data Line) : ligne de données bidirectionnelle,
SCL (Serial Clock Line) : ligne d'horloge de synchronisation bidirectionnelle.

=> Qu’est-ce qui est branché sur A4 et A5 ? Utilisez un nom parlant associé. De plus telles que définies ces 3 variables locales en fin de loop ne servent à rien (le compilateur va les dégager).

Indentez (ctrl-T ou sur Mac cmd-T) le code pour voir mieux les blocs {}

MEM1 MEM2 et MEM3 sont des noms qui ne nous disent pas à quoi servent ces variables. S’ils servent à différencier 3 états successifs pourquoi ne pas avoir une seule variable (avec un nom parlant) qui ferait 0,1,2,0,1,2,0,1,2... ?

Merci pour les conseils! Toutefois, J'aimerais avoir, une fois que je pourrais lire mes valeurs, à quoi ces dernières vont ressembler. Est-ce que je vais lire plusieurs valeurs ou seulement une que je devrais décortiquer? Ensuite, comment utiliser les valeurs pour les convertir en Force G? Merci! :slight_smile:

Votre produit est un GY-521 MPU-6050. Il se compose d’un Gyroscope et accéléromètre sur 3 axes, il permet donc de mesurer les accélérations linéaires et angulaires dans les trois axes de l’espace.

Cherchez des tutos pour MPU-6050, vous en trouverez plein (un exemple ici) ainsi que des bibliothèques qui facilitent la lecture des informations fournies par le module.

Ensuite un g est égal à l'accélération de la pesanteur à la surface de la Terre soit 9,80665 ms-2

Donc une fois obtenu vos vecteurs accélération en ms-2 vous divisez par 9,80665 et vous avez le nombre de g.

Une autre façon de faire c’est de travailler plus près du matériel. Le MPU délivre une valeur sur 16 bits (65536 valeurs possibles) qui représente l’accélération entre -x et +x directement en g. Il existe un registre de configuration qui permet de régler le x à ±2g ±4g, ±8g ou ±16g.

Donc si vous pensez ne pas être soumis à plus de 2g d’accélération positive ou négative par exemple vous réglez le registre à la bonne valeur et vous obtenez donc une resolution de 4g / 65536 directement en lisant le registre d’accélération.

PS: Lire la data sheet du mpu serait aussi un bon moyen de comprendre comment il fonctionne

J'ai fait un truc qui pourrait te convenir, décrit ici, par contre ce n'est pas le même accéléromètre (ADXL335). Tu peux t'en inspirer.

Bonjour à vous, ¸

Je viens de recevoir mon matériel mais je crois que je me suis trompé lors de l'achat de la carte. J'ai commandé cet item : https://www.amazon.ca/gp/product/B07KC9C6H5/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1 . Est-ce possible que je pourrai pas l'utiliser puisque c'est un shield? Je voulais commander la carte Arduino Nano. Merci de votre aide!

ce que vous avez commandé c'est trois exemplaire de clones d'Arduino Nano (donc bien des "compatibles" Nanos)

Au début vous nous avez dit avoir commandé trois GY-521 MPU-6050

ni dans un cas ni dans l'autre il ne s'agit de shields... Vous pouvez les connecter les uns aux autres en soudant les headers et les installant sur une breadboard ou un plaque pastillée et en mettant des fils de liaison.

est-ce que l'arduino que vous vouliez commander c'était celui ci: ARDUINO NANO 33 IOT ? il s'appelle Nano aussi mais n'a rien à voir avec les anciens Nano... Ce nouveau produit embarque un IMU (LSM6DS3) directement sur la carte et est bien plus puissant... mais pas le même prix unitaire non plus.

Ouff merci! Non c'est bien ce que je voulais commander. Toutefois, on dirait que je n'ai pas les drivers nécessaires sur mon ordinateur pour la faire fonctionner. Je ne suis pas capable de télécharger un programme sur la Nano à partir de l'IDE. Quand je vais sur le Gestionnaire des périphériques, l'ordinateur voit le périphérique mais c'est écrit USB Serial avec un icône d'avertissement (pas de pilote).

UPDATE : J'ai réussi à télécharger dessus en suivant cette procédure : https://www.instructables.com/Arduino-Nano-USB-Not-Recognizing-Fix/ .

Bonjour!
J'ai pris ce site : Utilisation d'un Module MPU6050 avec Arduino • AranaCorp pour les branchements et le code. J'ai ajouté les bibliothèques nécessaires et je réussi à l'envoyer dans la Nano. Je sais que la carte est alimentée puisqu'une lumière verte allume sur le module. Toutefois, dans le moniteur série, c'est comme si le module n'est pas détecté. J'y lis : Failed to find MPU6050 chip .

Dans le tuto ils disent

Pour s’interfacer avec le module GY-521, et donc le MPU6050, nous allons utiliser la librairie du même nom Adafruit_MPU6050.h. Il est important de noter que, selon le module utilisé, il vous faudra peut être modifier l’adresse I2C pour pouvoir récupérer les mesures.

vous avez vérifié ?

Sinon avez vous vérifié le débit de la console par rapport à votre code ? (Dans le tuto ça se traîne, c’est mis à 9600)

Non en effet je n'ai pas vérifié, comment est-ce que je pourrais trouver cette info? À combien je devrais mettre le débit selon vous?

Update : J'ai réussi à trouver l'info en faisant cette procédure : LCD I2C: tout pour que ça marche - Tutoriels et cours - Arduino Forum .

Dans le moniteur série, je lis (comme mentionné dans la procédure)
I2C Scanner
Scanning...
I2C device found at address 0x68 !
done

Après quelques recherches, j'ai réussi à lire des valeurs avec ce code :

[code]
// MPU-6050 Short Example Sketch
// By Arduino User JohnChi
// August 17, 2014
// Public Domain
#include<Wire.h>
const int MPU_addr=0x68;  // I2C address of the MPU-6050
int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
void setup(){
  Wire.begin();
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(9600);
}
void loop(){
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,14,true);  // request a total of 14 registers
  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);  //equation for temperature in degrees C from datasheet
  Serial.print(" | GyX = "); Serial.print(GyX);
  Serial.print(" | GyY = "); Serial.print(GyY);
  Serial.print(" | GyZ = "); Serial.println(GyZ);
  delay(333);
}

[/code]

Toutefois, avec l'autre, rien à faire...

OK donc votre module est bien connecté et à la bonne adresse.

Essayez un des codes d’exemple de Adafruit . Leur bibliothèque est testée avec leur produit. Les copies chinoises peuvent avoir des défauts que la bibliothèque n’attend pas.

Votre second code donne les valeurs brutes échantillonnées, lues au niveau bas. Si les valeurs ont l’air cohérente c’est un bon début.

Malheureusement le code d'exemple d'Adafruit ne me donne pas de valeurs cohérentes :

4⸮⸮⸮2J⸮QE⸮Q֠e⸮⸮⸮⸮QA⸮⸮⸮Q^⸮pa⸮⸮⸮T0⸮⸮⸮q⸮⸮⸮⸮p8T0a⸮⸮⸮Q⸮R⸮A⸮P⸮⸮⸮;⸮@⸮2⸮I⸮⸮⸮⸮

Dans celui de mon post précédent, j'y lis ces valeurs :

AcX = -1424 | AcY = 17 | AcZ = 4104 | Tmp = 49.21 | GyX = -518 | GyY = -524 | GyZ = -137
AcX = -1428 | AcY = 16 | AcZ = 4095 | Tmp = 49.21 | GyX = -520 | GyY = -521 | GyZ = -143
AcX = -1431 | AcY = 17 | AcZ = 4089 | Tmp = 49.21 | GyX = -525 | GyY = -525 | GyZ = -139
AcX = -1425 | AcY = 20 | AcZ = 4093 | Tmp = 49.21 | GyX = -522 | GyY = -526 | GyZ = -140

Croyez-vous quelles sont bonnes et cohérentes?

La vitesse (débit en bauds) de la console série doit être réglé à la vitesse choisie dans le code.
Si c’est Serial.begin(9600);alors Réglez la console sur 9600

Si c’est Serial.begin(115200);alors Réglez la console sur 115200

C'était bien ça. Toutefois, peu importe l'exemple d'Adafruit que j'utilise, je lis :
Adafruit MPU6050 test!
Failed to find MPU6050 chip

Par contre, quand je refais le test pour l'adresse l2C, je lis bien la même adresse que l'autre fois, soit :
I2C Scanner
Scanning...
I2C device found at address 0x68 !
done

Finalement, j'ai réussi à convertir mes valeurs en force G et en angle en réutilisant mon ancien code et en le modifiant pour la partie angle.

[code]
#include<Wire.h>
const int MPU_addr=0x68;  // I2C address of the MPU-6050
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);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(9600);
}
void loop(){
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr,14,true);  // request a total of 14 registers
  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)

   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("AcX = "); Serial.print(AcX/16384.00);
  Serial.print(" | AcY = "); Serial.print(AcY/16384.00);
  Serial.print(" | AcZ = "); Serial.print(AcZ/16384.00);
  Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53);  //equation for temperature in degrees C from datasheet
  Serial.print(" | AngleX= "); Serial.print(x);
  Serial.print(" | AngleY = "); Serial.print(y);
  Serial.print(" | AngleZ = "); Serial.println(z);
  Serial.println("---------------------------------------------------------------------------------------------------------");
  delay(500);
}

[/code]

Voici les valeurs que je lis dans le moniteur :

AcX = -0.07 | AcY = -0.11 | AcZ = 1.03 | Tmp = 36.53 | AngleX= 352.46 | AngleY = 354.92 | AngleZ = 236.11

AcX = -0.07 | AcY = -0.11 | AcZ = 1.03 | Tmp = 36.53 | AngleX= 352.62 | AngleY = 355.02 | AngleZ = 236.06

AcX = -0.06 | AcY = -0.11 | AcZ = 1.03 | Tmp = 36.53 | AngleX= 352.51 | AngleY = 355.17 | AngleZ = 237.30

AcX = -0.07 | AcY = -0.11 | AcZ = 1.03 | Tmp = 36.53 | AngleX= 352.63 | AngleY = 355.13 | AngleZ = 236.61

Si je ne me trompe pas, tout à l'air ok. Si je comprends bien, lorsque le module n'est pas complètement à plat, je lis une force G minime en X et Y puisque ces vecteurs entrent en quelque sorte dans la force de la gravité de la Terre lorsque le module est incliné. Ensuite, je me demande pourquoi je lis une force G sur le vecteur Z (ce n'est pas sensé être sur le vecteur Y puisque c'est celui qui est parallèle à la force gravitationnelle?)

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.