La scheda di sviluppo Adafruit Circuit Playground Classic offre una piattaforma completa dal punto di vista delle funzionalità per poter sviluppare una miriade di progetti embedded. Infatti, grazie alla ricca dotazione di sensoristica e alla presenza di LED RGB è possibile realizzare progetti divertenti e accattivanti semplicemente con la singola scheda. Inoltre, Adafruit ha elaborato differenti shield di espansione per aggiungere ulteriori funzionalità.
Dopo aver affrontato l’utilizzo dei NeoPixel e del sensore di temperatura nel primo articolo e del buzzer e degli ingressi capacitivi nel secondo articolo, in questa terza parte andremo ad affrontare l’utilizzo del sensore di movimento che abbiamo a disposizione sulla scheda di sviluppo Adafruit Circuit Playground Classic. In particolare, tra le innumerevoli dotazioni di bordo di questa piattaforma troviamo anche un sensore di movimento STM LIS3DH.
Gli accelerometri sono ormai diventati oggetti molto diffusi in quanto usati largamente all’interno non solo degli smartphone ma di innumerevoli oggetti grazie alla varietà di applicazioni che si possono implementare. Infatti, grazie all’ausilio degli accelerometri possiamo realizzare funzionalità interessanti quali:
- contatore di passi
- rilevamento della caduta libera
- funzioni di attivazione e disattivazione in base al movimento
- monitoraggio delle vibrazioni
In un package dalle dimensioni ridottissime (appena 3x3 millimetri) abbiamo un circuito integrato che implementa un accelerometro a 3 assi in tecnologia MEMS con un range di full-scale configurabile tra ±2g/4g/8g/16g. L’oggetto è concepito per mantenere dei bassissimi consumi garantendo al contempo ottime prestazioni. Infatti, da un rapido sguardo al datasheet del produttore scopriamo che questo componente è stato progettato anche per lavorare in modalità ultra low power (con un assorbimento di appena 2uA). Per chi volesse approfondire le caratteristiche tecniche di questo piccolissimo circuito integrato vi rimando al datasheet riportato nel link. La funzionalità base di un accelerometro è molto semplice: per ogni asse implementato (nel nostro caso tutti e tre gli assi) ci fornisce una misura dell’accelerazione a cui è sottoposto l’asse. Ricordiamo che l’accelerazione si misura in m/s^2 e, in qualsiasi caso, troveremo sempre l’accelerazione di gravità con direzione verso il centro della terra e pari a circa 9.81 m/s^2 (indicata anche con 1g).
Le funzionalità di libreria
Come per gli altri sensori e funzionalità della scheda Circuit Playground, anche per il sensore di movimento ci vengono in aiuto le funzioni già disponibili in libreria. Vediamo più precisamente quali sono:
- CircuitPlayground.motionX(), CircuitPlayground.motionY(), CircuitPlayground.motionZ(): attraverso queste tre funzioni possiamo andare a prelevare i dati acquisiti dal sensore di movimento lungo i tre assi X, Y e Z. In particolare, otterremo un valore di accelerazione espressa direttamente in m/s^2.
- Un’altra funzione molto utile è CircuitPlayground.setAccelRange(“range”) che ci consente di configurare il range del fondo scala del sensore potendo selezionare tra i seguenti 4 valori: ±2g/4g/8g/16g. La configurazione avviene semplicemente passando il parametro “range” che può assumere uno dei seguenti 4 valori:
-
- LIS3DH_RANGE_16_G = 0b11, // +/- 16g
- LIS3DH_RANGE_8_G = 0b10, // +/- 8g
- LIS3DH_RANGE_4_G = 0b01, // +/- 4g
- LIS3DH_RANGE_2_G = 0b00 // +/- 2g (default value)
Il valore di default per il range di accelerazione è quello corrispondente a un fondo scala di +/-2g e di fatto corrisponde anche al fondo scala che garantisce delle misure più accurate. Al crescere del valore di fondo scala diminuisce di conseguenza anche l’accuratezza garantendo però il poter misurare valori di accelerazione più elevati.
Esempio 1: plotter seriale dell’accelerometro
Qui di seguito riporto un semplice esempio che sfrutta le funzionalità di libreria per poter stampare sul plotter seriale dell'IDE di Arduino i valori delle accelerazioni lungo i tre assi X, Y e Z.
#include <Adafruit_CircuitPlayground.h> float X, Y, Z; void setup() { Serial.begin(9600); CircuitPlayground.begin(); //setting del range CircuitPlayground.setAccelRange(LIS3DH_RANGE_2_G ); } void loop() { //acquisizione dei valori X = CircuitPlayground.motionX(); Y = CircuitPlayground.motionY(); Z = CircuitPlayground.motionZ(); //stampa dei valori su seriale per monitor e plotter Serial.print("asse X: "); Serial.print(X); Serial.print(","); Serial.print("asse Y: "); Serial.print(Y); Serial.print(","); Serial.print("asse Z: "); Serial.println(Z); delay(100); }
Il calcolo dell’inclinazione
Come ben sappiamo, gli accelerometri sono sensori in grado di rilevare solo l’entità delle accelerazioni, espresse in m/s^2. Tuttavia, spesso in giro sentiamo parlare dell’utilizzo degli accelerometri come oggetti capaci di fornirci misure di inclinazione. Ma come è possibile? Il trucco o meglio stratagemma ci viene fuori dalla combinazione di due elementi:
- la nostra magica Terra che ci fornisce l’accelerazione di gravità
- l’applicazione di un pò di matematica, trigonometria e nozioni sui vettori
L’accelerazione di gravità è una grandezza vettoriale. Le grandezze vettoriali sono identificate tramite 3 elementi: verso, direzione e intensità. In particolar modo, l’accelerazione di gravità avrà direzione perpendicolare alla superfice terrestre (quindi alla nostra scrivania per intenderci), verso positivo verso la superfice terrestre e infine intensità pari a circa 9.81m/s^2 (il numero preciso è 9,80665 ma ci accontentiamo dell’approssimazione). Dunque, l’accelerazione di gravità ci dà un elemento di confronto su cui poter applicare un pò di trigonometria e calcolarci l’angolo di inclinazione. Infatti, ogni asse del nostro accelerometro ci fornirà un valore pari all’accelerazione di gravità quando posizionato lungo la stessa direzione e verso e di segno opposto se posizionato lungo la stessa direzione ma verso opposto. Considerando la nostra scheda Adafruit Circuit Playground Classic avremo che l’orientamento dei 3 assi è positivo secondo le frecce del simbolo riportato in serigrafia.
Passiamo ora alla funzione di calcolo dell’inclinazione e consideriamo per semplicità solo il primo asse, ossia l’asse z. Già grazie ad un asse siamo in grado di avere una stima dell’angolo di inclinazione. Sapendo che in un triangolo rettangolo vale la formula per cui un cateto (c) è pari all’ipotenusa (a) moltiplicata per il coseno dell’angolo adiacente (beta), allora invertendo la formula avremo che:
- l’angolo beta è pari alla funzione inversa del coseno (arcocoseno) il cui argomento sarà il rapporto tra cateto e ipotenusa
Tornando alla nostra applicazione avremo che il cateto è la misura di accelerazione lungo l’asse Z e l’ipotenusa l’accelerazione di gravità già nota. Dunque, la formula ha una sola incognita che è l’angolo e possiamo calcolarlo in maniera semplice ed immediata. Per il nostro progetto utilizzeremo la funzione acos() già disponibile nella IDE di Arduino. Questa è una funzione che calcola l’arcoseno a partire da un numero compreso tra -1 e 1 e restituisce un angolo espresso in radianti. La conversione di angolo da radianti a gradi è semplice ed immediata: basta moltiplicare per 180 e dividere per pi-greco. Purtroppo, come già abbiamo visto nell’esempio precedente, anche in posizione di riposo, l’accelerazione di gravità misurata (che dovrebbe essere pari a 9.81) è leggermente più alta. La causa può essere dovuta alle tolleranze del circuito integrato. Questo si può risolvere applicando una formula di compensazione delle misure, ossia calcolando il drift della misura in una posizione di riposo.
Se non correggiamo questo effetto avremo due conseguenze:
- la prima è che il rapporto tra cateto e ipotenusa può diventare superiore a 1, condizione fisicamente impossibile e soprattutto fuori dall’intervallo consentito per la funzione matematica arcoseno
- la seconda è un errore significativo nella misura di inclinazione
Realizziamo dunque una funzione che effettua 5 misurazioni in condizioni di riposo e calcola il valore di offset da applicare alle misure come misura tra il valore massimo acquisito e il valore. Infine, andiamo a correggere l’eventuale generazione di valori fuori dal dominio della funzione arcoseno.
Esempio 2: Calcolo dell'inclinazione
In questo secondo esempio ho riportato il codice integrale per il calcolo dell'inclinazione a partire dai valori di accelerazione.
#include <Adafruit_CircuitPlayground.h> [...]
ATTENZIONE: quello che hai appena letto è solo un estratto, l'Articolo Tecnico completo è composto da ben 1903 parole ed è riservato agli ABBONATI. Con l'Abbonamento avrai anche accesso a tutti gli altri Articoli Tecnici che potrai leggere in formato PDF per un anno. ABBONATI ORA, è semplice e sicuro.