mardi 29 août 2023

Magnétomètre/boussole HMC5883L et Raspberry Pi Pico (Micropython)

Dans cet article, nous utilisons un module HMC5883L relié à un Raspberry Pi Pico programmé en Micropython, afin de fabriquer une boussole électronique.


Le circuit intégré HMC5883L de la compagnie Honeywell permet de mesurer les 3 composantes (x, y, z) du champ magnétique dans lequel il se trouve. Il existe sur le marché plusieurs module ("breakout") faciles à connecter à un microcontrôleur. Celui que j'ai utilisé comporte 5 connecteurs identifiés VCC, GND, SCL, SDA et DRDY.


Installation du pilote micropython-rp2040-hmc5883l

Il existe quelques sur github quelques pilotes destinés à l'utilisation d'un module HMC5883L, qui semblent tous à peu près identiques. J'ai choisi micropython-rp2040-hmc5883l par SindormirNet. Il faut copier le fichier hmc5883l.py dans la mémoire du Raspberry Pi Pico.


Connexions

J'ai branché le module HMC5883L au Raspberry Pi Pico de cette façon:

  • Broche VCC du module HMC5883L: sortie 3,3 V du Raspberry Pi Pico
  • Broche GND du module HCM5883L: une des broches GND du Raspberry Pi Pico
  • Broche SCL du module HMC5883L: broche GP1 du Raspberry Pi Pico
  • Broche SDA du module HMC5883L: broche GP0 du Raspberry Pi Pico
  • Broche DRDY du module HMC5883L: pas branché


Script #1 (affichage dans la console)

La bibliothèque hmc5883l.py comporte une méthode "heading" qui calcule l'angle de l'axe x du capteur par rapport au nord...dans l'hypothèse extrêmement optimiste que le capteur ne nécessitera pas de calibration.

Dans les faits, le capteur qui mesure la composante dans la direction x n'aura probablement pas la même sensibilité que celui qui mesure la composante dans la direction y, et un champ magnétique nul ne produira pas nécessairement une mesure nulle.

Le script ci-dessous comporte donc une routine qui sert à calibrer les capteurs: on demande à l'utilisateur de faire tourner le module HMC5883L dans un plan horizontal sur au moins un tour complet. Pendant cette rotation, le script garde en mémoire la valeur maximale et la valeur minimale mesurées par le capteur x et par le capteur y. Les mesures brutes sont ensuite recalculées de façon à atténuer les imperfections des capteurs.

Pour que la direction soit affichée en fonction du nord géographique et non en fonction du nord magnétique, il faut que vous écriviez dans le script la valeur de la déclinaison magnétique là où vous êtes (variable "declinaison", à la ligne 18).

-

'''
Module magnétomètre - Boussole HMC5883L relié à un Raspberry Pi Pico
L'angle par rapport au nord est affiché dans la console.
Plus d'infos:
https://electroniqueamateur.blogspot.com/2023/08/magnetometreboussole-hmc5883l-et.html
'''
from hmc5883l import HMC5883L # https://github.com/SindormirNet/micropython-rp2040-hmc5883l/tree/master
import time
import math
boussole = HMC5883L()
# déclinaison magnétique en degrés là où vous êtes
# https://www.magnetic-declination.com/
declinaison = -12.8
# routine de calibration:
print ("Calibration")
print ("Tournez la boussole sur un tour complet dans un plan horizontal")
debut = time.time()
x, y, z = boussole.read()
xmin = x
xmax = x
ymin = y
ymax = y
while (time.time() - debut) < 8: # pendant 8 secondes
x, y, z = boussole.read()
if x < xmin:
xmin = x
if x > xmax:
xmax = x
if y < ymin:
ymin = y
if y > ymax:
ymax = y
# bilan de la calibration:
print('xmin: ' , xmin, ' xmax: ', xmax)
print('ymin: ' , ymin, ' ymax: ', ymax)
# petite pause pour laisser le temps de lire le résultat
time.sleep_ms(2000)
while True:
x, y, z = boussole.read()
# transformation des données brutes
xcal = (x-(xmax+xmin)/2)*(200)/(xmax-xmin)
ycal = (y-(ymax+ymin)/2)*(200)/(ymax-ymin)
# calcul de l'angle entre x et le nord
if xcal != 0:
angle = round(math.atan(ycal/xcal)*180/math.pi + declinaison,0)
print(angle, '°')
time.sleep_ms(200)

-

Boussole autonome

J'ai ensuite ajouté un écran OLED à mon circuit, de façon à obtenir une boussole parfaitement autonome qui ne dépend pas d'un ordinateur pour afficher ses mesures.

Il s'agit d'un écran OLED spi de 128 par 64 pixels.


J'ai branché l'écran OLED au Raspberry Pi Pico de cette façon:

  • Broche GND de l'écran: broche GND du Raspberry Pi Pico
  • Broche VCC de l'écran: sortie 3,3 V du Raspberry Pi Pico
  • Broche DO de l'écran: broche GP6 du Raspberry Pi Pico
  • Broche DI de l'écran: broche GP7 du Raspberry Pi Pico
  • Broche RES de l'écran: broche GP14 du Raspberry Pi Pico
  • Broche DC de l'écran: broche GP15 du Raspberry Pi Pico
  • Broche CS de l'écran: broche GP5 du Raspberry Pi Pico

Script #2 (boussole autonome)

Ce script affiche à l'écran OLED un plan cartésien (qui doit être aligné avec celui qui est imprimé sur le module HMC5883L), et une "aiguille de boussole" qui pointe obstinément vers le nord. Encore une fois, pour qu'elle pointe vers le nord géographique, vous devez modifier la valeur de la variable "declinaison" à la ligne 24, pour qu'elle reflète la valeur de la déclinaison magnétique là où vous êtes.


-

'''
Magnétomètre - Boussole HMCV5883L relié à un Raspberry Pi Pico
Une boussole indiquant le nord est dessinée sur
un écran OLED SPI.
'''
from hmc5883l import HMC5883L
import time
import math
from ssd1306 import SSD1306_SPI
from machine import Pin, SPI
boussole = HMC5883L()
#initialisation spi pour l'écran OLED
spi = SPI(0, baudrate=20000000, polarity=0, phase=0, sck=Pin(6), mosi=Pin(7), miso=Pin(4))
# initialisation oled
oled = SSD1306_SPI(128, 64, spi, Pin(15), Pin(14), Pin(5))
# déclinaison magnétique en degrés là où vous êtes
# https://www.magnetic-declination.com/
declinaison = -12.8
# routine de calibration
oled.text("Calibration",5,5)
oled.text("Tournez",5,20)
oled.text("la boussole",5,35)
oled.show()
debut = time.time()
x, y, z = boussole.read()
xmin = x
xmax = x
ymin = y
ymax = y
while (time.time() - debut) < 8: # pendant 8 secondes
x, y, z = boussole.read()
if x < xmin:
xmin = x
if x > xmax:
xmax = x
if y < ymin:
ymin = y
if y > ymax:
ymax = y
while True:
x, y, z = boussole.read()
# transformation des données brutes
xcal = (x-(xmax+xmin)/2)*(200)/(xmax-xmin)
ycal = (y-(ymax+ymin)/2)*(200)/(ymax-ymin)
# calcul de l'angle entre x et le nord (en radians)
if xcal != 0:
angle = math.atan(ycal/xcal) + declinaison * math.pi/180
if xcal < 0:
if ycal >= 0:
angle = angle + math.pi
else:
angle = angle - math.pi
# On remplit l'écran de noir (pour effacer)
oled.fill(0)
# tracé du repère cartésien
oled.line(34, 32, 90, 32, 1)
oled.line(64, 5, 64, 60, 1)
oled.text('x',92,28,1)
oled.text('y',60,0,1)
# tracé de l'aiguille de la boussole
oled.line(64,32,64+int(25*math.cos(angle)),32-int(25*math.sin(angle)),1)
oled.show()
time.sleep_ms(200)

-


À lire également:


Yves Pelletier


1 commentaire: