Club robotique de Sophia-Antipolis

Accueil > POBOTpedia > Capteurs > Capteurs de position > HMC6343 : une boussole intelligente

HMC6343 : une boussole intelligente

samedi 17 décembre 2011, par Julien H.

Depuis une dizaine d’années, on trouve des boussoles électroniques à bon marché. La puce Honeywell HMC6343 propose désormais une plus grande définition mais surtout améliore la fiabilité aux variations de position grâce à un programme utilisant trois sources d’informations (température, accélération, champ magnétique) pour calculer le cap en corrigeant lui-même les erreurs.

Pourquoi payer 150 euros une puce quand on n’a besoin que d’un cap avec une précision d’un degré et que des puces à 30 euros font ce travail ? Parce que cette puce intègre trois magnétomètres et trois accéléromètres et un capteur de température pour améliorer ce cap, permettant ainsi d’être insensible aux variations entourant le lieu de mesure, principalement des changements d’assiette ou de vitesse du support de cette boussole numérique.

A vous les robots qui se prennent des chocs, qui grimpent des pentes, qui font des virages rapides !

Principes

Pour utiliser une si petite puce comme une boussole, on utilise des capteurs de magnétorésistance anisotrope (ou AMR) : la résistance électrique mesurée change selon l’angle entre le courant électrique qui circule dans la puce et le champ magnétique terrestre. Dans d’autres usages, cet effet sert à détecter le passage d’un objet métallique, à mesurer une position ou un angle.

Si votre robot manque de place, les trois axes disponibles sur cette puce permettent de changer la position pour placer la boussole verticalement, à +/- 90 degrés autour de chaque axe (le reste se faisant par addition ou soustraction).

La lecture de la direction est faite 5 fois par seconde par défaut, mais elle peut se faire 1 ou 10 fois si on le souhaite.

Informations

Quand on remplace une boussole CMPS03 par cette puce, il faut adapter les pattes, mais aussi la tension, puisque la première utilise une tension TTL de 5 volts tandis que la seconde utilise la tension CMOS de 3,3 volts. Ce sont des valeurs proches mais en électronique numérique, il ne faut pas mélanger les tensions !

La CMPS03
La HMC6343

Programmation

Nous allons utiliser deux plateformes de développement : avec Arduino (très simple) et avec seulement un micro-contrôleur AVR (simple mais il faut de la méthode).

boussole pilotée par Arduino

Comme d’habitude, la première étape est de déterminer la bonne adresse I2C pour la bibliothèque Wire, sur 7 bits. La documentation indique 0x32 et 0x33, à cause du dernier bit indiquant le sens (écriture ou lecture), soit 0b00110010 sur 8 bits ce qui donne 0b001 1001 ou 0x19 sur 7 bits.

Voici le code pour Arduino 0022 :


#include <Wire.h>

/**
* Test de la boussole I2C HMC6343
*
* julien@pobot.org - 22 décembre 2012
*/

// l’adresse I2C esclave de la boussole
#define adr_HMC6343 0x19

void setup()

// configurer la liaison série
Serial.begin(115200) ;

// configurer la liaison I2C
Wire.begin() ;

Serial.println("Test HMC6343") ;

void loop()

// choisir le mode souhaité
appelSimple() ;

// attendre selon la fraicheur de mise à jour souhaitée
delay(150) ;

void appelSimple()

// premier appel, demande de la direction
Wire.beginTransmission(adr_HMC6343) ;
Wire.send(0x50) ;
Wire.endTransmission() ;

// il faut attendre 1 milliseconde
delay(2) ;

// second appel, lecture des deux premières valeurs
Wire.requestFrom(adr_HMC6343, 2) ;

// (facultatif) attendre que les deux octets soient disponibles
//while(Wire.available() < 2) ;

// concaténation des deux octets (décalage d’un octet sur la gauche)
Serial.println(Wire.receive()<<8+Wire.receive()) ;

Voici la version pour Arduino 1.0 :


#include <Wire.h>

/**
* Test de la boussole I2C HMC6343
*
* julien@pobot.org - 22 décembre 2012
*/

// l’adresse I2C esclave de la boussole
#define adr_HMC6343 0x19

void setup()

// configurer la liaison série
Serial.begin(115200) ;

// configurer la liaison I2C
Wire.begin() ;

Serial.println("Test HMC6343") ;

void loop()

// choisir le mode souhaité
appelSimple() ;

// attendre selon la fraicheur de mise à jour souhaitée
delay(150) ;

void appelSimple()

// premier appel, demande de la direction
Wire.beginTransmission(adr_HMC6343) ;
Wire.write(0x50) ;
Wire.endTransmission() ;

// il faut attendre 2 millisecondes
delay(2) ;

// second appel, lecture des deux premières valeurs
Wire.requestFrom(adr_HMC6343, 2) ;

// (facultatif) attendre que les deux octets soient disponibles
//while(Wire.available() < 2) ;

// concaténation des deux octets (décalage d’un octet sur la gauche)
Serial.println(Wire.read()<<8+Wire.read()) ;

Ces codes sont fournis tels quels, il faut les adapter à votre contexte.

Programmation en C

Si vous utilisez un micro-contrôleur sans couche d’abstraction telle celle d’Arduino, vous pouvez vous inspirer du code ci-dessous.

Comme vous le voyez, rien de bien compliqué : il faut envoyer 0x50 comme adresse de registre à lire et la boussole renvoie des octets. On lit les deux premiers pour reconstruire l’angle :


unsigned int angle_HMC6343(void)

// variable temporaire pour accumuler les deux octets
unsigned int recup_angle ;

TWCR = 0xA4 ; // démarrage de l’I2C
while(!(TWCR & 0x80)) ; // attendre confirmation
TWDR = 0x32 ; // adresse d’écriture de la boussole
TWCR = 0x84 ; // demander l’envoi
while(!(TWCR & 0x80)) ; // attendre confirmation
TWDR = 0x50 ; // adresse du registre
TWCR = 0x84 ; // demander l’envoi
while(!(TWCR & 0x80)) ; // attendre confirmation

TWCR = 0xA4 ; // on redémarre
while(!(TWCR & 0x80)) ; // attendre confirmation
TWDR = 0x33 ; // adresse de lecture de la boussole
TWCR = 0xC4 ; // annoncer la fin de transmission (on veut recevoir)
while(!(TWCR & 0x80)) ; // attendre confirmation
TWCR = 0x84 ; // message "nack" (dernier octet)
while(!(TWCR & 0x80)) ; // attendre confirmation
recup_angle = TWDR << 8 ; // lire la donnée reçue et stocker dans l’octet de poids fort de la variable

TWCR = 0xA4 ; // on redémarre
while(!(TWCR & 0x80)) ; // attendre confirmation
TWDR = 0x33 ; // adresse de lecture de la boussole
TWCR = 0xC4 ; // annoncer la fin de transmission
while(!(TWCR & 0x80)) ; // attendre confirmation
TWCR = 0x84 ; // message "nack" (dernier octet)
while(!(TWCR & 0x80)) ; // attendre confirmation
recup_angle += TWDR ; // lire la donnée et la stocker dans l’octet de poids faible

TWCR = 0x94 ; // arrêter la communication I2C.

return recup_angle ;

Ce code n’est pas le plus simple (on doit pouvoir gérer une seconde lecture sans renvoyer une demande, en changeant le "nack") mais il fonctionne.

Donner le cap !

Si l’on souhaite utiliser le module comme une boussole classique, en utilisant un cap personnel ou s’aligner avec le nord donné par un autre outil, il est nécessaire de prévoir une valeur de décalage dans le programme.

Mais si vraiment vous pensez que l’environnement du capteur est bruité et qu’il ne reconnaît pas correctement les changements de direction, il est possible de passer dans un mode de calibration des trois axes qui fera une lecture lors d’une rotation complète (360° autour de 2 axes) et en déduira des valeurs de décalage - ou offset - propres à votre environnement.

Forcément, cette dernière manipulation est à faire sur la position finale de la boussole, et n’améliorera pas (plus que ne le fait déjà le circuit interne de la puce) le fonctionnement lorsque votre robot se déplacera vers des masses métalliques.

Un message, un commentaire ?

modération a priori

Attention, votre message n’apparaîtra qu’après avoir été relu et approuvé.

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.