Misurare l’intensità luminosa col sensore TSL2591
Il sensore TSL2591 permette di misurare l’intensità luminosa di un ambiente. Ha una buona capacità di campionamento ed in particolare permette con un solo sensore di rilevare sia lo spettro IR sia quello visibile. Il range di misurazione va da 188 Lux sino ad arrivare ad 88000 Lux (unità di misura Lux).
Nella figura seguente potete osservare il diagramma del circuito:
La conversione dei due canali viene eseguita contemporaneamente. Al termine del ciclo di conversione i dati vengono memorizzati nei relativi registri (CH0 Data e CH1 Data). Dopo la memorizzazione dei dati viene automaticamente eseguita la misurazione successiva.
Per questo tutorial ho acquistato questo articolo.
Il TSL2591 possiede anche due livelli di soglia programmabili (Upper Limit e Lower Limit) che generano un interrupt se il valore della misurazione dell’intensità di luce eccede questi limiti, una funzionalità importante per ottimizzare il campionamento in base alle condizioni di luminosità dell’ambiente.
Il collegamento del sensore con un microcontrollore avviene utilizzando il bus I2C, l’indirizzo del dispositivo nel bus è 0x29 e non può essere modificato via software, come accade con analoghi dispositivi.
L’interazione microcontrollore sensore avviene scrivendo e leggendo i registri del dispositivo.
Nonostante esista una libreria che semplifica l’interfacciamento, credo che sia interessante capire come accedere ai registri del TSL2591 utilizzando le semplici istruzioni della libreria Wire (bus i2C), questo per ottimizzare il codice in termini di dimensione e di prestazioni.
Sul datasheet sono presenti tutte le informazioni relative al TSL2591, tramite questo ‘manuale’ possiamo capire quali registri dobbiamo leggere e scrivere. La tabella seguente elenca tutti i registri del TSL2591, il loro indirizzo e le informazioni sulla loro funzione:
Il primo registro che dobbiamo conoscere e il COMMAND, più che un registro è il primo dato che inviamo al TSL2591 suil bus I2C, che permette successivamente di accedere ad un registro specifico (indirizzi da 0x00 a 0x17), nel dettaglio il COMMAND è così composto:
Il bit 7 deve essere impostato alto per poter rendere valido il commando. I bit 6 e 5 servono per definire l’uso dei bit da 0 a 4. Se i bit 6 e 5 vengono settati rispettivamente uno basso e uno alto, intendiamo accedere ad un indirizzo, se invece i bit 6 e 5 vengono impostati rispettivamente uno alto e uno basso, intendiamo specificare una funzione (maggiori dettagli sul datasheet del TSL2591).
Passiamo subito passare alla pratica per capire come funziona questo meccanismo. Andremmo a leggere il registro 0x12 che contiene l’identificativo del dispositivo, settato di default al valore 0x50.
Formiamo, usando la notazione binaria, il valore che deve avere il COMMAND. Il bit 7, abbiamo detto, deve essere messo a 1, i bit 6 e 5 devono essere 0 e 1 (poichè intendiamo scrivere nei bit da 0 a 4 un indirizzo e non abilitare una funzione) e i bit da 0 a 4 conterranno il valore del registro che voglio leggere o scrivere, in questo caso 0x12:
Se questo è corretto dal registro 0x12 dovremmo leggere il valore 0x50:
//inserisco la libreria I2C #include <Wire.h> void setup() { //Attivo la seriale Serial.begin(9600); //inizializzo la porta I2C Wire.begin(); //inizio la trasmissione specificando //l'indirizzo del TSL2591 Wire.beginTransmission(0x29); //invio sul bus il valore del registro COMMAND Wire.write(0b10110010); //termino la trasmissione Wire.endTransmission(); //richiedo al dispositivo il valore del registro //precedentemente selezionato Wire.requestFrom(0x29, 1); //leggo il valore del registro byte c = Wire.read(); //invio al serial monitor il dato letto Serial.print("0b"); Serial.print(c ,BIN); Serial.print(" 0x"); Serial.print(c ,HEX); } void loop() { delay(50); }
Aprendo il Serial Monitor otterremo il valore aspettato:
Questo è il meccanismo che permette di accedere ai registri del TLS2591. Ora andremo a recuperare i valori dei registri interessati alla memorizzazione dei canali ADC CH0 e CH1, relativi alla spettro visibile e alla spettro IR.
Prima di eseguire la lettura dai registri 0x14, 0x15, 0x16 e 0x17 (Che contengono appunto il valore della conversione ADC) è necessario configurare alcuni registri del dispositivo come l’ENABLE (0x00) e il CONFIG (0x01).
Il registro ENABLE (0X00) è così composto:
Permette di ‘accendere’ il dispositivo e di avviare l’ALS Data Register per memorizzare i dati provenienti dagli ADC. I bit 4, 6 e 7 servono per settare le funzioni di interrupt e power down. Per il momento non useremo questi bit.
Quindi i bit 0 e 1 vengono impostati a 1 mentre gli altri bit impostati a 0.
Il registro ENABLE avrà questo valore: 0b00000011.
Un altro registro da configurare, prima di eseguire la lettura dai registri 0x14-0x17 e il CONTROL (0x01):
Questo registro ci permette di selezionare tramite i bit 4 e 5 il guadagno dell’integratore dei due canali. Il valore del AGAIN permette di variare la sensibilità del sensore in base alle condizioni di luce, se andiamo a misurare ambienti molto luminosi useremmo un basso guadagno, viceversa in ambienti bui ne potremmo aumenteremmo il guadagno.
Stesso discorso vale per il tempo di acquisizione, integration time ATIM, per ambienti luminosi potremmo impostare un basso tempo di integrazione (100 ms) mentre per ambienti poco luminosi un alto valore di integrazione (600ms).
Il bit 7 va impostato a zero, altrimenti otterremo il reset del dispositivo.
Impostiamo SRESET a uno (bit 7), AGAIN a 01 (medium Gain Mode) e ATIME a 100ms. Il registro avrà quindi questo valore 0b00010000.
Ora non ci resta che leggere i 4 byte dei registri 0x14-0x17, per recuperare i dati relativi alla conversione dello spettro visibile e IR:
//carico libreria i2c #include <Wire.h> void setup() { //init seriale Serial.begin(9600); //inizializzo la porta I2C della Arduino Wire.begin(); delay(100); Wire.beginTransmission(0x29); Wire.write(0b10110010);//10110010 Wire.endTransmission(); Wire.requestFrom(0x29, 1); byte c = Wire.read(); Serial.print("0b"); Serial.print(c ,BIN); Serial.print(" 0x"); Serial.print(c ,HEX); //attiva il tsl2195 Wire.beginTransmission(0x29); //attiva seleziono il registro 0x00 (enable) Wire.write(0b10100000); //attiva Wire.write(0b00000011); Wire.endTransmission(); //configuro il sensore gain e timing Wire.beginTransmission(0x29); //seleziono il registro 0x01 (Control) Wire.write(0b10100001); //imposto reset a 0 gain a 01 e timing a 000 Wire.write(0b00010000); Wire.endTransmission(); Wire.beginTransmission(0x29); //seleziono il registro 0x14 Wire.write(0b10110100); Wire.endTransmission(); } void loop() { //attendo almeno 100ms tra una lettura e l'altra delay(500); //leggo i dati dal registro 0x14 0x15 0x16 e 0x17 Wire.requestFrom(0x29, 4); byte ByteLowVIS = Wire.read(); byte ByteHighVIS = Wire.read(); byte ByteLowIR = Wire.read(); byte ByteHighIR = Wire.read(); int valore = 0; //unisco i due byte del registro //0x14 con il registro 0x15 valore = ByteHighVIS; valore <<= 8; valore |= ByteLowVIS; //invio il dato al serial monitor //luce visibile (CH0) Serial.print("LUCE VISIBILE "); Serial.println(valore); valore = 0; //unisco i due byte del registro //0x16 con il registro 0x17 valore = ByteHighIR; valore <<= 8; valore |= ByteLowIR; //invio il dato al serial monitor //luce IR (CH1) Serial.print("LUCE IR "); Serial.println(valore); }
Caricando il codice otterremo l’acquisizione dei dati:
I risultati ottenuti sono valori grezzi che vengono recuperati direttamente dai registri di conversione. Tramite questi dati possiamo calcolare il valore della luminosità espresso in Lux oppure considerarli come semplici variazioni numeriche.
Related posts
Articoli popolari
Sorry. No data so far.
.Net micro framework Arduino Arduino Webserver Domotica Flyport I2C IOT Netduino OpenPicus raspberry RTC Speed Test