Il firmware

Il firmware

Il suo compito, è quello di calcolare quale faccia è attualmente selezionata attraverso i valori fornito dal giroscopio e dall'accellerometro. Ma non solo!

I vincoli principali sulla piattaforma hardware su cui sviluppare il firmware del dispositivo erano le ridotte dimensioni ed il basso costo dei componenti. Per questo, la scelta è ricaduta su un Arduino Nano, un modulo Bluetooth HC-05 ed un sensore MPU6050, il quale contiene al suo interno un giroscopio ed un accelerometro MEMS. Questi ultimi due moduli sono ampiamente diffusi, documentati e facilmente reperibili a poco prezzo. Inoltre, sono da sempre utilizzati in progetti che sfruttano i prodotti Arduino, per cui un’alta compatibilità di tutti i componenti del sistema l’uno con l’altro era garantita. Per quanto riguarda l’Arduino Nano, inoltre, la sua versatilità e facilità d’impiego hanno rafforzato suddetta decisione. Lo scopo ultimo del firmware è individuare, con l’ausilio del sensore MPU6050, la faccia sulla quale l’ottaedro è stata attualmente posizionato dall’utente e comunicarla in una stringa di caratteri al dispositivo mobile connesso attraverso il Bluetooth. Sulla scheda integrata sono presenti anche tre LED (uno rosso, uno giallo ed uno verde) gestiti dal codice per indicare il livello della batteria. Al fine di ottenere ciò, la tensione in uscita dalla batteria, da 3.7 V, è disponibile in ingresso all’Arduino al pin A7. Il Bluetooth comunica con porta seriale come quella usata dallo standard USB: oltre all'alimentazione e al collegamento di terra, richiede un segnale di trasmissione ed uno di ricezione. A tale scopo, è stata utilizzata la libreria SoftwareSerial.h, che permette di definire una porta seriale su una qualunque coppia di pin dell'Arduino stesso. A tal scopo, è bastato porre prima della funzione setup() il comando:


SoftwareSerial bluetooth (rx_pin, tx_pin);

dove rx_pin = 12 e tx_pin = 10 (scelti per vantaggi di layout nella progettazione della scheda che connette i vari componenti). Il giroscopio MPU6050 sfrutta lo standard di comunicazione digitale seriale I2C: un protocollo sincrono di tipo master / slave che usa due link seriali fra il master (il quale invia le richieste di dati allo slave e può scrivere nei suoi regstri) e lo slave (il quale invia i dati richiesti dal master). Questi due link sono Serial Data (SDA, i dati effettivi inviati) e Serial Clock (SCL, segnale di riferimento del clock per mantenere la sincronia dei dati fra master e slave). Nell’Arduino Nano, suddetti link si trovano solo sui pin analogici A4 e A5, rispettivamente. Per poter far effettivamente comunicare i due componenti attraverso suddetto standard, è bastato utilizzare la libreria Wire.h, la quale mette a disposizione semplici primitive per poter trasmettere e ricevere dati con il dispositivo slave, una volta noto l’indirizzo I2C dell’MPU6050 (0x68, in esadecimale). Come convenzione nei codici Arduino, sono stati utilizzate delle variabili globali e delle costanti globali dichiarate prima della funzione setup(), la quale è il punto d’accesso per l’esecuzione del codice. La funzione setup() inizializza la comunicazione seriale con il Bluetooth e con il giroscopio, dichiara i pin dei LED e chiama la funzione set_up_mpu (). Quest’ultima attiva il giroscopio ed imposta i range di valori che possono assumere i dati (double) che rappresentano i segnali del giroscopio e dell’accelerometro. In seguito, Arduino chiama automaticamente la funzione loop(), la quale viene eseguita continuamente durante il funzionamento del dispositivo. In essa avvengono le elaborazioni volte ad individuare la faccia dell’ottaedro che è stata attualmente scelta dall’utente. Sono stati sfruttati i dati forniti dall’accelerometro per determinare la faccia scelta ed i dati forniti dal giroscopio per comprendere se il dispositivo sia in movimento oppure fermo. Se è in movimento, non deve essere fatta alcuna elaborazione. A tal scopo, la funzione loop prima di tutto richiede i dati del giroscopio attraverso la funzione values_gyr(), che li scrive nelle variabili globali gyx, gyy e gyz (letture del giroscopio per ciascuno degli assi cartesiani). Questi valori vengono poi salvati nelle variabili globali gyx_old, gyy_old e gyz_old, in modo che, dopo un delay di un secondo, si possano nuovamente richiedere i dati attuali del giroscopio in gyx, gyy e gyz, sovrascrivendo quelli precedenti. Questi, se il dispositivo è in movimento, saranno grandemente differenti rispetto a quelli salvati nelle variabili con suffisso “_old” ottenute un secondo prima; se invece è rimasto fermo, saranno molto simili. Per verificarlo, è stato posto un blocco if che determini se il valore assoluto della differenza fra le variabili gyx, gyy e gyz e quelle con suffisso “_old” sia inferiore ad una certa tolleranza gyr_tol, sufficientemente bassa per verificare la stabilità spaziale. E’ stata usata gyr_tol = 3.0, valore determinato sulla base di osservazioni sperimentali dei dati forniti in real-time dal giroscopio e dall’accelerometro. In caso la condizione di stabilità sia verificata, allora vengono richiesti anche i dati dell’accelerometro con la funzione values_acc(), la quale li scrive nelle variabili globali acx, acy e acz, in modo analogo a quanto fatto per il giroscopio. Successivamente, viene chiamata la funzione che elabora gli angoli di rollio (roll, rotazione del sistema di riferimento dell’accelerometro attorno all’asse x), di beccheggio (pitch, rotazione attorno all’asse y) e quello dato dalla rotazione attorno all’asse z (z_ang). La formula per calcolarli assume la medesima forma per i tre valori, anche se vengono usati in ordine differente i tre dati letti dall’accelerometro:


// pitch angle calculation
double mod = sqrt (acx * acx + acz * acz);
pitch = atan (acy / mod) * 180.0 / M_PI; 

// roll angle calculation
mod = sqrt (acy * acy + acz * acz);
roll = atan (acx / mod) * 180.0 / M_PI; 

// z axis angle calculation
mod = sqrt (acy * acy + acx * acx);
z_ang = atan (acz / mod) * 180.0 / M_PI;

Questi tre valori consentono di identificare in modo univoco l’orientazione spaziale dell’oggetto in questione e sono sufficienti per determinare la faccia su cui esso si trova. Ottenuti questi dati, viene chiamata la funzione calc_face(). In questa, la variabile globale intera che contiene il numero della faccia individuata viene inizialmente inizializzata a -1. Successivamente, si verifica con degli if annidati se il valore assoluto della differenza fra gli angoli di roll, pitch e z_ang attuali e quelli “propri” di ogni faccia è inferiore ad una certa tolleranza. Questi angoli “propri” di ogni faccia sono stati determinati sperimentalmente in condizioni ottimali di superficie piana e sono la media su un gran numero di campioni forniti dal dispositivo. Analogo a quanto fatto precedentemente per il giroscopio, la tolleranza ang_tol è stata posta pari a 10.0 sulla base di osservazioni sperimentali. Ad esempio, per la faccia 1 gli if annidati risultano essere:


if (abs (pitch - pitch_face_1) < ang_tol)     
	if (abs (roll - roll_face_1) < ang_tol)            
		if (abs (z_ang - z_ang_face_1) < ang_tol)                 	
			face = 1;

dove pitch_face_1 = -0.455, roll_face_1 = -50.065 e z_ang_face_1 = -39.965. Se tutte e tre le condizioni sui tre angoli vengono soddisfatte per una certa faccia, allora il valore di quest’ultima viene assegnata alla variabile face e questa viene poi inviato con il Bluetooth all’applicazione mobile in una determinata stringa. Se nessuna condizione è stata soddisfatta, allora non è stato possibile individuare alcuna faccia uguale alla posizione attuale ed il valore della variabile face rimane pari al -1 iniziale, che fungerà dunque da flag di fallimento dell’identificazione.

Il modulo Bluetooth e il giroscopio

La sezione per il power management

Più nel dettaglio. Come funziona?

La struttura

Per realizzare la struttura ci siamo serviti della tecnlogia di stampa 3D.

L'hardware

La piattaforma open source "Arduino" è il cuore pulsante dell'ottaedro, con attorno a se molti altri componenti importantissimi.

Il firmware

Un firmware "ah hoc" è stato sviluppato per coordinare tutte le funzionalità dell'ottaedro.

Il software

Avvalendosi dell'ambiente "Xamarin", è stato possibile creare in modo semplice e veloce un'app per smarthone in grado di tener traccia di tutte le attività, connettendosi con l'ottaedro.