Interfacer les capteurs MLX90393 avec un Yocto-I2C

Interfacer les capteurs MLX90393 avec un Yocto-I2C

Un client nous a récemment demandé de l'aide pour interfacer un capteur de champ magnétique Melexis MLX90393 avec un Yocto-I2C. On s'est dit que, quitte à devoir faire le travail d'intégration, autant en faire profiter tout le monde.





Le MLX90393 est donc un magnétomètre 3D capable de mesurer un champ magnétique dans trois directions orthogonales X,Y,Z, le plan du capteur étant aligné avec X et Y. Il peut aussi mesurer la température. Il se présente sous la forme d'un petit composant QFN de 3x3mm, on peut le trouver déjà soudé sur une carte d'évaluation auprès de différents fabricants comme Adafuit, Sparkfun ou encore directement Melexis.

Le MLX90393 est disponible sous forme de carte d'évaluation auprès de différents fabricants
Le MLX90393 est disponible sous forme de carte d'évaluation auprès de différents fabricants


Elles fonctionnent toutes selon le même principe bien que leur adresse I2C par défaut puisse éventuellement différer. On a choisi celle d'Adafruit parce que c'est celle qu'utilise notre client.

Connexions

La carte d'Adafruit peut être alimentée en 3.3V, le MLX90393 supporte facilement des communications à 400Hz. La configuration du Yocto-I2C et les branchements sont donc relativement triviaux.

Configuration du Yocto-I2C
Configuration du Yocto-I2C


Cablâge entre le MLX90393 et le Yocto-I2C
Cablâge entre le MLX90393 et le Yocto-I2C


Considérations à propos du MLX90393

En étudiant attentivement le datasheet du MLX90393, on note quelques points importants.

Adresse I2C

Suivant le modèle utilisé et la façon dont sont câblées les pins 11 et 12, l'adresse I2C du capteur peut prendre 38 valeurs différentes. L'adresse par défaut de la version Adafruit est 0x18, ce qui signifie que les commandes I2C de lecture devront commencer par 2* 0x18 + 1 = 0x31 et que les commandes en écriture devront commencer par 2* 0x18 = 0x30.

Status byte

Après chaque commande, il est recommandé d'envoyer une condition "restart" et d'effectuer une lecture pour récupérer l'octet de statut du MLX90393. Le bit 4 de l'octet de statut est le bit ERROR qui indique s'il y a eu un problème quelque part. Lorsque le bit ERROR est mis à 1, le capteur n'accepte plus aucune commande à part "reset".

Reset

La commande "reset" est 0xF0, le module répond par son octet de statut. La commande complète à envoyer, ressemble donc à, en supposant que l'adresse I2C du MLC90393 soit 0x18:

{S}30F0{R}31xx{N}{P}


Cependant, le datasheet du MLX90393 mentionne qu'il est préférable d'exécuter la commande exit (code 0x80) avant de lancer un reset. Lorsqu'il exécute cette commande exit le capteur répond par son statut. La commande I2C correspondante est donc:

{S}3080{R}31xx{N}{P}


Lancer une mesure

Pour lancer une mesure unique sur les trois magnétomètres ainsi que la sonde de température, il faut utiliser la commande 3F. Ici aussi, la réponse est le statut du capteur, la commande est donc:

{S}303F{R}31xx{N}{P}


Récupérer le résultat d'une mesure

La commande pour récupérer les résultats d'une mesure est 0x4f, la réponse est l'octet de statut, suivi des valeurs de température, champ magnétique Z, Y et Z qui sont encodées sous la forme d'un entier 16 bits signé. La température est un entier 16 bit non signé qui peut être converti en degrés Celsius avec la formule 25+(t-46244)/45.2 Si GAIN_SEL et RES sont à leur valeur par défaut de zéro, on peut convertir les valeurs x,y,z en µT avec les formules x*0.15, y*0.15 et z*0.242 à 25°C. Les variations de température peuvent légèrement affecter les résultats, mais le datasheet ne donne pas de formules formelles pour effectuer la compensation. Quoi qu'il en soit, la commande à envoyer est:

{S}304F{R}31xx{A}xx{A}xx{A}xx{A}xx{A}xx{A}xx{A}xx{A}xx{N}{P}


Implémentation

Pour interfacer le MLX90393 avec un Yocto-I2C, vous pouvez bien sûr envoyer les commandes depuis votre propre code, mais il est plus efficace d'utiliser le système de jobs du Yocto-I2C. On va donc créer un job sous la forme d'une petite machine à états pilotée par la variable $state, chacun des trois états correspond à une tâche. Pour rappel, le Yocto-I2C va en permanence essayer d'exécuter chaque tâche à tour de rôle, et une commande assert qui échoue interrompt la tâche en cours.

Tâche de démarrage

Le but principal de cette tâche est d'initialiser la variable $state. Accessoirement, au vu du nombre d'adresses I2C possibles pour le MLX90393, on va utiliser une variable plutôt que coder la valeur directement dans les commandes et pré-calculer les variables $W et $R qu'on utilisera au début de chaque commande. A la fin de la tâche, on initialise le variable $state à 1.

compute $I2Caddr=0x18 compute $W=$I2Caddr*2 compute $R=$I2Caddr*2+1 compute $state=1


On a besoin de n'exécuter cette tâche qu'une seule fois.

Tâche d'initialisation du capteur

Cette tâche sert à forcer une réinitialisation du capteur. On a fait en sorte qu'elle soit exécutée dès le début du job histoire d'être sûr que l'on démarre d'un bon pied. Cette tâche consiste à:

  • Vérifier que la variable $state est initialisée et que sa valeur vaut 1
  • Envoyer la commande EXIT, comme on utilise les variables $W et $R on emploie writeVar plutôt que writeLine
  • Lire le résultat.
  • Envoyer la commande RESET.
  • Lire le résultat.
  • Vérifier que le bit ERROR du statut est à zéro
  • Attendre un peu
  • Mettre la variable $state à 2

Ce qui correspond à :

assert isset($state) assert $state==1 writeVar {S}($W:BYTE)80{R}($R:BYTE)xx{N}{P} expect (BYTE):{A}{A} (BYTE):{A}($status:BYTE) writeVar {S}($W:BYTE)F0{R}($R:BYTE)xx{N}{P} expect (BYTE):{A}{A} (BYTE):{A}($status:BYTE) assert ($status & 0x10) == 0 wait 200 compute $state = 2


Cette tâche est périodique et exécutée à une fréquence de 10Hz.

Tâche d'interrogation du capteur

C'est cette tâche qui fait le vrai travail:

  • Elle vérifie que la variable $state est initialisée et que sa valeur vaut 2
  • Elle met la variable $state à 1, ainsi, si un assert interrompt la tâche, la tâche d'initialisation du capteur sera relancée.
  • Elle envoie la commande pour déclencher une mesure.
  • Elle lit le statut.
  • Elle vérifie que le bit ERROR de $status est à zéro.
  • Elle envoie la commande pour déclencher la lecture du résultat.
  • Elle lit le résultat et mappe les valeurs lues dans les variables $status,$t,$z,$y,$x.
  • Elle vérifie que le Bit ERROR de $status est à zéro.
  • Elle mappe les genericSensor 1,2,3 et 4 du Yocto-I2C sur les valeurs respectives de $x, $y, $z et $t en appliquant les formules de conversion en µT et °.C
  • Petit bonus, elle calcule l'angle en degrés formé par $x et $y qu'elle mappe sur le genenicSensor5.
  • Enfin, elle remet la variable $state à 2.

Ce qui correspond à:

assert isset($state) assert $state==2 compute $state=1 writeVar {S}($W:BYTE)3F{R}($R:BYTE)xx{N}{P} expect (BYTE):{A}{A} (BYTE):{A}($status:BYTE) assert ($status & 0x10) == 0 writeVar {S}($W:BYTE)4F{R}($R:BYTE)xx{A}xx{A}xx{A}xx{A}xx{A}xx{A}xx{A}xx{A}xx{N}{P} expect (BYTE):{A}{A} (BYTE):{A}($status:BYTE)($t:WORD)($z:SWORD)($y:SWORD)($x:SWORD) assert ($status & 0x10) == 0 compute $1=$x*0.15 compute $2=$y*0.15 compute $3=$z*0.242 compute $4=25+($t-46244)/45.2 compute $5=180*atan2($y,$z)/pi compute $state=2


Cette tâche est périodique et exécutée à une fréquence de 10Hz. C'est tout pour la partie code, vous pouvez télécharger le job complet ici.

Et ça marche?

Oui, ça marche sans problème, par contre, il faut veiller à ne pas utiliser un aimant trop fort et ne pas le placer trop près du capteur, sinon cela va provoquer un overflow et les valeurs mesurées vont wrapper, rendant ainsi le résultat difficile à interpréter. Pour tester notre job, en plus d'utiliser Yocto-Visualization, on a construit un petit gagdet:

Notre banc de test du  MLX90393
Notre banc de test du MLX90393


Il est basé sur un Yocto-I2C, un Yocto-Color-V2 et anneau de LEDs adressables. Un script Python lit l'orientation du champ magnétique induit par un petit aimant caché dans un gros bouton simplement posé sur le dispositif, et allume la LED correspondante avec un petit effet de fondu. Le tout est bizarrement addictif.

Le même, en action
Le même, en action


Conclusion

A priori le MLX90393 marche plutôt bien et grâce au système de jobs du Yocto-I2C, on peut facilement l'exploiter comme si c'était un capteur Yoctopuce classique. On n'a présenté ici que le fonctionnement de base, mais il est possible de changer la plage de sensibilité du capteur en jouant sur les paramètres GAIN_SEL et RES_XYZ du MLX90393. Il est aussi apparemment possible de stocker des données arbitraires dans la mémoire libre du capteur. Cet essai a été l'occasion de découvrir un bug dans la commande WriteVar, veillez à ce que votre Yocto-I2C ait un firmware supérieur ou égal à 61198 avant d'essayer le job décrit dans cet article.

Commenter aucun commentaire Retour au blog












Yoctopuce, get your stuff connected.