PMod Nav : Problème de communication avec le LSM9DS1

Bonjour,

Réalisant un TIPE sur le stabilisateur de caméra, mon professeur de SII m'a proposé d'utiliser une carte arduino (une MEGA) et d'utiliser comme centrale inertielle la capteur Pmod Nav.

Cependant je suis totalement novice encore avec Arduino et je ne comprends quel est le problème avec le capteur...
J'ai installé les librairies demandé, effectué les bons branchements et j'ai rentré le code (fourni) suivant :

/************************************************************************
*                                                                                                                                        
*    Test du module Pmod IMU 9 axes + Baromètre  (basé sur le programme de Jim Lindblom)                                        
*                                                                    
*************************************************************************
* Description:  Pmod_NAV                                              
* Toutes les données (accéléromètre, gyroscope, magnétomètre)  sont affichées 
* dans le moniteur série
*  
* Matériel
*        1. Arduino Uno                                       
*        2. Module Pmod NAV (télécharger la bibliothèque 
*        https://github.com/sparkfun/SparkFun_LSM9DS1_Arduino_Library)
*        Licence Beerware
*        
* Câblage           
*        Module<----------> Arduino
*        J1 broche 6        3.3V
*        J1 broche 5        GND
*        J1 broche 4        A5
*        J1 broche 2        A4
************************************************************************/
// Appel des bibliothèques
#include <Wire.h>
#include <SparkFunLSM9DS1.h>

// Déclaration des adresses du module
#define LSM9DS1_M  0x1E 
#define LSM9DS1_AG  0x6B 

LSM9DS1 imu;                                // création de l'objet imu

// Configuration du module
#define PRINT_CALCULATED
#define PRINT_SPEED 250 
static unsigned long lastPrint = 0; 

// Le champ magnétique terrestre varie en fonction de sa localisation.
// Il faut ajouter ou soustraire une constante pour obtenir la bonne valeur
// du champ magnétique à l'aide du site suivant
// http://www.ngdc.noaa.gov/geomag-web/#declination
#define DECLINATION -0.33 // Declinaison (en degrés) pour Paris.

void setup(void) 
{
   Serial.begin(115200);                                // initialisation de la liaison série 
   imu.settings.device.commInterface = IMU_MODE_I2C;    // initialisation du module
   imu.settings.device.mAddress = LSM9DS1_M;
   imu.settings.device.agAddress = LSM9DS1_AG;
   if (!imu.begin())
  {
    Serial.println("Probleme de communication avec le LSM9DS1.");
    while (1);
  }
}

void loop() 
{
  
  if ( imu.gyroAvailable() )
  {
    imu.readGyro();             // acquisition des données du gyroscope
  }
  if ( imu.accelAvailable() )
  {
    imu.readAccel();           // acquisition des données de l'accéléromètre
  }
  if ( imu.magAvailable() )
  {
    imu.readMag();             // acquisition du magnétomètre
  }
  
  if ((lastPrint + PRINT_SPEED) < millis())
  {
    printGyro();  // Print "G: gx, gy, gz"
    printAccel(); // Print "A: ax, ay, az"
    printMag();   // Print "M: mx, my, mz"
    
    printAttitude(imu.ax, imu.ay, imu.az,-imu.my, -imu.mx, imu.mz);
    Serial.println();
    
    lastPrint = millis(); 
  }
}

void printGyro()
{
  
  Serial.print("G: ");
#ifdef PRINT_CALCULATED
  Serial.print(imu.calcGyro(imu.gx), 2);
  Serial.print(", ");
  Serial.print(imu.calcGyro(imu.gy), 2);
  Serial.print(", ");
  Serial.print(imu.calcGyro(imu.gz), 2);
  Serial.println(" deg/s");
#elif defined PRINT_RAW
  Serial.print(imu.gx);
  Serial.print(", ");
  Serial.print(imu.gy);
  Serial.print(", ");
  Serial.println(imu.gz);
#endif
}

void printAccel()
{  
  
  Serial.print("A: ");
#ifdef PRINT_CALCULATED
  Serial.print(imu.calcAccel(imu.ax), 2);
  Serial.print(", ");
  Serial.print(imu.calcAccel(imu.ay), 2);
  Serial.print(", ");
  Serial.print(imu.calcAccel(imu.az), 2);
  Serial.println(" g");
#elif defined PRINT_RAW 
  Serial.print(imu.ax);
  Serial.print(", ");
  Serial.print(imu.ay);
  Serial.print(", ");
  Serial.println(imu.az);
#endif

}

void printMag()
{  
 
  Serial.print("M: ");
#ifdef PRINT_CALCULATED
  Serial.print(imu.calcMag(imu.mx), 2);
  Serial.print(", ");
  Serial.print(imu.calcMag(imu.my), 2);
  Serial.print(", ");
  Serial.print(imu.calcMag(imu.mz), 2);
  Serial.println(" gauss");
#elif defined PRINT_RAW
  Serial.print(imu.mx);
  Serial.print(", ");
  Serial.print(imu.my);
  Serial.print(", ");
  Serial.println(imu.mz);
#endif
}


void printAttitude(float ax, float ay, float az, float mx, float my, float mz)
{
  float roll = atan2(ay, az);
  float pitch = atan2(-ax, sqrt(ay * ay + az * az));
  
  float heading;
  if (my == 0)
    heading = (mx < 0) ? PI : 0;
  else
    heading = atan2(mx, my);
    
  heading -= DECLINATION * PI / 180;
  
  if (heading > PI) heading -= (2 * PI);
  else if (heading < -PI) heading += (2 * PI);
  else if (heading < 0) heading += 2 * PI;
  
  
  heading *= 180.0 / PI;
  pitch *= 180.0 / PI;
  roll  *= 180.0 / PI;
  
  Serial.print("Pitch, Roll: ");
  Serial.print(pitch, 2);
  Serial.print(", ");
  Serial.println(roll, 2);
  Serial.print("Heading: "); Serial.println(heading, 2);
}

J'ai dans le moniteur de série : Probleme de communication avec le LSM9DS1.
Donc apparemment le capteur ne peut s'initialiser...

Merci de votre aide !

Ton capteur c'est bien celui-ci ?

Pour le branchement, tu as bien fait comme ça (I2C) ? A priori : Mega 20 -- SDA, Mega 21 -- SCL, alim 3.3V

Je ne vois pas de problème dans ton code. Le seul truc qu'il faudrait tester c'est :

#define LSM9DS1_M   0x1E // Would be 0x1C if SDO_M is LOW
#define LSM9DS1_AG  0x6B // Would be 0x6A if SDO_AG is LOW

SDO_M et SDO_AG sont des broches visibles sur le module, de l'autre côté. Si elles sont "en l'air", sont-elles considérées LOW ou HIGH ? Essaye les diverses combinaisons d'adresses (1E/1C et 6A/6B)

hello
ou passer un scaner i2c

// --------------------------------------
// i2c_scanner
//
// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// Version 6, November 27, 2015.
//    Added waiting for the Leonardo serial communication.
//
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//
 
#include <Wire.h>
 
 
void setup()
{
  Wire.begin();
 
  Serial.begin(115200);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\n I2C Scanner");
}
 
 
void loop()
{
  byte error, address;
  int nDevices;
 
  Serial.println("Scan en cours ...");
 
  nDevices = 0;
  for(address = 8; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
 
    if (error == 0)
    {Serial.print("\n");
      Serial.print("peripherique I2C trouve a l'adresse 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("erreur inconnue a l'adresse 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }  
    Serial.print(address,HEX);
   Serial.print(".");
    Serial.print( (address%20) ? "":"\n");  
  }
  if (nDevices == 0)
    Serial.println("pas trouve de peripheriques I2C\n");
  else
    Serial.println("termine\n");
 
  delay(5000);           // wait 5 seconds for next scan
}

Bonjour,

Je suppose que c'est bien celui-ci intégrer dans ce capteur (pmod nav) :

Pour le branchement j'ai respecté ce qui était écrit dans le code et je me suis référé à cette image :

@lesept Le changement des 01x... n'ont pas d'effets; sinon pour les branchements j'ai plutôt du A4 et du A5 du coup ?

@dfgh Pour passer le scanner ça donne ça :

Scan en cours ...
8.9.A.B.C.D.E.F.10.11.12.13.14.
15.16.17.18.19.1A.1B.1C.1D.1E.1F.20.21.22.23.24.25.26.27.28.
29.2A.2B.2C.2D.2E.2F.30.31.32.33.34.35.36.37.38.39.3A.3B.3C.
3D.3E.3F.40.41.42.43.44.45.46.47.48.49.4A.4B.4C.4D.4E.4F.50.
51.52.53.54.55.56.57.58.59.5A.5B.5C.5D.5E.5F.60.61.62.63.64.
65.66.67.68.69.6A.6B.6C.6D.6E.6F.70.71.72.73.74.75.76.77.78.
79.7A.7B.7C.7D.7E.pas trouve de peripheriques I2C

merci de vos réponses

Le scanner te donnera "l'adresse" sous laquelle ton microcontrôleur connaîtra le capteur. Il semble y avoir 2 adresses, une pour le gyromètre, une pour l'accéléromètre. Elles sont définies dans les lignes

// Déclaration des adresses du module
#define LSM9DS1_M  0x1E 
#define LSM9DS1_AG  0x6B

Vérifie que le scanner (oui tu l'exécutes directement tel quel et tu regardes ce qui apparaît sur la console) te donne ces valeurs. S'il donne d'autres valeurs, change-les dans le code. Si tu ne comprends pas le résultat, poste ce que dit la console (tout) sur le forum.

Le scanner donne :

Scan en cours ...
8.9.A.B.C.D.E.F.10.11.12.13.14.
15.16.17.18.19.1A.1B.1C.1D.1E.1F.20.21.22.23.24.25.26.27.28.
29.2A.2B.2C.2D.2E.2F.30.31.32.33.34.35.36.37.38.39.3A.3B.3C.
3D.3E.3F.40.41.42.43.44.45.46.47.48.49.4A.4B.4C.4D.4E.4F.50.
51.52.53.54.55.56.57.58.59.5A.5B.5C.5D.5E.5F.60.61.62.63.64.
65.66.67.68.69.6A.6B.6C.6D.6E.6F.70.71.72.73.74.75.76.77.78.
79.7A.7B.7C.7D.7E.pas trouve de peripheriques I2C

Est ce normal ? On dirait que le capteur n'est même pas branché ?

hello si le scan trouve un périphérique, il te donne l'adresse
voir copie écran jointe, tu verras qu'il a été exécuté avec une méga et qu'il trouve bien la 3231 qui est raccordée en 20 et 21
nota: uno mega
SCL A5 21
SDA A4 20

edit: en complément, il semble que tu ai le choix i2c ou spi
tu as bien fais les raccordements?
CS M Magnetometer Chip Select This pin selects between I2C and SPI on the magnetometer. Keep it HIGH for I2C, or use it as an (active-low) chip select for SPI.
HIGH (1): SPI idle mode / I2C enabled
LOW (0): SPI enabled / I2C disabled.

CS AG Accel/Gyro Chip Select This pin selects between I2C and SPI on the accel/gyro. Keep it HIGH for I2C, or use it as an (active-low) chip select for SPI.
HIGH (1): SPI idle mode / I2C enabled
LOW (0): SPI enabled / I2C disabled.

J'ai pourtant fais ce que tu m'as indiqué mais j'ai toujours le même rapport, pas de périphériques I2C trouvé...

tu as vu mon complément d'info au dessus?

Je n'ai pas l'impression que ce soit un problème de code : peux-tu poster précisément les branchements (tous !)

@dfgh : on voit les bornes CS_M et CS_AG sur le schéma que j'ai mis plus haut. Si elles sont laissées flottantes, ça correspond à LOW ou à HIGH ?

en principe une patte laissée en l'air est considérée en HIGH
pour éviter ces situations "indéterminées, on fixe le potentiel des pattes en l'air en les raccordant soit à VCC soit à GND

Désolé dfgh mais je ne comprend pas trop ton complément d'info...
Sinon pour le branchement :

On ne voit rien : fais une sorte de tableau, genre :

Capteur  ----   Arduino
  Pin x   --  Broche y

Oui pardon tu as raison :

Module<----------> Arduino
*        J1 broche 6        3.3V
*        J1 broche 5        GND
*        J1 broche 4        A5
*        J1 broche 2        A4

Sur ce pinout, les broches du port I2C sont bien les 20 et 21 :

Le pinout du capteur est ici : on lit

  • Pin2 : SCI
  • Pin4 : SCK
    C'est pour le SPI, mais on sait qu'il est utilisable en I2C. En I2C, la pin SCL correspond à l'horloge donc elle doit être reliée à la pin4 du capteur
    Donc :
Module<----------> Arduino
*        J1 broche 6        3.3V
*        J1 broche 5        GND
*        J1 broche 4        21
*        J1 broche 2        20

Si ça ne fonctionne vraiment pas, essaie de l'utiliser en bus SPI...

Avec ce branchage j'obtient bien :

Scan en cours ...
8.9.A.B.C.D.E.F.10.11.12.13.14.
15.16.17.18.19.1A.1B.1C.1D.
peripherique I2C trouve a l'adresse 0x1E  !
1E.1F.20.21.22.23.24.25.26.27.28.
29.2A.2B.2C.2D.2E.2F.30.31.32.33.34.35.36.37.38.39.3A.3B.3C.
3D.3E.3F.40.41.42.43.44.45.46.47.48.49.4A.4B.4C.4D.4E.4F.50.
51.52.53.54.55.56.57.58.59.5A.5B.5C.
peripherique I2C trouve a l'adresse 0x5D  !
5D.5E.5F.60.61.62.63.64.
65.66.67.68.69.6A.
peripherique I2C trouve a l'adresse 0x6B  !
6B.6C.6D.6E.6F.70.71.72.73.74.75.76.77.78.
79.7A.7B.7C.7D.7E.termine

Donc à priori c'était les bon ports. Pour l'utilisation de mon programme il faut que je garde ce branchement du coup ?

Ben oui...

C'est bon ça fonctionne !
Merci beaucoup à vous 2 :slight_smile:

HipHipHip===>HOURRA :slight_smile: