Arduino: misuriamo il campo magnetico terrestre con il magnetometro HMC5883L

Il magnetometro HMC5883L

HMC5883L compass main

Questo componente (un piccolo chip) HMC5883L prodotto dalla Honeywell, basa il suo funzionamento sulla tecnologia AMR (Anisotropic Magnetoresistive) e ci permette di poter misurare sia la direzione che l’ampiezza del campo magnetico terrestre. Questo magnetometro HMC5883L ha al suo interno 3 sensori magneto-resistivi disposti su 3 assi perpendicolari (assi cartesiani x,y e z). Qui potete trovare il datasheet del componente.

HMC5883L_chip

Fig.1: Il chip HMC5883L della Honeywell

Il campo magnetico ha effetto su questi sensori modificando in qualche modo la corrente che li attraversa. Applicando una scala a questa corrente, possiamo conoscere la forza magnetica (espressa in Gauss) esercitata su ciascun sensore.

Il componente HMC5883L comunica con Arduino attraverso il protocollo I2C, un protocollo molto semplice da usare.

Per il nostro esempio con Arduino io ho acquistato la breakout board del HMC5883L distribuita dalla Sparkfun in cui è visibile al centro il chip integrato.

Sparkfun-HMC5883L

Triple Axis Magnetometer Breakout – HMC5883L

Sul mercato sono disponibili moltissime altre breakout board su cui è integrato questo chip, alcune davvero molto economiche.

MPU6050 HMC5883L BMP180 GY 87 ACC bussola barom. Arduino Raspberry Pi

HMC5883L BMP180 GY 87 ACC

SODIAL Modulo L3G4200D ADXL345 HMC5883L BMP085

SODIAL (R) Modulo L3G4200D ADXL345 HMC5883L BMP085

Lo schema elettrico

  • Arduino GND -> HMC5883L GND
  • Arduino 3.3V -> HMC5883L Vcc
  • Arduino A4(SDA) -> HMC5883L SDA
  • Arduino A5(SCL) -> HMC5883L SCL

HMC5883L Fritzing

La libreria HMC5884L per Arduino

In internet è possibile trovare numerose librerie programmate specificamente per l’utilizzo di questo sensore. Per gli esempi trattati in questo articolo ho scelto di utilizzare una libreria prelevata dalla LoveElectronic un po’ di tempo fa (anche se attualmente non riesco più a ritrovare il sito) chiamata appunto HMC5884L.

Clicca qui per fare il download della libreria. Una volta scaricato il file zip, estraete il contenuto all’interno della directory Program Files > Arduino > LIbraries (se sei su Windows), cioè una cartella nominata HMC5883L.

HMC5883L files library

Fig.4: File contenuti all’interno della libreria HMC5883L

Una volta estratto il contenuto fate partire l’IDE di Arduino. Se tutto è stato installato correttamente troverete un nuovo esempio caricato all’interno dell’IDE (come mostrato nella figura 5).

HMC5883L library IDE

Fig.5: Se l’installazione è andata correttamente troverete l’esempio Simple all’interno di HMC5883L

Un sito in cui è presentato un ottimo tutorial con questa libreria è questo.

Il miglior modo per imparare ad utiliizzare questa libreria è quella di utilizzarla in semplici esempi, durante i quali verranno spiegati i comandi e le funzioni principali, il loro funzionamento e come si usano. A tale scopo in questo articolo faremo due esempi, per prima cosa realizzeremo una bussola digitale, poi utilizzeremo HMC5883L come un vero e proprio magnetometro, raccogliendo dei dati per poi utilizzarli nella rappresentazione di un campo vettoriale tramite MATLAB.

Realizziamo una bussola digitale

Tutti quanti hanno familiarità con questo genere di oggetti. Una piccola scatoletta cilindrica con all’interno un ago di materiale ferroso che risentendo del campo magnetico terrestre, si allinea secondo le linee di campo che percorrono la superficie della terra, indicando così il nord.

Quello che vogliamo realizzare con Arduino è la creazione di una bussola che ci darà il valore 0° quando si punta il sensore verso il nord magnetico, e 180° quando invece stiamo puntando il sud.

Il codice che stiamo utilizzando è molto comune in rete con infinite piccole variazioni. Lo propongo perchè è unn esempio molto utile per capire come utilizzare questo sensore, molto semplice nel suo insieme e adatto a prendere confidenza con i comandi della libreria HMC5883L

Per prima cosa dobbiamo importare la libreria HMC5883L.

Dato che la scheda HMC5883L comunica con Arduino attraverso il protocollo I2C, è necessario importare anche la libreria Wire (leggi qui per maggiori informazioni).

Una volta incluse tutte le librerie necessarie, dichiariamo come variabile globale l’istanza di HMC5883L

Adesso possiamo cominciare a definire il contenuto dei due metodi setup() e loop() onnipresenti in qualsiasi sketch di Arduino.

Cominciamo come logico, dal metodo setup(). Per prima cosa attiviamo il protocollo di comunicazione I2C tra Arduino e il magnetometro.

Inoltre, dato che abbiamo bisogno di visualizzare da qualche parte i valori delle letture del magnetometro, utilizzeremo la comunicazione seriale tra Arduino e un PC. Specifichiamo quindi

Inizializzate tutte le connessioni, adesso possiamo inizializzare anche il magnetometro definendo:

Il passo successivo sarà quello di configurare il sensore a seconda delle nostre esigenze. Per prima cosa è necessario definire il guadagno (scala di risposta) su cui far lavorare il nostro magnetometro.

Con queste righe di codice abbiamo impostato il guadagno a 1.3 Ga (fondo scala), cioè le nostre misure dovranno essere comprese tra valori di -1.3 e 1.3 Ga.

Le scale possibili di guadagno impostabili sul nostro magnetometro sono:  0.88, 1.3, 1.9, 2.5, 4.0, 4.7, 5.6 e 8.1 gauss. Inutile dire che se le vostre minure rientrano entro un certo intervallo, cercate di selezionare la scala minore possibile che lo contiene, poichè la precisione della misura effettuata dalla vostra scheda sarà maggiore.

Adesso cominciamo a definire il contenuto della funzione loop(). Il codice scritto all’interno di questa funzione verrà eseguito in continuazione, e quindi ad ogni sua esecuzione verrà effettuata una misurazione da parte del sensore.

La funzione ReadRawAxis() restituisce il valore ottenuto direttamente dal magnetometro. Quindi i valori ottenuti in questo modo non hanno alcun riferimento al vero valore della forza del campo magnetico, ma sono solo proporzionali ad esso. Quindi se sei interessato al vero valore in gauss del campo magnetico non dovresti prendere in considerazione questa funzione, ma sostituirla con la funzione ReadScaledAxis().

Nel nostro caso però noi siamo interessati a simulare l’orientamento dell’ago magnetico di una bussola, quindi i valori reali non ci interessano. Quindi possiamo tranquillamente utilizzare i valori grezzi di lettura.

Ricordiamoci che il nostro magnetometro è in grado di rilevare contemporaneamente le misure sui tre assi cartesiani. Per ottenere questi valori, basta richiamare i seguenti valori appartenenti alla variabile oggetto MagnetometerRaw in cui li abbiamo immagazzinati. Ecco un esempio di come possiamo ottenere i 3 valori ciascuno per ogni asse (righe da non inserire nel codice).

Se avessimo voluto invece utilizzare i valori reali riportati direttamente in scala (misure in Gauss). (righe da non inserire nel codice)

Adesso definiamo l’ago della bussola all’interno della funzione loop().

dato che l’angolo che otteniamo da tale formula è in radianti, convertiamola in gradi che è un formato a noi molto più familiare e leggibile.

Adesso non ci resta altro che visualizzare il valore ottenuto sul nostro PC collegato ad Arduino tramite comunicazione seriale.

Ho aggiunto delay() in modo da effettuare una misura al secondo (1000 ms), ma potete variare questa misura a vostro piacimento.

Ecco il codice al completo:

Adesso collegando Arduino al PC e aprendo una comunicazione seriale potete controllare il funzionamento della vostra bussola digitale. Ruota la breakout board fin quando non otterrai il valore 0. Una volta ottenuto questo valore scoprirai la direzione del nord (magnetico).

HMC5883L compass serial

Fig.6: Monitor seriale

La declinazione magnetica

Il campo magnetico che avvolge il globo terrestre non è nè perfetto nè uniforme, ma è soggetto a continue variazioni sia nello spazio che nel tempo. Questo effetto è chiamato declinazione magnetica. A tal proposito c’è una bellissima GIF animata che voglio proporvi che presenta la variazione del campo magnetico durante questi ultimi 4 secoli (1590-1990).

Per quanto riguarda la nostra bussola digitale è possibile tenere conto di questo effetto modificando leggermente la formula utilizzata nell’esempio precedente.

Per prima cosa dobbiamo ricavarci il valore della declinazione magnetica della posizione in cui stiamo effettuando la misura. Esiste in internet un bellissimo sito in grado di fornirci in tempo reale proprio il valore della declinazione magnetica di cui abbiamo bisogno (www.magnetic-declination.com). Questo sito vi darà immediatamente la declinazione magnetica della posizione in cui sei collegato. Ecco il mio esempio sotto:

magnetic-declination-map-rome

Fig.7: il valore della declinazione magnetica a Roma al momento in cui sto scrivendo l’articolo.

Dal casella che appare al centro della nostra mappa siamo interessati principalmente al valore:

  • Magnetic declination: +2° 38′ EAST

Adesso connettiamoci su WolframAlpha, un bellissimo sito per il calcolo e le informazioni scientifiche online. Grazie ad esso convertiremo il valore della declinazione magnetica in radianti: nel campo di immissione digitiamo

Wolframalpha radians

Fig.8: il sito WolframAlpha permette di fare molti calcoli matematici e conversioni di unità di misura online

Wolframalpha_radians-result

Fig.9: ecco il risultato della conversione in milliradianti

Quindi all’interno della funzione loop() aggiungiamo il seguente codice:

Questo perchè abbiamo ottenuto una declinazione EAST, se invece la declinazione è WEST avremmo dovuto scrivere:

Ed infine

Un altro esempio: visualizziamo il campo magnetico sul nostro tavolino

Adesso sviluppiamo un altro esempio, a mio parere un po’ più divertente, anche se più laborioso.

In questo esempio faremo una serie di misure sul tavolino vicino al nostro computer per visualizzare le linee di campo che lo attraversano. Nella seconda fase dell’esempio introdurremo un magnete vicino alla zona in cui abbiamo effettuate le misure precedenti e rieffettueremo le misure nuovamente. Sarà interessante osservare l’effetto che introdurrà il magnete sulle linee di campo che attraversano il nostro tavolino.

Per l’esempio che stiamo considerando prenderemo in considerazione solo le componenti vettoriali del campo magnetico sull’asse X e sull’asse Y, visualizzando il campo magnetico che attraversa la superficie del nostro tavolino.

Per prima cosa prendiamo in considerazione il codice per Arduino

come potete vedere dal codice ho utilizzato le misure raw, ma se volete fare un lavoro più preciso vi consiglio di utilizzare le misure scaled. Inoltre ho fatto in modo che il valore visualizzato sul PC serialmente, sia la media ottenuta su 500 valori. Ho fatto vari tentativi e ho visto che con questa media si ottengono valori abbastanza ripetitivi. Incrementando o decrementando il numero dei campioni per media ottengo risulati peggiori (nel vostro caso potete fare varie prove).

Adesso passiamo alla misura vera e propria.

Per prima cosa ho preso un foglio a quadretti e ho disegnato su di esso 35 quadrati aventi ciascuno la stessa dimensione della breakout board della Sparkfun. Ho creato così una matrice di 5×7 quadrati, e poi ho numerato ciascuno di essi in ordine crescente.

HMC5883L matrix measurements

Fig.10: Un foglio a quadretti è una buona base per tracciare una matrice di punti di misura.

Poi ho messo il foglio sul tavolino fissandolo in modo che non si possa muovere su di esso (con del nastro adesivo, o dei pesetti). Una volta fatto questo ho effettuato delle misure del campo magnetico su ciascun quadratino, annotandomi sia la forza del campo magnetico dell’asse X che dell’asse Y. (N.B. i valori letti molto spesso oscilleranno, cercate di vedere il valore che ricorre più spesso)

Alla fine otterrete una tabella di valori. Io vi mostro la tabella dei valori che ho ottenuto io sul mio tavolino e che poi saranno quelli visualizzati nell’esempio.

  X Y Z
1 -27 -348 -386
2 -17 -347 -388
3 14 -350 -389
4 14 -351 -390
5 -5 -360 -393
6 -20 -350 -377
7 -10 -345 -380
8 2 -350 -387
9 27 -353 -390
10 17 -356 -394
11 -46 -325 -368
12 -3 -334 -380
13 9 -340 -386
14 -26 -340 -388
15 -16 -347 -400
16 0 -318 -232
17 17 -340 -368
18 20 -347 -385
19 3 -340 -401
20 21 -340 -408
21 -27 -394 -308
22 -10 -350 -378
23 -5 -334 -398
24 -12 -338 -404
25 -48 -326 -423
26 -47 -350 none
27 1 -346 none
28 1 -343 none
29 38 -343 none
30 -35 -330 none
31 -80 -400 none
32 1 -346 none
33 -23 -342 none
34 15 -340 none
35 -107 -410 none

Una volta ottenuti tutti i valori, apro una sessione su MATLAB e comincio a definire una matrice SX e SY contenenti i valori misurati rispettivamente per X che per Y. Queste due matrici SX e SY hanno dimensione 5×7 ed i valori vanno inseriti al loro interno nella stessa disposizione che abbiamo sul foglio a quadretti, in modo che la distribuzione spaziale delle misure venga rispettata.

definiamo inoltre la disposizione spaziale X e Y di ciascun quadrato (misura).

e finalmente otteniamo la visualizzazione dei vettori del campo magnetico. La figura che otteniamo è invertita rispetto alla foto del tavolino (la cella 1 è in basso a sinistra)

campo magnetico

Fig.11: Il campo magnetico terrestre rappresentato vettorialmente sul piano del tavolino

Adesso inseriamo un magnete alla sinistra del foglio a circa 7 cm da esso e in corrispondenza del centro del foglio.

HMC5883L matrix measurements 2

Fig.8: il magnete è posizionato a destra della matrice

Rieffettuiamo tutte le misure per ciascun quadratino come abbiamo fatto in precedenza, fino ad ottenere la seguente tabella.

  X Y Z
1 -109 -303 -383
2 -108 -284 -391
3 -130 -322 -394
4 -174 -188 -412
5 -244 -9 -446
6 -124 -290 -380
7 -158 -350 -380
8 -185 -267 -394
9 -329 -182 -412
10 -756 -147 -417
11 -125 -294 -363
12 -127 -323 -400
13 -199 -330 -388
14 -403 -275 -399
15 -975 -240 -475
16 -73 -321 -243
17 -105 -356 -365
18 -178 -398 -385
19 -406 -450 -387
20 -778 -820 -332
21 -98 -474 -343
22 -106 -370 -373
23 -154 -420 -390
24 -157 -517 -386
25 -390 -736 -290
26 -85 -373 -382
27 -93 -394 -385
28 -89 -430 -381
29 -121 -500 -380
30 -113 -650 -430
31 -74 -375 -380
32 -76 -465 -378
33 -38 -422 -381
34 -65 -500 -390
35 -160 -523 -400

 

Adesso, sempre con MATLAB definiamo due matrici 5×7 VX e VY contenenti le nuove misure, e alla fine rilanciamo la rappresentazione grafica.

Con il comando hold on possiamo sovrapporre la nuova rappresentazione con quella precedente in modo da visualizzare meglio le variazioni al campo magnetico terrestre introdotte con l’avvicinamento di un magnete.

campo magnetico 2

Fig.12: Il campo vettoriale senza magnete (verde) e quello con il magnete (blu)

Come possiamo vedere l’effetto è abbastanza considerevole in prossimità del bordo destro e va via via diminuendo con l’allontanarsi dal magnete.

Conclusioni

Questo piccolo articolo è solo una piccola introduzione alle grandi potenzialità di questo sensore. Molto interessante sarebbe l’estendere l’esempio precedente a 3 dimensioni considerando anche la Z. Un’altra buona idea sarebbe quella di poter visualizzare la variazione nel tempo del campo magnetico.

Ma questo lo lascio a voi! Arrivederci al prossimo articolo.

 

 

 

 

17 commenti:

  1. albertosallusti

    Complimenti Fabio, bell’articolo applicativo/sperimentale su una brekout board con magnetometro veramente interessante. La spiegazione dei passaggi e del codice utilizzato in questo tutorial è chiarissima e ineccepibile, come al solito.

  2. Ottimo articolo Fabio, professionale e competente come sempre.

  3. Bellissimo articolo!!!Mi chiedevo se è possibile impiegare (sempre che non si tratti di un osservazione fuori luogo dato che non ho nessuna competenza nel campo) il sensore descritto o, se esistono sensori in grado di misurare il campo magnetico sott’acqua. Ad esempio campo magnetico prodotto dalla corrente elettrica sott’acqua.

    • Ciao xnLibn,

      il sensore è un vero e proprio magnetometro a 3 assi (XYZ), quindi in linea teorica è in grado di misurare qualsiasi campo magnetico. Se si vuole misurare un campo magnetico sott’acqua dovrai utilizzare un’opportuna protezione del sensore, inoltre tale involucro, non dovrà in qualche modo schermare il campo magnetico.
      Poi per quanto riguarda l’intensità del campo magnetico da misurare, quello dipende dalla sensibilità del sensore. Inoltre si dovrà in qualche modo tenere conto del campo magnetico terrestre ed eliminarlo, per avere solo le misure del campo magnetico prodotto da un motore, dalla corrente elettrica, da una sorgente di qualche tipo, da un magnete, ecc..
      Spero di esserti stato di aiuto.

  4. Grazie mille sei stato gentilissimo!

  5. riccardopichi

    Buonasera secondo lei e’ possibile integrare in un solo sketch questa bussola con il sensore bmp180?

    • Ciao Riccardo,

      personalmente non l’ho ancora fatto, ma i device che comunicano con protocollo I2C possono lavorare tutti contemporaneamente sui canali A4 e A5 di Arduino. L’importante è che gli indirizzi siano diversi e noti, in modo da chiamarli correttamente durante la connessione tra Arduino e i corrispettivi device. Il sensore BMP180 sembra lavorare su indirizzo 0x77 che è diverso da quelli del magnetometro, quindi dovrebbe essere OK.
      Inutile dire che se funziona, ti invito a presentare un bell’articolo al riguardo. 😉 Stiamo cercando nuovi autori.

      • riccardopichi

        Ti ringrazio per la veloce risposta. Il protocollo i2c non dovrebbe dare problemi. Provo a fare qualcosa nei prossimi giorni.

      • riccardopichi

        Sono riuscito partendo dal tuo esempio e prendendo spunto da un altro esempio per il BMP180 GY-68 a mostrare su uno schermo Lcd I2C pressione, temperatura, altitudine e l’indicazione in gradi del nord magnetico. Ho un piccolo problema: non riesco a rappresentare il simbolo ° nel display lcd: hai qualche idea?

  6. Ciao, ho caricato lo sketch su arduino ma ottengo sempre lo stesso valore sul monitor seriale anche muovendo il sensore. Questo valore resta sempre lo stesso se ricarico lo sketch oppure chiudo il programma e lo riapro ma cambia (anche senza muovere la bussola) se prima di ricaricare lo sketch della bussola ne carico un altro (qualunque). Cosa può essere?

    • Ciao,

      da quanto mi dici possono essere 3 cose:
      errore del codice (ma che lo fa compilare….mmm strano…tipo qualche errore di casting nelle variabili?)
      errore dei collegamenti del circuito
      o qualche malfunzionamento della scheda (controlla se c’è qualche contatto o scarico a terra che fa risultare strani valori.).

      Fammi sapere di più (tipo valori che ti appaiono, se sono coerenti o sono numeri sproporzionati…)

      • Non credo sia un problema dovuto al codice, perché l’ho semplicemente incollato (l’unica modifica sono stati i simboli “” che nel codice sul sito mi appaiono come “<” e “>” … o forse sta proprio qui il problema?).

        I collegamenti sbagliati li escluderei perché sono semplicissimi e li ho controllati più volte. Ho controllato anche che i collegamenti sulla scheda stessa non fossero interrotti.

        I valori che ottengo sul monitor seriale questi sono sempre compresi tra 0 e 360.

        • Ciao, problema risolto!

          Dopo lunghe ricerche ho scoperto che ci sono in giro due sensori magnetici diversi ma simili, HMC5883L e QMC5883L. Nel mio caso il secondo è stato spacciato per il primo e questo è il motivo del malfunzionamento.
          Per chi dovesse riscontrare lo stesso problema c’è il codice per leggere i valoti dal secondo dei due sensori:

          https://github.com/iNavFlight/inav/pull/1935

  7. Ciao Fabio piacere sono Paco, innanzitutto complimenti per il tuo bell’articolo, poi volevo chiederti se riuscivi a darmi qualche dritta in merito al problema che ti espongo, io in sostanza avrei la necessità di poter leggere i dati della misurazione della bussola a circa 40 metri di distanza dal punto in cui dovrei piazzare arduino con magnetometro, avrei pensato di inviare tutti i dati a mezzo di una scheda di rete che credo che esista con arduino, cosa ne pensi riesci ad aiutarmi?. in effetti la bussola con il display mi funzionerebbe ma se volessi mettere il solo magnetometro sul punto in cui effettuare la misurazione 40 mt sarebbero un po troppo in termini di cavo perchè la scheda legga i dati rilevati dal sensore in effetti ho provato e non funziona giustamente. mi consigli qualcosa? resto in attesa se qualcuno mi riesce ad aiutare. saluti a tutti e soprattutto complimenti per il sito.

    • Per questo tipo di progetti ti consiglio di usare gli Arduino MKR1000 o simile con wifi integrato. Vedi articoli sul sito al riguardo (wifi101). Altrimenti puoi usare lo shield wifi per arduino ma rischi di spendere di piu. Lo sketch per il magnetometro rimarrà pressoché lo stesso, dovrai solo aggiungere i comandi per comunicazione wifi.

Lascia un commento

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.