BH1750. חיישן אור סביבה עם אוטובוס I2C.
ה-BH1750 הוא חיישן תאורת סביבה עם רזולוציה ורגישות גבוהה למדי. הוא מתנהג מול האור הנראה בצורה דומה לזו של העין האנושית ואינו מושפע מקרינת אינפרא אדומה ואינו תלוי בטמפרטורת הצבע של סוג התאורה, כלומר, הוא עובד היטב עם אור טבעי ועם סוגים שונים של תאורה מלאכותית. הוא מתקשר דיגיטלית עם המיקרו-בקר, עם אוטובוס I2C, כך שהוא עמיד בפני הפרעות אם הוא ממוקם במרחק מסוים מהמעגל שקורא אותו. זמן התגובה שלו נמוך למדי, פחות מ-200 אלפיות השנייה בנסיבות הכי לא טובות.
מנקודת מבט אלקטרונית, היישום שלו פשוט מאוד. פשוט חבר את המתח (בין 2,4V ל-3,6V) ואת אוטובוס I2C. לחלופין, ניתן לשנות את כתובת האוטובוס לחיבור שני התקנים (עם ADDR ברמה נמוכה הוא 0B0100011 או 0x23 ועם ADDR ברמה גבוהה הוא 0B1011100 או 0x5C) וניתן להשתמש בקו VDI עבור פונקציית האיפוס עם מיקרו-בקר.
כדי לחבר את BH1750 ל Arduino, בנוסף להיותו מופעל על ידי פלט 3,3 וולט, הכי נכון להשתמש בממיר רמות בנוסף ל- נגדים משיכה עבור אוטובוס I2C. למרות שהרכיב יתמוך בחיבור ישיר לאוטובוס אוטובוס I2C לא מומלץ להגדיל מעגל מבלי לשקול המרת הרמה.
בשל הפופולריות שלו, הנובעת מהיותו זול מאוד ביחס לדיוק שלו, ישנם מספר מודולים, כמו ה-GY-30 המוכר, אותו ניתן לראות בתצלום בהתחלה. כדי לחבר אותם בצורה נוחה יותר בעת יצירת אב טיפוס עם מיקרו-בקר, הם בדרך כלל כוללים ממירי רמה עבור אוטובוס I2C ווסת מתח כדי להפעיל אותם במתח גבוה יותר (עד 5V) במקום פלט 3,3V של Arduino.
ל-BH1750 שני מצבי קריאה, רציף ואינדיווידואלי, המתאימים לשני מצבים, פעיל ומתח נמוך או שינה. בעוד שאם נעשה שימוש במצב קריאה רציפה, ה-BH1750 נשאר פעיל לאחר הדגימה, לאחר ביצוע מדידה בודדת הוא נכנס אוטומטית למצב שינה וצריכת חשמל נמוכה. הקריאה הראשונה במצב רציף לוקחת לכל היותר 180 אלפיות השנייה ואחריה בין 16 אלפיות השנייה ל-120 שניות בהתאם לרזולוציה.
החיישן מסוגל למדוד במרווחים (רזולוציה) של 4 לוקס, 1 לוקס ו-0,5 לוקס. ה-BH1750 ממליץ בגיליון הנתונים שלו להשתמש ברזולוציה של 1 לוקס, המאפשרת להבחין בהארות מתחת ל-10 לוקס (המתאים לדמדומים) ואשר חסינה יותר לרעשים שעלולים להשפיע על המדידה.
הרזולוציות של 1 לוקס ו-4 לוקס משתמשות ב-16 סיביות הנתונים כדי לייצג את החלק השלם כך שניתן להשיג מדידה מקסימלית של 65535 לוקס (יום שמש ללא אור ישיר). מצב 0,5 לוקס משתמש בביט הפחות משמעותי עבור החלק העשרוני (נמדד מ-0,5 לוקס עד 0,5 לוקס) כך שעם 15 הסיביות הנותרים ניתן לייצג ערך מקסימלי של 32767 לוקס (חיצוני ללא אור ישיר)
בדרך כלל, החלון האופטי לפיו נמדד האור הסביבתי מתאים לכל הספקטרום הנראה והמטרה היא להשיג בו פיזור רגישות הדומה לזו של בני אדם. אם החלון האופטי מצטמצם (האור נמדד בטווח אורך גל נמוך יותר) ניתן להגביר את הרגישות של ה-BH1750 (עד 0,11 לוקס) עם מצב של ביטול כוונון ההשפעה של החלון האופטי על ידי הגדלת קריאת הזמן בפרופורציה. מכיוון שבמצב מיוחד (מגודל) זה נלקחות קריאות נפרדות, ההקשר חייב לאפשר זאת מבלי לשנות במיוחד את תנאי המדידה (לדוגמה, החיישן חייב להישאר יציב מאוד, אסור לו לעבור לאזור עם תנאי תאורה שונים)
BH1750 קודי פעולה
Estado
5>
-
0B00000000
(0x00
) צריכת חשמל נמוכה או מצב סרק. -
0B00000001
(0x01
) להדליק. -
0B00000111
(0x07
) איפוס. מנקה את יומני הנתונים של BH1750.
Resolución
5>
-
0B00010011
(0x13
) מדידה רציפה ברזולוציית 4 לוקס (בין 16 אלפיות השנייה לזמן קריאה) -
0B00010000
(0x10
) מדידה רציפה ברזולוציית 1 לוקס (זמן קריאה של 120 אלפיות השנייה) -
0B00010001
(0x11
) מדידה רציפה ברזולוציית 0,5 לוקס (זמן קריאה של 120 אלפיות השנייה) -
0B00100011
(0x23
) מדידה ברזולוציית 4 לוקס (זמן קריאה של 16 אלפיות השנייה) -
0B00100000
(0x20
) מדידה ברזולוציית 1 לוקס (זמן קריאה של 120 אלפיות השנייה) -
0B00100001
(0x21
) מדידה ברזולוציית 0,5 לוקס (זמן קריאה של 120 אלפיות השנייה)
התאמה לשינוי בחלון האופטי
5>
-
0B011MT
[0,1,2,3,4] סיביות נמוכה של ה-MTREG (REGISTER של זמן מדידה). -
0B01000MT
[5,6,7] ביט גבוה של רגיסטר 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, תתבקש להזין שני בתים (רזולוציה היא 16 סיביות) עם Wire.requestFrom()
שנקראים, באמצעות Wire.read()
, ונטענים למספר שלם ללא סימן, מסובבים את הבת הראשון ב-8 סיביות. האוטובוס משוחרר לאחר מכן עם 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 לוקס ומצב הקריאה רציף. הדוגמה מציגה, באמצעות הקונסולה הטורית 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 לוקס ו-4 לוקס משתמשים ב-16 סיביות הנתונים כדי לבטא את המדידה כמספר שלם. מצד שני, במצב 0,5 לוקס, הביט האחרון מייצג חלק עשרוני, כלומר, הערך שתורם למדידה הכוללת מוסט בחזקת שתיים ימינה. במצב 1 לוקס או 4 לוקס הסיביות האחרונה (LSB) שווה 20, 2 הלפני אחרון1, 2 הבאים2...במצב 0,5 לוקס הסיביות האחרונה (LSB) שווה 2-1, 2 הלפני אחרון0, 2 הבאים1...
לפי מבנה נתונים זה, ובהתחשב בכך שיש לבצע שתי קריאות I2C של בית, כדי לקבל את הערך של 16 סיביות יש לטעון את הסיביות המשמעותיות ביותר של הביט, הראשונים להיקרא, ולסובב אותם 8 סיביות שמאלה במצב רזולוציית 1 לוקס ובמצב רזולוציית 4 לוקס. רק 7 ביטים ב-0,5 לוקס. כדי לאחד את דרך הקריאה במצב 0,5 לוקס ניתן לטעון את הבת המשמעותי ביותר למספר שלם ללא סימן, לסובב 8 סיביות שמאלה, לטעון את הביט הפחות משמעותי ולסובב את כל המספר השלם ללא הסימן 1 סיביות שמאלה. ימינה, שימור הערך של החלק העשרוני המציין את LSB (מעט משמעותי) ליישם אותו מאוחר יותר.
באופן הגיוני, עבור מצבי לוקס 1 או 4 לוקס יש צורך להשתמש במספרים שלמים ללא סימנים (unsigned int
) בשביל מה Arduino לא לשמור את MSB (החלק המשמעותי ביותר) עבור הסימן ולהיות מסוגלים לפעול ישירות עם הערך האמיתי של המדידה, לא עם מספר שלילי. ב ארדואינו בשל לא הכרחי מכיוון שמספרים שלמים משתמשים ב-32 סיביות, אבל אותה תוכנית תעבוד גם אם משתמשים בה unsigned int
.
הקוד הבא מראה כיצד ישמש מצב 0,5 לוקס
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”);
}
}
}
|
הורד את המסמכים לדוגמאות של מדידת אור הסביבה עם חיישן BH1750 ו- Arduino.
לפרסם תגובה