Questa sera mi sono imbattuto in un vecchio problema che avevo già tentato di aggirare con qualche barbatrucco ma con scarsi risultati.

La lettura della rotazione della ruota funziona piuttosto bene fintanto che la ruona non si ferma proprio in corrispondenza della parte bianca (acceso). In questa posizione, il contatore di giri della ruota inizia a dare i numeri in modo del tutto casuale. Per un po' rimane fermo, poi inizia a contare in modo velocemente una serie di rotazioni, ... insomma, quando BigWheely è fermo in questa posizione il sistema diventa alquanto instabile.

Dopo uno sterminato numero di esperimenti ho capito che sembrano esserci diverse concause, quella più accreditata è un problema di disturbi di natura elettrica generati dal servo, che per mantenere la sua posizione viene gestito con impulsi in frequenza (PWM).
In alcune posizioni, il servo inizia a vibrare leggermente e ad emettere un ronzio, ho letto che spesso questo è normale, MA è proprio quando si verifica questo ronzio che è più probabile vi siano i conteggi della rotazione della ruota in modo incontrollato !

Sto tutt'ora cercando una soluzione, ho già tentato numerose strade ma senza sostanziali miglioramenti, attualmente sto verificando se può aiutarmi la soluzione proposta in questo articolo (Eliminare interferenze date dai servomotori).

schema_arduino

Il test di rotazione di BigWheely sulla sedia ha ottenuto risultati sempre migliori, a partire dalle prime rilevazioni, fino alle compensazioni ottenute mediante le funzioni lineari.

Il software per la calibrazione di FreeIMU ha permesso di implementare un metodo semplice (e soprattutto leggero per Arduino) e in grado di correggere molto efficacemente i valori misurati dalla bussola.

I fenomeni e le tecniche per la compensazione dei compass è descritta abbondantemente in questo articolo, anche se lo sconsiglio perchè è piuttosto pesantino!!

Piuttosto consiglio l'articolo che allego, che spiega molto bene il fenomeno e approfondisce l'argomento, anche questo è un po' tecnico, ma è davvero molto interessante.

Calcolare gli offset di compensazione utilizzando Magneto

Magneto v1.2 è un piccolo software descritto su questo sito , che permette di calcolare gli offset in modo analogo a quello di FreeIMU, con la sostanziale differenza che non è necessario scaricare quasi 100 Mb di programma ma soli 400Kb (vedi allegato).

Il software permette di caricare dei tracciati (acquisizioni dati) fatti in precedenza, e di applicare l'algoritmo.
Io ho provato ad usare il tracciato generato dal software FreeIMU_GUI e ho ottenuto dei valori di offset praticamente identici.

risultati Magneto 1.2:

magneto test1


risultati FreeIMU_GUI:

risultati calibrazione FreeIMU GUI

 

 

Questo è il video del comportamento del compass dopo aver applicato gli offset calcolati mediante il software di FreeIMU o Magneto.

 

Dopo avere preparato tutti i tool necessari, ho preparato BigWheely nella stessa posizione dei test precedenti, ovveros su una sedia girevole.

test compass sedia r

 

Ora ho iniziato a campionare i dati tramite il FreeIMU calibration GUI, nel frattempo ruotavo lentamente la sedia.

Ecco il video della campionatura dei valori:

 

 

Al termine dell'acquisizione, e premuto il pulsante Calibrate, il programma calcola automaticamente gli offset di correzione.

risultati calibrazione FreeIMU GUI

 

Molto interessante è il fatto che i dati trasmessi da Arduino vengono salvati in un file, questo si chiama magn.txt e si trova all'interno della cartella principale del programma.

Io allego il file della mia acquisizione.

Ho approfondito la lettura e l'interpretazione di questi dati, riportandoli in un foglio excel e applicando le correzioni calcolate, in modo da vedere graficamente il risultato:

tabella calibrazione0

 

Mettendo in relazione i valori X e Y acquisiti dal compass è possibile visualizzare il cerchio più volte descritto durante lo studio dell'algoritmo per la calibrazione. Il grafico seguente rappresenta Fx(y).

Il cerchio BLU indica i dati acquisiti,senza correzioni, mentre il cerchio ROSSO indica i valori dopo aver applicato l'offset calcolato (per X e Y).

grafico calibrazione1

 

