[HMC5883L] Fixer des limite pour le servo

Bonjour les amis,

Y a quelques mois j'ai fait appel a vous pour ce projet.
Aujoud'hui je reviens vers vous car j'ai détecté un truc que je n'arrive pas a resoudre tout seul.

Voila mon souci:

J'ai une HMC5883l qui est connectée bien sur a une carte arduino uno puis un servo moteur.
je veux faire en sorte que la boussole control la direction de mon engin ( Kontiki) jusqu'ici tout va bien quand je bouge la bousole le servo change la direction pour la corriger vers celle de départ.

NB: - Servo est a la position 90 au départ
- HeadingDegree Position initiale dés le fonctionnement de systeme (j'oriente le kontiki vers la direction que je souhaite avant de demarrer le systeme)

Quand je fesais les tests j'etait sur le cap entre 90 et 130 (ce cap représente la position initiale celle que je veux que le moteur corrigé a chaque fois le kontiki change de direction) du coup puisque le moteur soit : va partir de 90 vers 180 ou vers 0 ( +90 ou -90 ) dans ce cas pas de pb mais quand j'ai recement fait le test et que j'etait sur 20 degré (20 vers 0 vers -4 vers - 15 par exemple) le servo change completement la direction car l'ecart devient grand et aussi change la polarisation (soit de + vers le - ou le contraire) et c'est la le souci au fait.

CODE

#include <Servo.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>

/* Assign a unique ID to this sensor at the same time */
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);
Servo myservo1;
Servo myservo2;

int servoPos = 90;
int servoPos1 = 90;

int memo_cap_degres;

int compassCorrection = 0; // set to 0 (not used)

int MaxLimit = 180;
int MinLimit = 0;

int Limit_drt = 4;
int Limit_gch = 176;

//on suppose que les BP actionnés ammenent GND sur leur entrée
byte LED[] = {0, 2, 3, 4,  5}; // les LEDS sont sur 3, 4, 5, 6
byte REED[] = {0, 7, 8, 10, 13}; // les BP sont sur 7, 8, 9, 10
int Relais[] = {0, 12};// les Relais sont sur 11,12 case 0 non utilisée
unsigned long deb_tempo[]={0,0,0,0,0};
unsigned long tempo [] = {0000, 5000, 10000, 20000, 30000};//tableau des temps désirés
boolean  flag_tempo[] = {false, false, false, false, false, false};

void setup() 
{
  Serial.begin(9600);
  for ( byte f = 1; f <= 4; f++)
  {
    pinMode(REED[f],     INPUT_PULLUP);
    pinMode(LED[f],      OUTPUT); digitalWrite(LED[f], LOW);
  }
  pinMode(Relais[1], OUTPUT); digitalWrite(Relais[1], LOW);
  pinMode(Relais[2], OUTPUT); digitalWrite(Relais[2], LOW);
  test_leds();

    if(!mag.begin())
  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while(1);
  }
    /* Display some basic information on this sensor */
  displaySensorDetails();
  myservo1.write(90);
  myservo2.write(90);
  delay(2000);
}

void displaySensorDetails(void)
{
  sensor_t sensor;
  mag.getSensor(&sensor);
  myservo1.attach(6);
  myservo2.attach(11);
  delay(500);
}

static int headingInitial;

void loop()
{
  extinction_leds();
  
  /*Section du HMC5883l*/

  sensors_event_t event; 
  mag.getEvent(&event);

  float heading = atan2(event.magnetic.y, event.magnetic.x);  
  
  int headingDegrees = (heading * 180/M_PI); 

//heading = abs(heading);

if (headingInitial==0)
{
headingInitial =headingDegrees;
}
  
int offset =   headingInitial - headingDegrees;


  myservo1.write(servoPos1 - offset);
  /*Serial.print("Heading (Initial): "); Serial.println(headingInitial);
  Serial.print("headingDegrees: "); Serial.println(headingDegrees);
  Serial.print("offset "); Serial.println(offset);
  Serial.print("Servo pos "); Serial.println(servoPos - offset);*/
  Serial.println(offset);
  myservo1.write(offset);
  delay(500);

/*Fin Section du HMC5883l*/

  for ( byte f = 1; f <= 4; f++)
  { 
    if ((digitalRead(REED[f]) == LOW) && ( flag_tempo[f] == false)) //lecture des BP chacun à son tour
    {
      flag_tempo[f] = true;
      deb_tempo[f] = millis();
     
    }
    MINUTES(1);//1 pour relais 1
    
    
  }
}

void MINUTES(byte relais)
{
  for (byte m = 1; m <= 4; m++)
  {
    if (flag_tempo[m] == true)
    {
      if ((millis() - deb_tempo[m]) < tempo[m])
      {
        digitalWrite(Relais[relais], HIGH);
        digitalWrite(LED[m] , HIGH); //allume la led correspondant à la tempo
      }
      else
      { 
        flag_tempo[m] = false;
        digitalWrite(Relais[relais], LOW);
        digitalWrite(LED[m] , LOW); //allume la led correspondante
        myservo2.write(180);
        delay(1000);
        //myservo2.write(0);
        //delay(1000);
        myservo2.write(90);
      }
    }
  }
}
void extinction_leds()
{
  //Serial.print(" extinction led ");
  for ( byte f = 1; f <= 4; f++)
  {
    if (flag_tempo[f] == false)
    {
      digitalWrite(LED[f], LOW);                      //eteinds les leds
    }
  }
}

void test_leds()
{
  for ( byte f = 1; f <= 4; f++)
  {   digitalWrite(LED[f] , HIGH);//allume les 4 leds
  }
  delay(500);
  for ( byte f = 1; f <= 4; f++)
  {    digitalWrite(LED[f] , LOW);//eteinds les 4 leds
  }
}

Je ne sais pas est ce que je suis claire ou pas mais si vous avez des question n'hesitez pas svp
Par avance merci

Si j'ai bien compris

  • Votre servo (disons la variable angleServo) initialement est à 90° (au centre) et cela doit correspondre à la valeur initiale donné par la boussole qui peut être n'importe quoi entre 0° et 360° (disons la variable directionInitiale)

  • Vous souhaitez que si en cours de route la direction donnée par la boussole change (disons la variable directionActuelle) alors vous modifiez la variable angleServo pour compenser et vous remettre sur le bon cap.

  • je suppose que vous avez bien conscience que cela ne vous emmène plus vers le même point d'arrivée. Si on suppose que en t=20 on détecte que le véhicule a dévié et qu'on corrige le cap, on arrivera à un autre endroit.

est-ce bien cela le but ?

Bonjour @J-M-L ,
Merci infiniment pour votre retour.
Vous avez bien compris ma demande, c'est exactement ce que je veux.
Sinon si le kontiki devie ce ne serai pas un grand probleme. puisqu'il gardera le meme sens c-a-d qu'il ne va pas aller lateralement ou carrement a la droite ou a gauche si c'est une deviation de 5 degré voir meme 10 c'est pas grave (en tout cas il sera devier par le courant de la mer forcement).

Bonsoir les amis,
Pas de nouvelles ?
Merci

Je suppose que la boussole est fixée dans l'axe longitudinal du kontiki. vous pouvez pointer vers la bonne direction mais dériver à cause du courant, la boussole ne servira pas à compenser cette dérive

Pour les maths, quand vous faites

  float heading = atan2(event.magnetic.y, event.magnetic.x);  
  int headingDegrees = (heading * 180/M_PI); 

atan2() donne une valeur dans l'intervalle [-PI,+PI] radians donc le domaine de variation de headingDegrees sera [-180°, 180°]. 0° étant le nord, 90° l'Est, -90° l'Ouest et le sud est aux 2 extrémités

Si vous voulez ramener cela sur [0°, 360°] plus classique Il faut une petite fonction (si l'angle est positif, on ne change rien, s'il est négatif on ajoute 360) donc

  float heading = atan2(event.magnetic.y, event.magnetic.x);  
  int headingDegrees = (heading * 180/M_PI); // [-180°, 180°]
  if (headingDegrees < 0) headingDegrees += 360;  // [0°, 360°] avec 0° pour le Nord, 90° l'est, 180° le Sud, 270° l'Ouest

et si vous faites des opérations ensuite sur ce heading, faites le toujours modulo 360°

Bonjour @J-M-L ,
Merci pour les explications.
Mais mon probléme ce n'est pas a ce niveau, si par exemple je me positionne sur 20° et que le kontiki sera devié par les vagues vers l'autre (vers le sens de 0°) et moi je calcule la difference entre la position initiale et la nouvelle donc le moteur va agir vers le sens contraire.


Si par exemple mon kontiki est le trait rouge sur 20 et il passe a 10 de l'autre sens (normalement -10) et ma formule donne:

  int offset =   headingInitial - headingDegrees;
  myservo1.write(servoPos1 - offset);

la si il part de 20 a 15 (gab de 5°) offset sera 20 - 10 = 10°
donc myservo1.write = 90 - 10 = 80°
Mais si il par vers 10 ( -10 inferieur a 0) on aura 20 - 10 = 10° et myservo1.write = 90 - 10 = 80°
Donc il reprendra la position initiale alors que le kontiki est completement dévié.

C'est exactement ca que je n'arrive pas a regler (et ce probleme je l'ai sur les deux coté 360 et 0)
Merci

Est ce qu'il y a un moyen a chauqe fois que le systeme demarre on lance une calibration de la hmc5883l et la mettre sur 90°. avec ca je n'aurai pas de probléme mais je ne suis pas sur que ca existe (code qui va permettre de calibrer la HMC5883l) ?

Le hmc5883l indique les 3 composantes projetées de la boussole par rapport au Nord . Vous travaillez dans le plan horizontal donc ne conservez que x et y pour calculer donc l'angle instantané par rapport au nord.

Je ne comprends pas trop votre dessin, pourquoi y a-t-il deux fois une échelle de 360° ? vouliez vous dire plutôt +180° et -180°

Avec la petite modification suggérée sur headingDegrees pour se ramener à [0°, 360°] vous aurez l'angle Initial A0 mesuré dans le setup et correspondant à 90° du servo et en cours de route vous mesurez Ac (angle courant).

Si vous vous contentez de regarder (Ac - A0), le modulo 360° va vous jouer des tours. Soit on résout cela en regardant dans quel sens tourner (droite ou gauche):
il faut regarder la position de Ac par rapport au secteur (A0+180°) en tenant compte que l'on peut dépasser 360° ➜ je vous laisse chercher un peu

Soit si on veut faire un peu de force brute, on peut dire que l'angle absolu à considérer est le minimum de
(|Ac - A0|) de (|360°- Ac + A0|) et de (|360°- A0 + Ac|)

voici quelques exemples en mettant la formule dans un tableur

Comme on travaille en valeur absolue, vous ne couperez pas à résoudre la question de savoir si cet angle obtenu de dérive est à appliquer à gauche ou à droite.
➜ je vous laisse chercher comment j'ai obtenu la dernière colonne qui dit si Ac est à droite ou à gauche de A0 (donc faudra bouger dans l'autre sens)

vous allez obtenir donc un angle de ±180° et s'il faut aller à droite ou à gauche, il faut traduire cela ensuite (simple application de map()) en angle du servo et mettre 0 pour -180° et 180 pour +180

Bonjour @J-M-L ,

Ca fait 3h que je bagare avec mais ca me depaase.

je le regle d'un bout et je perts l'autre bout.

static int headingInitial;

void loop()
{
  extinction_leds();
  
  /*Section du HMC5883l*/

  sensors_event_t event; 
  mag.getEvent(&event);

  float heading = atan2(event.magnetic.y, event.magnetic.x);  
  int headingDegrees = (heading * 180/M_PI); // [-180°, 180°]
  if (headingDegrees < 0) headingDegrees += 360;  // [0°, 360°] avec 0° pour le Nord, 90° l'est, 180° le Sud, 270° l'Ouest 

  if (headingInitial==0){headingInitial =headingDegrees;}
 
  //float offset =   headingInitial - headingDegrees;

  //droite
  if (headingDegrees < headingInitial) {
    myservo1.write(servoPos - abs(360 - headingDegrees + headingInitial));}
  //gauche
  if (headingDegrees > headingInitial) {
    myservo1.write(servoPos - abs(360 - headingInitial + headingDegrees));}

  Serial.print("Gauch : "); Serial.println(abs(360 - headingDegrees + headingInitial));
  Serial.print("Droite : "); Serial.println(abs(360 - headingInitial + headingDegrees));
  Serial.print("HeadingInital : "); Serial.println(headingInitial);
  Serial.print("Heading : "); Serial.println(headingDegrees);
  delay(500);
  //myservo1.write(servoPos - offset);

/*Fin Section du HMC5883l*/

je n'arrive pas appliqué vos explications en language arduino :face_with_hand_over_mouth:.

essayez de faire tourner ce code:

// retoure un entier signé qui donne l'écart entre les 2 angles, le signe indiquant si on  tourne dans le sens trigonomètrique (+) ou inverse (-)
int16_t angleCorrection(int16_t angleInitial, int16_t angleCourant) {   // angles dans l'intervalle[0°, 360°]
  int16_t delta1 = abs(angleCourant - angleInitial);
  int16_t delta2 = abs(360u - angleCourant + angleInitial);
  int16_t delta3 = abs(360u - angleInitial + angleCourant);
  int16_t minDelta12 = min(delta1, delta2);
  int16_t angleRetenu = min(minDelta12, delta3);
  if (((angleInitial + angleRetenu) % 360) != angleCourant) angleRetenu *= -1;
  return angleRetenu;
}

void setup() {
  int16_t test[][2] = {{30, 40}, {30, 90}, {30, 10}, {30, 350}, {30, 209}, {30, 210}, {30, 211}, {350, 355}, {350, 10}, {350, 330}, {350, 170}};
  size_t nbTests = sizeof test / sizeof test[0];

  Serial.begin(115200); Serial.println();
  for (size_t i = 0; i < nbTests; i++) {
    int16_t delta = angleCorrection(test[i][0], test[i][1]);
    Serial.print(F("Initial : ")); Serial.print(test[i][0]);
    Serial.print(F("\tCourant : ")); Serial.print(test[i][1]);
    Serial.print(F("\t Delta : ")); Serial.print(abs(delta));
    Serial.println(delta >= 0 ? F("° à Tribord") : F("° à Babord"));
  }
}

void loop() {}

Le moniteur série à 115200 bauds devrait afficher

Initial : 30	Courant : 40	 Delta : 10° à Tribord
Initial : 30	Courant : 90	 Delta : 60° à Tribord
Initial : 30	Courant : 10	 Delta : 20° à Babord
Initial : 30	Courant : 350	 Delta : 40° à Babord
Initial : 30	Courant : 209	 Delta : 179° à Tribord
Initial : 30	Courant : 210	 Delta : 180° à Tribord
Initial : 30	Courant : 211	 Delta : 179° à Babord
Initial : 350	Courant : 355	 Delta : 5° à Tribord
Initial : 350	Courant : 10	 Delta : 20° à Tribord
Initial : 350	Courant : 330	 Delta : 20° à Babord
Initial : 350	Courant : 170	 Delta : 180° à Tribord

une fois que vous aurez compris, le plus simple reste d'écrire:

int16_t angleCorrection( int16_t angleInitial, int16_t angleCourant )
{
  int16_t diff = ( angleCourant - angleInitial + 180 ) % 360 - 180;
  return diff < -180 ? diff + 360 : diff;
}

c'est un peu plus matheux mais ça marche pareil (et même mieux car vos angles peuvent être en dehors de l'intervalle [0°, 360°], le modulo dans la différence se charge de gérer cela)

C'est vraiment trés difficile pour moi de comprendre le code.
Je n'arrive pas a suivre, voila ce que j'ai fait:

NB: j'ai eu le meme message que vous sur le moniteur mais dés que j'ajoute la 2eme partie ca fonctionne pas.

#include <Servo.h>
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>

/* Assign a unique ID to this sensor at the same time */
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);
Servo myservo1;
Servo myservo2;

int servoPos = 90;
int servoPos1 = 90;

int memo_cap_degres;

int MaxLimit = 180;
int MinLimit = 0;

int compassCorrection = 0; // set to 0 (not used)

//on suppose que les BP actionnés ammenent GND sur leur entrée
byte LED[] = {0, 2, 3, 4,  5}; // les LEDS sont sur 3, 4, 5, 6
byte REED[] = {0, 7, 8, 10, 13}; // les BP sont sur 7, 8, 9, 10
int Relais[] = {0, 12};// les Relais sont sur 11,12 case 0 non utilisée
unsigned long deb_tempo[]={0,0,0,0,0};
unsigned long tempo [] = {0000, 5000, 10000, 20000, 30000};//tableau des temps désirés
boolean  flag_tempo[] = {false, false, false, false, false, false};

/*HMC5883L*/

// retoure un entier signé qui donne l'écart entre les 2 angles, le signe indiquant si on  tourne dans le sens trigonomètrique (+) ou inverse (-)
int16_t angleCorrection(int16_t angleInitial, int16_t angleCourant) {   // angles dans l'intervalle[0°, 360°]
  int16_t delta1 = abs(angleCourant - angleInitial);
  int16_t delta2 = abs(360u - angleCourant + angleInitial);
  int16_t delta3 = abs(360u - angleInitial + angleCourant);
  int16_t minDelta12 = min(delta1, delta2);
  int16_t angleRetenu = min(minDelta12, delta3);
  if (((angleInitial + angleRetenu) % 360) != angleCourant) angleRetenu *= -1;
  return angleRetenu;
}
/*FIN HMC5883L*/

void setup() 
{
/* J_M_L */

   int16_t test[][2] = {{30, 40}, {30, 90}, {30, 10}, {30, 350}, {30, 209}, {30, 210}, {30, 211}, {350, 355}, {350, 10}, {350, 330}, {350, 170}};
  size_t nbTests = sizeof test / sizeof test[0];

  Serial.begin(115200); Serial.println();
  for (size_t i = 0; i < nbTests; i++) {
    int16_t delta = angleCorrection(test[i][0], test[i][1]);
    Serial.print(F("Initial : ")); Serial.print(test[i][0]);
    Serial.print(F("\tCourant : ")); Serial.print(test[i][1]);
    Serial.print(F("\t Delta : ")); Serial.print(abs(delta));
    Serial.println(delta >= 0 ? F("° à Tribord") : F("° à Babord"));
  }
  
/* FIN J_M_L */

  Serial.begin(9600);
  for ( byte f = 1; f <= 4; f++)
  {
    pinMode(REED[f],     INPUT_PULLUP);
    pinMode(LED[f],      OUTPUT); digitalWrite(LED[f], LOW);
  }
  pinMode(Relais[1], OUTPUT); digitalWrite(Relais[1], LOW);
  pinMode(Relais[2], OUTPUT); digitalWrite(Relais[2], LOW);
  test_leds();

    if(!mag.begin())
  {
    /* There was a problem detecting the HMC5883 ... check your connections */
    Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
    while(1);
  }
    /* Display some basic information on this sensor */
  displaySensorDetails();
  myservo1.write(90);
  myservo2.write(90);
  delay(2000);

}
void displaySensorDetails(void)
{
  sensor_t sensor;
  mag.getSensor(&sensor);
  myservo1.attach(6);
  myservo2.attach(11);
  delay(500);
}

static int headingInitial;

void loop()
{
  extinction_leds();
  
  /*Section du HMC5883l*/

  sensors_event_t event; 
  mag.getEvent(&event);

//  float heading = atan2(event.magnetic.y, event.magnetic.x);  
//  int headingDegrees = (heading * 180/M_PI); // [-180°, 180°]
//  if (headingDegrees < 0) headingDegrees += 360;  // [0°, 360°] avec 0° pour le Nord, 90° l'est, 180° le Sud, 270° l'Ouest 
//
//  if (headingInitial==0){headingInitial =headingDegrees;}
// 
//  //float offset =   headingInitial - headingDegrees;
//
//  //droite
//  if (headingDegrees < headingInitial) {
//    myservo1.write(servoPos - abs(360 - headingDegrees + headingInitial));}
//  //gauche
//  if (headingDegrees > headingInitial) {
//    myservo1.write(servoPos - abs(360 - headingInitial + headingDegrees));}

  int16_t angleCorrection( int16_t angleInitial, int16_t angleCourant )
{
  int16_t diff = ( angleCourant - angleInitial + 180 ) % 360 - 180;
  return diff < -180 ? diff + 360 : diff;
}

//  Serial.print("Gauch : "); Serial.println(abs(360 - headingDegrees + headingInitial));
//  Serial.print("Droite : "); Serial.println(abs(360 - headingInitial + headingDegrees));
//  Serial.print("HeadingInital : "); Serial.println(headingInitial);
//  Serial.print("Heading : "); Serial.println(headingDegrees);
//  delay(500);
//myservo1.write(servoPos - offset);

/*Fin Section du HMC5883l*/

  for ( byte f = 1; f <= 4; f++)
  { 
    if ((digitalRead(REED[f]) == LOW) && ( flag_tempo[f] == false)) //lecture des BP chacun à son tour
    {
      flag_tempo[f] = true;
      deb_tempo[f] = millis();
     
    }
    MINUTES(1);//1 pour relais 1
    
    
  }
}

void MINUTES(byte relais)
{
  for (byte m = 1; m <= 4; m++)
  {
    if (flag_tempo[m] == true)
    {
      if ((millis() - deb_tempo[m]) < tempo[m])
      {
        digitalWrite(Relais[relais], HIGH);
        digitalWrite(LED[m] , HIGH); //allume la led correspondant à la tempo
      }
      else
      { 
        flag_tempo[m] = false;
        digitalWrite(Relais[relais], LOW);
        digitalWrite(LED[m] , LOW); //allume la led correspondante
        myservo2.write(180);
        delay(1000);
        //myservo2.write(0);
        //delay(1000);
        myservo2.write(90);
      }
    }
  }
}
void extinction_leds()
{
  //Serial.print(" extinction led ");
  for ( byte f = 1; f <= 4; f++)
  {
    if (flag_tempo[f] == false)
    {
      digitalWrite(LED[f], LOW);                      //eteinds les leds
    }
  }
}

void test_leds()
{
  for ( byte f = 1; f <= 4; f++)
  {   digitalWrite(LED[f] , HIGH);//allume les 4 leds
  }
  delay(500);
  for ( byte f = 1; f <= 4; f++)
  {    digitalWrite(LED[f] , LOW);//eteinds les 4 leds
  }
}


et voila l'erreur que j'ai:

Arduino : 1.8.13 (Windows 10), Carte : "Arduino Uno"





















C:\Users\Asus\Documents\Arduino\TEST_J_M_L_1\TEST_J_M_L_1.ino: In function 'void setup()':

TEST_J_M_L_1:60:1: error: a function-definition is not allowed here before '{' token

 {

 ^

exit status 1

a function-definition is not allowed here before '{' token



Ce rapport pourrait être plus détaillé avec
l'option "Afficher les résultats détaillés de la compilation"
activée dans Fichier -> Préférences.

Merci

je vous donne du code de test pour comprendre la fonction, vous n'avez pas à intégrer tout cela dans votre code...

la seule chose dont vous ayez besoin c'est la fonction

int16_t angleCorrection( int16_t angleInitial, int16_t angleCourant )
{
  int16_t diff = ( angleCourant - angleInitial + 180 ) % 360 - 180;
  return diff < -180 ? diff + 360 : diff;
}

elle vous retourne un angle signé qui est le plus petit angle pour aller de angleInitial à angleCourant


commencez par tester cela:

#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);

sensors_event_t mesureBoussoleDebut;
int16_t angleDebut;

int16_t calculeAngle(int16_t a, int16_t b )
{
  int16_t d = (a - b + 180) % 360 - 180;
  return d < -180 ? d + 360 : d;
}

void setup() {
  sensor_t sensor;

  Serial.begin(115200); Serial.println();
  if (!mag.begin()) {
    Serial.println(F("Erreur, HMC5883 absent!"));
    while (true) yield();
  }
  mag.getSensor(&sensor);

  mag.getEvent(&mesureBoussoleDebut);
  angleDebut = atan2(mesureBoussoleDebut.magnetic.y, mesureBoussoleDebut.magnetic.x) * 180.0 / M_PI;
  if (angleDebut < 0) angleDebut += 360;  // [0°, 360°] avec 0° pour le Nord, 90° l'est, 180° le Sud, 270° l'Ouest
}


void loop() {
  sensors_event_t mesureBoussoleEnRoute;
  mag.getEvent(&mesureBoussoleEnRoute);
  int16_t angleEnRoute = atan2(mesureBoussoleEnRoute.magnetic.y, mesureBoussoleEnRoute.magnetic.x) * 180.0 / M_PI;
  if (angleEnRoute < 0) angleEnRoute += 360;  // [0°, 360°] avec 0° pour le Nord, 90° l'est, 180° le Sud, 270° l'Ouest

  int16_t delta = calculeAngle(angleDebut, angleEnRoute);
  Serial.print(F("Initial : ")); Serial.print(angleDebut);
  Serial.print(F("\tCourant : ")); Serial.print(angleEnRoute);
  Serial.print(F("\t Delta : ")); Serial.print(abs(delta));
  Serial.println(delta >= 0 ? F("° à Tribord") : F("° à Babord"));
  delay(100);
}

avec votre kontiki attaché au port série, console ouverte à 115200 bauds.

au moment du boot on lit la direction, ensuite ~10 fois par seconde vous aurez l'angle par rapport à cette direction initiale qui sera affiché --> orientez (à plat) le kontiki vers bâbord ou tribord et vous devriez avoir l'info qui s'affiche

code tapé ici sans avoir testé.

Une fois que cela fonctionnera on se souciera d'ajouter les servo, les LEDs etc...

Bonjour @J-M-L et merci infiniment pour votre précieuse aide :slight_smile:

Le code fonctionne, seuelement que je ne comprends pas pour quoi a droite est un peut lent au niveau de la reaction du moteur mais sa fonctionne bien de l'autre coté.

En tout cas je suis entrain de faire des tests toujours pour etre sur que c'est bon mais a présent tout va bien merci encore une fois.

Dés que je termine les tests je vous dirai la suite.

vos moteurs créent peut être des perturbations électromagnétiques qui influencent la boussole ?

J'ai déja réfléchis a ca mais même que les servo sont loin j'ai le méme souci mais je croie jusqu'a présent ca ne pose pas un grand probleme.

j'ai eu un doute sur le calcule que vous avez fait pour le DELTA mais bon.

je vous tiendrai aucourant si vraiment ca necessite le resoudre.
Encore une fois merci beaucoup.

c'est possible, je n'ai pas le montage donc je n'ai pas pu tester.

le plus simple pour tester c'est de poser votre capteur sur un rapporteur, le faire pointer vers 90° par exemple et faire tourner (à plat) le capteur vers la gauche ou la droite. Si le chiffre affiché est complètement faux, c'est qu'il y a un souci.

Oui c'est une bonne idée