Interfacciamento accelerometro a 3 assi ADXL345 a PIC12F1822

In questo “esperimento”, che sto facendo per testare un mio semplice software di prossima pubblicazione (su youtube ho messo una bozza tempo fa), vi illustro come collegare un accelerometro a 3 assi ADXL345 prodotto dalla Analog Devices ad un PIC12F1822. La scelta è ricaduta su questo piccolo PIC per i seguenti motivi:

  • Il software di cui parlavo riceve i dati su RS232/Seriale emulata su USB e plotta l’andamento dei valori di accelerazione su 3 grafici in tempo reale, ho quindi bisogno di un pic con una UART, e il 12F1822 ce l’ha!
  • L’ADXL345 comunica su bus I2C, e il 12F1822 ha un modulo MSSP, (great!)
  • Ho quindi bisogno solo di 4 pin, perchè dovrei usare una MCU da 40 pin?

L’ADXL345 funziona a 3.3V, il pic12F1822 può tranquillamente essere alimentato a 3.3V, per cui alimenterò entrambi con tale tensione, bisognerà unicamente stare attenti in fase di programmazione su ICSP a disconnettere l’accelerometro dalla scheda se non vogliamo danneggiarlo subito a meno che non ci ricordiamo di impostare il pickit per fornire 3.3V anzichè 5.

L’ADXL345 viene venduto su una comoda Breakout Board che consente un utilizzo facile, altrimenti il package non sarebbe proprio di quello adatto agli hobbysti nemmeno più esperti (si tratta di un package LGA, Land Grid Array). Non abbiamo di fronte un accelerometro di quelli proprio economici ma ha numerose caratteristiche interessanti come la presenza di due pin di interrupt, che possono essere programmati per rilevare il “TAP” e “Doppio TAP” (un po’ come click e doppio click col mouse) o per altre funzioni, ha una risoluzione fino a 13bit e può misurare fino a ±16 g, consentendoci di settare la scala. Può inoltre funzionare sia in I2C che in SPI, un accelerometro completo insomma, utilizzabile per mille applicazioni diverse dalle più semplici a quelle che richiedono elevate caratteristiche.

Questo è il semplice circuito che ho approntato:

L’alimentazione a 3.3V non potete fornirla dal Pickit perchè questo porta a massa i pin PGD e PGC, e il pin PGC come vedete è utilizzato anche dal Clock I2C. Sul Pin MCLR non ho messo la resistenza di pullup perchè nella word di configurazione utilizzo MCLRE_OFF. Sappiamo che sui pin dell’I2C  ci vanno 2 resistenze di pullup: il modulo I2C lo setto per lavorare a 400KHz e con le resistenze da 4.7KΩ mi sono trovato bene, eventualmente abbiate qualche problema (tipo: state usando una breadboard cinese) provate con un valore leggermente più alto (o più basso?). I pin RX/TX del PIC vanno verso un adattatore seriale TTL/RS232 (però attenzione: bisogna prendere degli accorgimenti per interfacciarlo ai 3.3V richiesti dal PIC), oppure verso un adattatore seriale TTL/USB (che lo potete usare anche su un portatile). Io personalmente mi trovo molto bene con questo di Robot-Italy che può essere impostato per interfacciarsi anche con le logiche TTL a 3.3V: operazione necessaria in questo caso.

Per usare l’ADXL345 in modalità I2C anzichè SPI è necessario collegare il pin CS a VCC, in questo caso il pin contrassegnato come SDO ha la funzione ALT ADDRESS (indirizzo alternativo): collegando tale pin a massa l’accelerometro avrà l’indirizzo a 7bit 0x53 (che si traduce in 0xA6 per la scrittura e 0xA7 per la lettura). Collegando invece SDO a VCC l’indirizzo a 7 bit sarà 0x1D (0x3A in scrittura e 0x3B in lettura).

Appena alimentato, l’ADXL345 si trova in standby (Vedi datasheet, pagina 6, paragrafo “Power Sequencing”), per cui bisogna metterlo in modalità misura inviando un comando al registro 0x2D (registro POWER_CTL):

Il bit che ci interessa è il 3: mettendolo a 1 l’accelerometro esce dallo standby e si mette in modalità misura, per cui all’inizio, dopo essermi assicurato che tutti i moduli siano inizializzati correttamente, invio tale sequenza:

I2cStart();
I2cWriteMaster(ADXL_ADDRESS<<1); // invio indirizzo ADXL345 in scrittura (bit0 a 0)
I2cWriteMaster(0x2D);
I2cWriteMaster(8);
I2cStop();

Fate riferimento all’articolo sull’I2C per capire il senso di queste operazioni. I valori di accelerazione lungo i 3 assi sono contenuti nei registri a partire dal 0x32 fino al 0x37:

0x32: parte bassa asse X
0x33: parte alta asse X
0x34: parte bassa asse Y
0x35: parte alta asse Y
0x36: parte bassa azze Z
0x37: parte alta asse Z

I dati sono restituiti, di default, nel formato complemento a 2, quindi signed a 10bit. La risoluzione e il formato dati si cambiano nel registro 0x31:

In particolare il bit 2 posto a zero (condizione di default) permette l’allineamento a destra del risultato con il segno. I bit 0 e 1 impostano il range di misura. All’avvio il valore di questo registro è 0x00 per cui l’accelerometro è settato per avere un range di misura di ±2g.

Per leggere il valore degli assi in un colpo solo è conveniente utilizzare la lettura sequenziale a partire dall’indirizzo 0x32. La lettura sequenziale viene eseguita in maniera uguale alla lettura random, con la sola differenza che basta inviare un ACK dopo il primo byte ricevuto dallo slave in maniera tale che esso continui a fornire dati spostandosi man mano nei registri successivi. Basterà dare un NACK alla fine dell’ultimo byte che ci interessa per interrompere la comunicazione. In questo articolo è già spiegato tutto.

Dopo aver memorizzato in un buffer tutti i dati ricevuti dallo slave, provvedo semplicemente a stamparli su seriale in maniera rapida utilizzando una printf:

printf("%d,%d,%d\n\r",x,y,z);

La seriale è impostata per lavorare a 57600,8,n,1. Un esempio di comunicazione seriale con il 12F utilizzato in questo progetto l’ho già fatto in questo precedente articolo.

Su seriale leggeremo quindi 3 valori separati da virgola, indicanti rispettivamente i valori di accelerazione lungo gli assi X,Y,Z. Il valore restituito non è espresso in g ma in bit. Abbiamo detto di avere una risoluzione di 10bit e che il valore restituito è di tipo signed, per cui a 10bit otterremo dei valori che vanno da un minimo di -512 (che corrisponde ad un’accelerazione negativa) ad un massimo di 511. Con un range di misura di ±2g, abbiamo che il valore massimo (511) corrisponde ad un’accelerazione di +2g. Tenendo l’accelerometro fermo perfettamente orizzontale, col il corpo rivolto verso l’alto, dobbiamo misurare un valore prossimo a zero lungo gli assi X e Y e un valore intorno a 255 lungo l’asse Z, che corrisponde al valore di 1g (accelerazione di gravità=9,8m/s2), difatti nelle prove ottengo una cosa del genere:

Per queste considerazioni vi rimando al completo articolo sugli accelerometri che ho scritto tempo fa.

Nelle nuove librerie I2C, disponibili solo ai collaboratori di settorezero nella sezione picmicro/librerie, ho inserito una funzione I2cBulkRead per eseguire la lettura sequenziale.

Download

Il download contiene unicamente il main, le librerie I2C vanno scaricate a parte.

Una demo più aggiornata che fa uso delle librerie I2C generate dall’MPLAB Code Configurator da MPLAB X IDE e che fa uso del compilatore XC8 è disponibile in questo articolo.

Se questo articolo ti è piaciuto, condividilo su un social:
Se l'articolo ti è piaciuto o ti è stato utile, potresti dedicare un minuto a leggere questa pagina, dove ho elencato alcune cose che potrebbero farmi contento? Grazie :)