BH1750. Αισθητήρας φωτός περιβάλλοντος με δίαυλο I2C.
Ο BH1750 είναι ένας αισθητήρας φωτισμού περιβάλλοντος με αρκετά υψηλή ανάλυση και ευαισθησία. Συμπεριφέρεται μπροστά στο ορατό φως με τρόπο συγκρίσιμο με αυτό του ανθρώπινου ματιού και δεν επηρεάζεται από την υπέρυθρη ακτινοβολία ούτε εξαρτάται από τη θερμοκρασία χρώματος του τύπου φωτισμού, δηλαδή λειτουργεί καλά με φυσικό φως και με διαφορετικών τύπων τεχνητού φωτισμού. Επικοινωνεί ψηφιακά με τον μικροελεγκτή, με το Δίαυλος I2C, άρα είναι ανθεκτικό σε παρεμβολές αν τοποθετηθεί σε συγκεκριμένη απόσταση από το κύκλωμα που το διαβάζει. Ο χρόνος απόκρισής του είναι αρκετά χαμηλός, λιγότερο από 200 ms στις πιο δυσμενείς συνθήκες.
Από ηλεκτρονικής πλευράς η εφαρμογή του είναι πολύ απλή. Απλώς συνδέστε το ρεύμα (μεταξύ 2,4 V και 3,6 V) και το Δίαυλος I2C. Προαιρετικά, η διεύθυνση διαύλου μπορεί να αλλάξει για τη σύνδεση δύο συσκευών (με ADDR σε χαμηλό επίπεδο είναι 0B0100011 ή 0x23 και με ADDR σε υψηλό επίπεδο είναι 0B1011100 ή 0x5C) και η γραμμή VDI μπορεί να χρησιμοποιηθεί για τη λειτουργία επαναφοράς με το μικροελεγκτή.
Για να συνδέσετε το BH1750 στο Arduino, εκτός από το ότι τροφοδοτείται από την έξοδο 3,3 V, είναι πιο σωστό να χρησιμοποιείτε έναν μετατροπέα στάθμης επιπλέον του αντιστάσεις έλξης για Δίαυλος I2C. Αν και το εξάρτημα θα υποστηρίζει απευθείας σύνδεση με το δίαυλο Δίαυλος I2C Δεν είναι σκόπιμο να διαστασιολογήσετε ένα κύκλωμα χωρίς να σκεφτείτε τη μετατροπή της στάθμης.
Λόγω της δημοτικότητάς του, που οφείλεται στο ότι είναι πολύ φθηνό σε σχέση με την ακρίβειά του, υπάρχουν αρκετές μονάδες, όπως το γνωστό GY-30, που φαίνεται στην φωτογραφία στην αρχή. Για να τα συνδέσετε πιο άνετα όταν κάνετε πρωτότυπα με μικροελεγκτή, συνήθως περιλαμβάνουν μετατροπείς στάθμης για το Δίαυλος I2C και ρυθμιστές τάσης για να τα τροφοδοτούν με υψηλότερη τάση (έως 5 V) αντί για την έξοδο 3,3 V του Arduino.
Το BH1750 έχει δύο λειτουργίες ανάγνωσης, συνεχή και μεμονωμένη, που αντιστοιχούν σε δύο καταστάσεις, ενεργή και χαμηλή ισχύ ή ύπνο. Ενώ εάν χρησιμοποιηθεί η λειτουργία συνεχούς ανάγνωσης, το BH1750 παραμένει ενεργό μετά τη δειγματοληψία, μετά την εκτέλεση μιας μεμονωμένης μέτρησης μπαίνει αυτόματα σε λειτουργία ύπνου και χαμηλής κατανάλωσης. Η πρώτη ανάγνωση σε συνεχή λειτουργία διαρκεί το πολύ 180 ms και οι επόμενες μεταξύ 16 ms και 120 ms, ανάλογα με την ανάλυση.
Ο αισθητήρας έχει τη δυνατότητα μέτρησης σε διαστήματα (ανάλυση) 4 lux, 1 lux και 0,5 lux. Το BH1750 συνιστά στο φύλλο δεδομένων του τη χρήση της ανάλυσης 1 lux, η οποία επιτρέπει τη διάκριση φωτισμών κάτω των 10 lux (που αντιστοιχεί στο λυκόφως) και είναι πιο απρόσβλητος στον θόρυβο που θα μπορούσε να επηρεάσει τη μέτρηση.
Οι αναλύσεις 1 lux και 4 lux χρησιμοποιούν τα 16 bit δεδομένων για να αναπαραστήσουν το ακέραιο τμήμα, ώστε να μπορεί να επιτευχθεί μέγιστη μέτρηση 65535 lux (ηλιόλουστη μέρα χωρίς άμεσο φως). Η λειτουργία 0,5 lux χρησιμοποιεί το λιγότερο σημαντικό bit για το δεκαδικό μέρος (μετράει από 0,5 lux έως 0,5 lux), επομένως με τα υπόλοιπα 15 bit είναι δυνατό να αντιπροσωπευτεί μια μέγιστη τιμή 32767 lux (εξωτερικό χωρίς άμεσο φως)
Κανονικά, το οπτικό παράθυρο σύμφωνα με το οποίο μετράται το φως του περιβάλλοντος αντιστοιχεί σε ολόκληρο το ορατό φάσμα και ο στόχος είναι να επιτευχθεί μια κατανομή ευαισθησίας σε αυτό συγκρίσιμη με αυτή των ανθρώπων. Εάν το οπτικό παράθυρο μειωθεί (το φως μετριέται σε χαμηλότερο εύρος μήκους κύματος), η ευαισθησία του BH1750 μπορεί να αυξηθεί (έως 0,11 lux) με μια λειτουργία ακύρωσης της προσαρμογής της επίδρασης του οπτικού παραθύρου αυξάνοντας την ένδειξη του χρόνου σε αναλογία. Εφόσον σε αυτήν την ειδική (υπερμεγέθη) λειτουργία λαμβάνονται ξεχωριστές μετρήσεις, το περιβάλλον πρέπει να το επιτρέπει χωρίς να αλλάζει ιδιαίτερα τις συνθήκες μέτρησης (για παράδειγμα, ο αισθητήρας πρέπει να παραμένει πολύ σταθερός, να μην μετακινείται σε περιοχή με διαφορετικές συνθήκες φωτισμού)
BH1750 Κωδικοί Λειτουργίας
Estado
5>
-
0B00000000
(0x00
) Χαμηλή ισχύς ή κατάσταση αδράνειας. -
0B00000001
(0x01
) Αναμμένο. -
0B00000111
(0x07
) Επαναφορά. Διαγράφει τα αρχεία καταγραφής δεδομένων BH1750.
Ανάλυση
5>
-
0B00010011
(0x13
) Συνεχής μέτρηση σε ανάλυση 4 lux (μεταξύ 16 ms και χρόνου ανάγνωσης) -
0B00010000
(0x10
) Συνεχής μέτρηση σε ανάλυση 1 lux (χρόνος ανάγνωσης 120 ms) -
0B00010001
(0x11
) Συνεχής μέτρηση σε ανάλυση 0,5 lux (χρόνος ανάγνωσης 120 ms) -
0B00100011
(0x23
) Μια μέτρηση σε ανάλυση 4 lux (χρόνος ανάγνωσης 16 ms) -
0B00100000
(0x20
) Μια μέτρηση σε ανάλυση 1 lux (χρόνος ανάγνωσης 120 ms) -
0B00100001
(0x21
) Μια μέτρηση σε ανάλυση 0,5 lux (χρόνος ανάγνωσης 120 ms)
Ρύθμιση για αλλαγή σε οπτικό παράθυρο
5>
-
0B011MT
[0,1,2,3,4] Χαμηλό bit του καταχωρητή MTREG (Measurement Time REGister). -
0B01000MT
[5,6,7] Υψηλό bit καταχωρητή MTREG.
Διαβάστε το BH1750 από το Arduino
Για τη μέτρηση του φωτισμού περιβάλλοντος με το BH1750 από Arduino χρησιμοποιείται η βιβλιοθήκη Σύρμα που διαχειρίζεται τις επικοινωνίες με το Δίαυλος I2C. Η διαδικασία είναι η συνηθισμένη σε αυτόν τον τύπο επικοινωνίας, πρώτα ενεργοποιούνται (μία φορά στο πρόγραμμα) με Wire.begin()
, η επικοινωνία με το BH1750 ξεκινά με Wire.beginTransmission()
και τη διεύθυνσή σας I2C (0x5C ή 0x23 ανάλογα με το αν το ADDR είναι υψηλό ή χαμηλό αντίστοιχα), διαμορφώνεται στέλνοντας τον αντίστοιχο κωδικό με Wire.write()
και το λεωφορείο απελευθερώνεται με Wire.endTransmission()
15
|
Wire.begin();
|
17
18
19
|
Wire.beginTransmission(DIRECCION_BH1750_0);
Wire.write(MEDIDA_CONTINUA_UN_LUX_BH1750);
Wire.endTransmission();
|
Εάν χρησιμοποιείται μία από τις λειτουργίες συνεχούς ανάγνωσης, η Wire.beginTransmission() χρησιμοποιείται για τη λήψη των δεδομένων με τη διεύθυνση I2C που αντιστοιχεί στην πρόσβαση στο BH1750, σας ζητούνται δύο byte (η ανάλυση είναι 16 bit) με Wire.requestFrom()
που διαβάζονται, χρησιμοποιώντας Wire.read()
, και φορτώνονται σε έναν ανυπόγραφο ακέραιο, περιστρέφοντας το πρώτο byte κατά 8 bit. Το λεωφορείο στη συνέχεια απελευθερώνεται με Wire.endTransmission()
. Το τελικό αποτέλεσμα προκύπτει διαιρώντας την επιστρεφόμενη τιμή με τον συντελεστή ακριβείας (1,2 εάν δεν αλλάξει το οπτικό παράθυρο)
28
29
|
Wire.beginTransmission(DIRECCION_BH1750_0);
Wire.requestFrom(DIRECCION_BH1750_0,2);
|
37
38
|
lectura_BH1750=Wire.read()<<8; // Leer el primer byte y rotarlo 8 bits
lectura_BH1750|=Wire.read(); // Leer el segundo byte y «juntarlo» con el anterior on OR
|
40
|
iluminacion=long(100.0*(float)lectura_BH1750/DIVISOR_PRECISION)/100; // Resultado corregido y sin decimales
|
Εάν χρησιμοποιείται η λειτουργία μεμονωμένων μετρήσεων, το BH1750 εισέρχεται σε κατάσταση αναστολής λειτουργίας Για να επιστρέψετε στην ενεργή λειτουργία, μπορεί να σταλεί μια διαμόρφωση (η ίδια λειτουργία ανάγνωσης ή μια νέα) ή ο κωδικός ενεργοποίησης (0x01). Ο κωδικός τερματισμού λειτουργίας (1750x0) μπορεί να χρησιμοποιηθεί για να εξαναγκάσει το BH00 σε κατάσταση αναστολής λειτουργίας.
Είναι σημαντικό να τηρείτε τον χρόνο ανάγνωσης του αισθητήρα, ο οποίος εξαρτάται από την ανάλυση. Εάν η αναμονή δεν είναι κρίσιμη, μπορεί να ενοποιηθεί σε μια τιμή για όλες τις περιπτώσεις που μπορεί να είναι ελαφρώς μεγαλύτερη από το αναμενόμενο μέγιστο για να διασφαλιστεί ότι η ανάγνωση θα ολοκληρωθεί.
Για να γίνει πιο άνετη η εγγραφή κώδικα για το BH1750 Arduino, οι πιο σχετικοί κωδικοί λειτουργίας βρίσκονται στο παρακάτω έγγραφο κεφαλίδας.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
#define REPOSAR_BH1750 0x00 // Modo de reposo o bajo consumo
#define ENCENDER_BH1750 0x01
#define RESETEAR_BH1750 0x07
#define MEDIDA_CONTINUA_CUATRO_LUX_BH1750 0x13
#define MEDIDA_CONTINUA_UN_LUX_BH1750 0x10
#define MEDIDA_CONTINUA_MEDIO_LUX_BH1750 0x11
#define MEDIDA_SIMPLE_CUATRO_LUX_BH1750 0x23
#define MEDIDA_SIMPLE_UN_LUX_BH1750 0x20
#define MEDIDA_SIMPLE_MEDIO_LUX_BH1750 0x21
#define ESPERA_BH1750_0 250 // 250 milisegundos de espera de lectura del BH1750 (mayor que la máxima)
#define TIMEOUT_I2C 10 // 10 milisegundos de espera antes de renunciar a leer el bus I2C
#define DIVISOR_PRECISION 1.2 // valor por el que dividir la lectura para calcular la luminosidad 1.2 si no hay cambios en la ventana óptica
#define DIRECCION_BH1750_0 0x23
#define DIRECCION_BH1750_1 0x5C
|
Το ακόλουθο παράδειγμα κώδικα δείχνει την πιο κοινή λειτουργία ανάγνωσης στον αισθητήρα φωτός I2C BH1750. Η ανάλυση είναι 1 lux και η λειτουργία ανάγνωσης είναι συνεχής. Το παράδειγμα δείχνει, χρησιμοποιώντας τη σειριακή κονσόλα Arduino, κάθε αποτέλεσμα που προκύπτει από τη μετρούμενη τιμή.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
#include “BH1750.h” // Cargar los códigos de operación del BH1750
#include <Wire.h>
unsigned int lectura_BH1750;
unsigned int iluminacion;
//float iluminacion; // Mostrar el valor con decimales
long cronometro_lecturas=0;
long tiempo_transcurrido;
long cronometro_timeout_i2c;
void setup()
{
Serial.begin(9600);
Wire.begin();
delay(ESPERA_BH1750_0); // Espera inicial para estabilizar el BH1750
Wire.beginTransmission(DIRECCION_BH1750_0);
Wire.write(MEDIDA_CONTINUA_UN_LUX_BH1750);
Wire.endTransmission();
}
void loop()
{
tiempo_transcurrido=millis()–cronometro_lecturas;
if(tiempo_transcurrido>ESPERA_BH1750_0)
{
cronometro_lecturas=millis();
Wire.beginTransmission(DIRECCION_BH1750_0);
Wire.requestFrom(DIRECCION_BH1750_0,2);
do
{
tiempo_transcurrido=millis()–cronometro_timeout_i2c;
}
while(Wire.available()<2&&tiempo_transcurrido<TIMEOUT_I2C);
if(Wire.available()>1)
{
lectura_BH1750=Wire.read()<<8; // Leer el primer byte y rotarlo 8 bits
lectura_BH1750|=Wire.read(); // Leer el segundo byte y «juntarlo» con el anterior on OR
//iluminacion=lectura_BH1750/DIVISOR_PRECISION; // Resultado corregido y con decimales (mínimamente más preciso pero menos legible)
iluminacion=long(100.0*(float)lectura_BH1750/DIVISOR_PRECISION)/100; // Resultado corregido y sin decimales
Serial.print(“La iluminación es de “);
Serial.print(iluminacion);
Serial.println(” lux”);
}
}
}
|
Όπως είπα παραπάνω, και οι δύο λειτουργίες ανάλυσης 1 lux και 4 lux χρησιμοποιούν τα 16 bit δεδομένων για να εκφράσουν τη μέτρηση ως ακέραιο. Από την άλλη πλευρά, στη λειτουργία 0,5 lux, το τελευταίο bit αντιπροσωπεύει ένα δεκαδικό μέρος, δηλαδή, η τιμή που συμβάλλει στη συνολική μέτρηση μετατοπίζεται κατά μια ισχύ δύο προς τα δεξιά. Σε λειτουργία 1 lux ή 4 lux το τελευταίο κομμάτι (LSB) αξίζει 20, το προτελευταίο 21, τα επόμενα 22…σε λειτουργία 0,5 lux το τελευταίο κομμάτι (LSB) αξίζει 2-1, το προτελευταίο 20, τα επόμενα 21...
Σύμφωνα με αυτή τη δομή δεδομένων, και λαμβάνοντας υπόψη ότι πρέπει να πραγματοποιηθούν δύο μετρήσεις I2C ενός byte, για να λάβετε την τιμή των 16 bit, πρέπει να φορτώσετε τα πιο σημαντικά bit του byte, τα πρώτα προς ανάγνωση, και να τα περιστρέψετε 8 bit προς τα αριστερά σε λειτουργία ανάλυσης 1 lux και σε λειτουργία ανάλυσης 4 lux και μόνο 7 bit στο 0,5 lux. Για να ενοποιήσετε τον τρόπο ανάγνωσης στη λειτουργία 0,5 lux, μπορείτε να φορτώσετε το πιο σημαντικό byte σε έναν ανυπόγραφο ακέραιο, να περιστρέψετε 8 bit προς τα αριστερά, να φορτώσετε το λιγότερο σημαντικό byte και να περιστρέψετε ολόκληρο τον ανυπόγραφο ακέραιο αριθμό 1 bit προς τα αριστερά, διατηρώντας την τιμή του δεκαδικού μέρους που δηλώνει το LSB (λιγότερο σημαντικό bit) για να το εφαρμόσετε αργότερα.
Λογικά, για λειτουργίες 1 lux ή 4 lux είναι απαραίτητο να χρησιμοποιηθούν ακέραιοι αριθμοί χωρίς υπογραφή (unsigned int
) για ποιο λόγο Arduino μην κρατήσετε το MSB (πιο σημαντικό bit) για το πρόσημο και να μπορεί να λειτουργεί απευθείας με την πραγματική τιμή της μέτρησης, όχι με αρνητικό αριθμό. Σε Arduino λόγω δεν είναι απαραίτητο αφού οι ακέραιοι χρησιμοποιούν 32 bit, αλλά το ίδιο πρόγραμμα θα λειτουργήσει επίσης αν χρησιμοποιηθεί επίσης unsigned int
.
Ο παρακάτω κώδικας δείχνει πώς θα χρησιμοποιηθεί η λειτουργία 0,5 lux
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
#include “BH1750.h” // Cargar los códigos de operación del BH1750
#include <Wire.h>
unsigned int lectura_BH1750;
//unsigned int iluminacion;
float iluminacion; // Mostrar el valor con decimales
long cronometro_lecturas=0;
long tiempo_transcurrido;
long cronometro_timeout_i2c;
bool parte_decimal;
void setup()
{
Serial.begin(9600);
Wire.begin();
delay(ESPERA_BH1750_0); // Espera inicial para estabilizar el BH1750
Wire.beginTransmission(DIRECCION_BH1750_0);
Wire.write(MEDIDA_CONTINUA_MEDIO_LUX_BH1750);
Wire.endTransmission();
}
void loop()
{
tiempo_transcurrido=millis()–cronometro_lecturas;
if(tiempo_transcurrido>ESPERA_BH1750_0)
{
cronometro_lecturas=millis();
Wire.beginTransmission(DIRECCION_BH1750_0);
Wire.requestFrom(DIRECCION_BH1750_0,2);
do
{
tiempo_transcurrido=millis()–cronometro_timeout_i2c;
}
while(Wire.available()<2&&tiempo_transcurrido<TIMEOUT_I2C);
if(Wire.available()>1)
{
lectura_BH1750=Wire.read()<<8; // Leer el primer byte y rotarlo 8 bits
lectura_BH1750|=Wire.read(); // Leer el segundo byte y «juntarlo» con el anterior on OR
parte_decimal=(lectura_BH1750<<15)>0;
lectura_BH1750>>=1;
iluminacion=((float)lectura_BH1750+(parte_decimal?0.5:0.0))/DIVISOR_PRECISION;
Serial.print(“La iluminación es de “);
Serial.print(iluminacion);
Serial.println(” lux”);
}
}
}
|
Δημοσίευση σχολίου