Problème de mesure avec une boussole HMC5883L

Bonjour,

alors voilà, je me décide enfin a poster une demande d'aide car je n'ai pas d'explication à mon problème...

Je précise toutefois que l'arduino, la programmation en c et c++ n'ont pratiquement plus de secret pour moi :wink:

J'essaye de récupérer l'angle d'inclinaison XY via un module HMC5883L mais les valeurs retournées sont incohérentes et complètement décalées des valeurs obtenues avec une App boussole smartphone.
J'ai tout éssayé : calibration, plusieurs type de code mais sans résultats.

un exemple du décalage :

App - HMC5883L


0 258
90 170
180 110
270 69

Avez - vous une idée ou un code exemple fonctionnel svp ?

Merci d'avance pour votre aide :wink:

Est-ce que vous mesurez les bons angles (X ou Y ou Z) ?
Y a-t-il un environnement proche magnétique ?

Cordialement.

Pierre

bonjour Pierre,

merci pour ton aide :wink:

J'ai mon PC portable et smartphone à 30cm...

Je fais dabord une calibration avec le prog HMC5883_Calibrate.ino : Je récupère les 2 dernières valeurs OffX = 133, OffY = -133.

Je modifie ensuite les offsets dans le prog réel HMC5883_Compass.ino :
...
// Set calibration offset. See HMC5883L_calibration.ino
compass.setOffset(133, -133);
...

Je devrais normalement obtenir des valeurs proches de celle d'une vraie boussole même sans calibration non ?

Je ne connais pas ce produit ni les logiciels associés.

Pour autant, je sais qu'on se fait facilement avoir avec des champs perturbateurs.

Il faudrait que vous fassiez votre manip avec des angles bien définis, comme vous le faites, mais en plusieurs endroits. Si les résultats continuent à être erronés, le problème de champ perturbateur sera éliminé.

Cordialement.

Pierre

J'ai déjà placé le module dans mon bateau de modélisme et j'obtenais les même problèmes...
Il y a certainement un truc qui m'échape mais quoi....

ça a l'air pourtant très simple vu les tuto sur le web.

J'y perds mon latin là.

Si le c et c++ n'ont presque plus de secret pour toi, tu lis en direct sans bibliothèque les registres 0x04 0x08 et 0x06, respectivement le x y et z, et tu regardes les valeurs retournées.

mx = float (Core::readTwi (_device, 0x04, 16)) / 1090.0;
my = float (Core::readTwi (_device, 0x08, 16)) / 1090.0;
mz = float (Core::readTwi (_device, 0x06, 16)) / 1090.0;

Pour ma part je divise les valeurs brutes par 1090 pour avoir des valeurs standard en Gauss comme le montre le datasheet:

Ok, pas de soucis pour ça :wink:

Mais que faire comme conversion avec les Gauss pour obtenir les degrés réels, appliquer cette équation :

X et Y étant les valeurs en Gauss :

Direction (y>0) = 90 - [arcTAN(x/y)]*180/Pi
Direction (y<0) = 270 - [arcTAN(x/y)]*180/Pi
Direction (y=0, x<0) = 180.0
Direction (y=0, x>0) = 0.0

voilà, je viens de faire les modifs mais j'ai toujours ce comportement bizarre par rapport à ma boussole App smartphone...

voici le code :

float Angle;
float RawX = float(HMC5803L_Read(X));
float RawY = float(HMC5803L_Read(Y));

if (RawY >0) {
Angle = 270.0 - (atan(RawX/RawY))*180.0/Pi;
}
if (RawY <0) {
Angle = 90.0 - (atan(RawX/RawY))*180.0/Pi;
}
if ((RawY == 0) && (RawX < 0)) {
Angle = 180.0;
}
if ((RawY == 0) && (RawX > 0)) {
Angle = 0.0;
}

Serial.println(Angle);

Voici les datas :

Min X : -463
Max X : 766
Min Y : -612
Max Y : 432
Offset X : 151
Offset Y : -90

Que dois - je faire avec ces données svp ?

Personne pour m'aider ???

Merci pour cette explications :wink:

j'ai regardé la datasheet aujourd'hui avec attention et essayé de récupérer les valeurs X, Y et Z reçues sur 6 Bytes :

X MSB
X LSB
Z MSB
Z LSB
Y MSB
Y LSB

Après remise en forme des bytes dans des variable Int16, je dois normalement obtenir, d'après la datasheet, des valeur variant de f800 à 07ff -> 63488 à 2048. qui doit donner un range de -2048 -> 2048.

Je n'obtiens malheureusement pas ces valeurs...

int16_t HX,HY,HZ;

Wire.requestFrom(HMC5983_ADDRESS, 6);

if(6<=Wire.available()){
HX = Wire.read()<<8; //MSB x
HX |= Wire.read(); //LSB x
HZ = Wire.read()<<8; //MSB z
HZ |= Wire.read(); //LSB z
HY = Wire.read()<<8; //MSB y
HY |= Wire.read(); //LSB y
}

// range is 0xF800 to 0x07FF or -2048 to 2047
if (HX>32767) {
HX -= 65536;
}
if (HZ>32767) {
HZ -= 65536;
}
if (HY>32767) {
HY -= 65536;
}

Je ne vois pas où se situe le problème....

Bonjour,

J'ai eu le même problème avec ce bidule.

La solution que j'ai trouvée est d'ajouter un facteur de correction à la variable X(direction x) ou la variable Y, ou aux deux.

La formule que je dois utilisée est:

float heading = atan2(y+10, x);

Je dois donc ajouter +10 à la variable "y" pour obtenir de bon résultats!!

Évidemment, le facteur de correction doit être différent pour chaque capteur, faut donc le trouver.

Pour ce faire, j'ai trouver (sans correction) les valeurs x et y des quatre points cardinaux, ce qui m'a permis de trouver la correction pour "y".

J'espères que ce conseil pourra t'aider...

As tu une idée des valeurs min et max des axes bruts que tu obtenais ? J ai un doute sur les valeurs que je reçois...?

Bonjour,

Je ne me rappelle pas exactement ce que j'avais mais c'était quelques chose comme:

Nord (360°)... (y,x)=(10,0)

Sud(180°)...(y,x)=(-20,-20)

Donc pour "y" une différence de :(+10 + (-20))=30 points de différence.
pour "x" une différence de :(0 + (-20))=20 points de différence.

Est (90°).......(y,x)=(-15,0)
Ouest(270°)..(y,x)=(+5,-20)

Donc pour "y" une différence de :(-15 + (5))=20 points de différence.
pour "x" une différence de :(0 + (-20))=20 points de différence.

Donc pour l'orientation Est/Ouest les différences sont identiques mais pour l'orientation Nord/Sud il y a une différence de 10 entre "x" et "y".

Il faut donc trouver le facteur de correction pour "x" ou "y" et faire des tests (en + ou en -) pour ces variables pour trouver la bonne orientation boussole.

Dans mon programme j'avais les instructions suivantes:

float heading = atan2(y+10, x);// correction de +10 pour la valeur de "event.magnetic.y" , ici, pour mon capteur.
  //float heading = atan2(y, x);
  
//***********************************************************************************************************************  
  // Lorsque vous avez "heading", il faut corriger avec un facteur de déclinaison pour avoir le pole nord géographique.
  // Trouvez, ici, pour votre location : http://www.magnetic-declination.com/
  // La mienne est d'environ -14.5 degrés, ou  -0.244 radians
   
  float declinationAngle =-0.244;
  heading += declinationAngle;
//***********************************************************************************************************************  
etc.
etc.

J'espère que tu pourras trouver le(s) bon(s) facteur(s) de correction.

Quant c'est fait, ce bidule fonctionne parfaitement.

Au début, c'est vraiment décourageant quand on a pas la correction voulue.

Merci pour cette bonne explication :wink:

voici le données que je reçois, peux - tu me dire comment les convertir suivant ton principe stp ?

0|360 : X(-53) Y(-23)
90 : X(-72) Y(72)
180 : X(15) Y(75)
270 : X(43) Y(-33)

je précise que je fais mes tests sur un gps neo6m ou neo8m Ublox avec Compass intégré hmc5883

après avoir épluché tous les tutos, vidés sur le web, je ne comprends pas les valeurs que je reçois...

Elles n'ont vraiment pas l'air cohérentes... Que faire ???

Boucle de lecture byte :

Wire.requestFrom(HMC5883_ADDRESS, 6);

uint16_t buffer[6];
if (Wire.available()>=6) {
for(uint8_t i=0;i<6;i++)
buffer = Wire.read();

  • X = (buffer[0]<<8) | buffer[1];*
  • Z = (buffer[2]<<8) | buffer[3];*
  • Y = (buffer[4]<<8) | buffer[5];*
  • //X=-X; // Position capteur inversé.*
  • }*
    Voici les bytes brutes que je lis au 4 points cardinaux :
    0 : FF | C6 -- 0 | A5 -- FF | DE => Byte 0, 1, 2, 3, 4, 5
    90 : FF | AC -- 0 | C2 -- 0 | 3A => Byte 0, 1, 2, 3, 4, 5
    180 : 0 | 14 -- 0 | AA -- 0 | 41 => Byte 0, 1, 2, 3, 4, 5
    270 : 0 | 27 -- 0 | 8D -- FF | E3 => Byte 0, 1, 2, 3, 4, 5
    D'apès le datasheet, le range est de -2048 à 2047. (0xF800–0x07FF)
    J'espère avoir donner beaucoup plus de détails....

Ok, c est rassurant... Mais comment procéder pour étalonner les valeurs svp ?

Récupérer les min et max de chaque axe pas de soucis, mais apres, que faire avec ces données et quelle formule utiliser pour obtenir les coordonnées angulaires parfaitement alignees avec une boussole ?