Per curiosità ho analizzato anche i dati di Fx(z), questo mostra la deviazione rispetto l'asse z.
Idealmente avrei dovuto vedere una semplice riga e non un ellisse come mostrato nel grafico seguente.

In realtà un piccolo scompenso esiste anche qui, ma per ora vorrei poter trascurare questo "errore" in quanto non è molto accentuato. Nel caso in cui avessi utilizzato il compass nelle tre dimensioni, avrei dovuto da subito tenerne conto, ma nel progetto BigWheely, l'inclinazione dell'asse z non cambia mai (si muove su superfici piane !). 

grafico calibrazione2

 

Nel grafico seguente ho voluto mettere in relazione l'angolo di rotazione con l'arcotangente calcolata tra gli assi X e Y.

Si può notare che l'arcotangente tra i 2 vettori non è lineare in funzione della rotazione di BigWheely.
Questo è proprio il fenomeno riscontrato negli esperimenti precedenti, per cui l'indicazione dell'angolo sembra impazzire durante la rotazione (vedi test precedenti).

La linea ROSSA mostra invece il comportamento ideale. Il valore compensato dovrebbe avvicinarsi a questa linea di tendenza.

grafico calibrazione3

 

Ho voluto infine mettere in relazione l'errore generato in funzione della rotazione, si può notare come in prossimità di alcuni angoli la differenza è pressochè nulla (es. 70° e 150°) , mentre in altre posizioni, l'errore si manifesta notevolmente.

grafico calibrazione4

 

L'applicazione permette infine di esportare i valori di compensazione in un file, questo è pensato per l'utilizzo con il modulo FreeIMU, ma questi dati saranno certamente utili al momento di integrarli nel futuro firmware di BigWheely.


/**
* FreeIMU calibration header. Automatically generated by FreeIMU_GUI.
* Do not edit manually unless you know what you are doing.
*/
#define CALIBRATION_H
const int acc_off_x = 0;
const int acc_off_y = 0;
const int acc_off_z = 0;
const float acc_scale_x = 0.665659;
const float acc_scale_y = nan;
const float acc_scale_z = nan;
const int magn_off_x = 255;
const int magn_off_y = 153;
const int magn_off_z = -160;
const float magn_scale_x = 262.332062;
const float magn_scale_y = 272.456604;
const float magn_scale_z = 93.983179;
Allegati:
Scarica questo file (magn.txt)magn.txt[ ]298 kB

Sto facendo alcuni test per trovare il modo di migliorare la lettura del modulo bussola (HMC5887L) in quanto i risultati ottenuti finora anche se non sono pessimi, non mi soddisfano ancora.

Ho trovato un interessante GUI per la visualizzazione dei dati raccolti dal modulo compass che si basa sulle librerie FreeIMU.

Ho quindi tentato di utilizzarlo sulla mia configurazione, sono infatti riuscito abbastanza semplicemente ad utilizzare questo software e poter testare in tempo reale i valori registrati dal modulo compass e visualizzarli.

Ecco i passi necessari:

1) Installare le librerie FreeIMU

Scaricare la libreria FreeIMU e salvarla sul computer. Io l'ho allegata a questo articolo (vedi in fondo all'articolo, ma può essere scaricata anche dal sito che descrive questo progetto.

Quindi aprire il software Arduino e installare la libreria:

installa freeIMU1

installa freeIMU2

 

A questo punto si dovrebbe caricare lo sketch FreeIMU_serial.ino, ma stranamente c'erano degli errori in questo esempio per la quale non funziona correttamente con il software di calibrazione, percui caricate lo sketch che allego (versione corretta).

 

installa freeIMU3

ATTENZIONE: Caricare lo sketch allegato, e non quello di esempio!

 

Caricare questo sketch su Arduino

installa freeIMU4

 

 

2) Scaricare e avviare FreeIMU Magnetometer and Accelerometer Calibration GUI

 Scaricare e avviare il software FreeIMU Magnetometer and Accelerometer Calibration GUI (circa 90Mb)

FreeIMU GUI

 

3) Connessione Arduino - GUI e test

Il sistema è ora pronto per inizia l'acquisizione dei dati.

Inserire il nome della porta su cui è collegato Arduino, quindi premere il tasto Connect. Se la porta è corretta, nella finestra command appare la scritta "Arduino serial port opened correctly".

Se tutto è corretto (importante che su Arduino sia in esecuzione lo sketch corretto), nella parte inferiore della GUI dopo qualche secondo appare il messaggio:

"Connected to: FreeIMU library by Fabio Varesano - varesano.net, FREQ:16 MHz, LIB_Version: 20121122, IMU: FreeIMU v0.4"

e si attiva il pulsante Start Sampling, l'acquisizione dei dati inizia!

 

Allegati:
Scarica questo file (FreeIMU-20121122_1126.zip)Libreria FreeIMU 2012/11/22[ ]3148 kB
Scarica questo file (FreeIMU_serial.ino)FreeIMU_serial.ino[ ]5 kB

Il risultato deludente della precisione del modulo compass non mi ha dato pace per parecchio tempo.

Così ho voluto cercare di capire meglio questo problema e fare ulteriori tests.

 

Raccolta dati per elaborare una soluzione

Innanzitutto ho disegnato su un foglio delle righe in corrispondenza dei vari angoli. La posizione del Nord non è rilevante per questo test, ho voluto in ogni caso verificare se in qualche modo il mio cellulare era influenzato da qualche campo magnetico che non avevo considerato.

test angoli setup

 

Ho predisposto BigWheely parallelo ai rispettivi angoli che ho disegnato e ne ho rilevato i valori trasmessi.

Ho raccolto i dati in un foglio excel e fatto alcune considerazioni:

tabella funzione compass

 grafico funzione compass

 

Interpretazione dei dati raccolti

Innanzitutto, l'asse orizzontale mostra l'angolo REALE di posizionamento, mentre l'asse verticale indica il valore MISURATO.

La linea retta BLU denominata "Teorico" indica il comportamente ideale, ad ogni angolo reale corrisponde lo stesso angolo misurato.

Le curve VERDI e ROSSE sono molto simili tra loro, ho provato infatti a rilevare le identiche misurazioni ma assegnando alla funzione SetScale (libreria HMC5883L.h descritta in precedenza) valori differenti (prima 8.1 Ga e poi 1.3 Ga).
Il risultato, come si può notare dalla sovrapposizione delle curve, non cambia di molto.

 

Calcolo delle funzioni di compensazione

Ho aggiunto delle linee di tendenza in corrispondenza della curva ROSSA, e ho identificato una funzione di quinto grado che aderiva molto bene, ho dovuto scartare subito l'idea di integrare questa funzione in Arduino in quanto risolverla sarebbe stato un calcolo eccessivo (i numeri in gioco erano davvero molto grandi).
Ho quindi optato per utilizzare funzioni lineari e di suddividerle in segmenti più piccoli.

Calcolando i coefficienti k1, k2, k3 che determinano l'inclinazione e b1,b2,b3 (descritti erroneamente sempre con b) che influenzano lo spostamento verticale della retta, ne ho ricavato 3 funzioni F(x).
Da queste funzioni F1(x), F2(x), F3(x) ho potuto calcolare le rispettive funzioni inverse G1(x), G2(x), G3(x).

Si può notare come la curva risultante delle funzioni inverse G(x) rappresentata in AZZURRO seguono piuttosto bene la linea teorica.

 

Ho infine applicato queste funzioni in uno sketch su Arduino e ho provato ad effettuare di nuovo i rilevamenti.
Nelle immagini seguenti sono riportate le posizioni di BigWheely (sinistra), dei rispettivi angoli misurati (Campo Movement) e l'angolo rappresentato dopo le compensazioni appena descritte (campo Angle). 
NOTA: Il campo Movement mostra l'angolo moltiplicato per 10 (es: 3580 ==> 358.0 gradi)

 

 

 ANGOLO RIFERIMENTO: 0 GRADI  
 test angolo 0 misura angolo 0 
 ANGOLO RIFERIMENTO: 90 GRADI  
 test angolo 90  misura angolo 90
ANGOLO RIFERIMENTO: 180 GRADI  
test angolo 180 misura angolo 180
ANGOLO RIFERIMENTO: 270 GRADI  
test angolo 270 misura angolo 270

 

 

Generalmente le misurazioni si sono rilevate decisamente migliorate, in corrispondenza degli angoli dei punti cardinali (0; 90; 180; 270) sembra esserci una buona precisione.

 

Per concludere l'esperimento ho riapplicato l'identico test fatto in precedenza per constatare il comportamento durante la rotazione continua, ecco il video: