BH1750. เซ็นเซอร์วัดแสงโดยรอบพร้อมบัส I2C
BH1750 เป็นเซ็นเซอร์วัดแสงโดยรอบที่มีความละเอียดและความไวสูงพอสมควร มีพฤติกรรมเมื่อเผชิญกับแสงที่มองเห็นได้ในลักษณะเทียบเคียงกับดวงตามนุษย์ และไม่ได้รับผลกระทบจากรังสีอินฟราเรดและไม่ขึ้นอยู่กับอุณหภูมิสีของประเภทของแสง กล่าวคือ ทำงานได้ดีกับแสงธรรมชาติและกับ แสงประดิษฐ์ประเภทต่างๆ มันสื่อสารแบบดิจิทัลกับไมโครคอนโทรลเลอร์ด้วย บัส I2Cดังนั้นจึงทนทานต่อการรบกวนหากวางไว้ที่ระยะห่างจากวงจรที่อ่านค่า เวลาตอบสนองค่อนข้างต่ำ น้อยกว่า 200 ms ในสถานการณ์ที่ไม่พึงประสงค์ที่สุด
จากมุมมองทางอิเล็กทรอนิกส์ การใช้งานนั้นง่ายมาก เพียงเชื่อมต่อไฟ (ระหว่าง 2,4V ถึง 3,6V) และ บัส I2C. ทางเลือก สามารถเปลี่ยนที่อยู่บัสเพื่อเชื่อมต่ออุปกรณ์สองตัวได้ (โดย ADDR ในระดับต่ำคือ 0B0100011 หรือ 0x23 และด้วย ADDR ที่ระดับสูงคือ 0B1011100 หรือ 0x5C) และสามารถใช้สาย VDI สำหรับฟังก์ชันรีเซ็ตด้วย ไมโครคอนโทรลเลอร์
เพื่อเชื่อมต่อ BH1750 เข้ากับ แพลตฟอร์มฮาร์ดแวร์นอกเหนือจากการจ่ายไฟจากเอาต์พุต 3,3 V แล้ว การใช้ตัวแปลงระดับนอกเหนือจาก ตัวต้านทานแบบดึงขึ้น สำหรับ บัส I2C. แม้ว่าส่วนประกอบจะรองรับการเชื่อมต่อโดยตรงกับบัสก็ตาม บัส I2C ไม่แนะนำให้ปรับขนาดวงจรโดยไม่คำนึงถึงการแปลงระดับ
เนื่องจากความนิยมซึ่งเนื่องจากมีราคาถูกมากเมื่อเทียบกับความแม่นยำ จึงมีหลายโมดูล เช่น GY-30 ที่รู้จักกันดี ซึ่งสามารถเห็นได้ในรูปถ่ายตอนเริ่มต้น เพื่อเชื่อมต่อได้สะดวกยิ่งขึ้นเมื่อสร้างต้นแบบด้วยไมโครคอนโทรลเลอร์ โดยปกติแล้วจะรวมตัวแปลงระดับไว้ด้วย บัส I2C และตัวควบคุมแรงดันไฟฟ้าเพื่อจ่ายไฟด้วยแรงดันไฟฟ้าที่สูงกว่า (สูงถึง 5V) แทนที่จะเป็นเอาต์พุต 3,3V ของ แพลตฟอร์มฮาร์ดแวร์.
BH1750 มีโหมดการอ่านสองโหมด โหมดต่อเนื่องและโหมดเดี่ยว ซึ่งสอดคล้องกับสองสถานะ คือ ใช้งานและพลังงานต่ำ หรือโหมดสลีป แม้ว่าจะใช้โหมดการอ่านต่อเนื่อง BH1750 จะยังคงทำงานอยู่หลังจากการสุ่มตัวอย่าง หลังจากดำเนินการวัดค่าเดี่ยวแล้ว BH180 จะเข้าสู่โหมดสลีปและโหมดพลังงานต่ำโดยอัตโนมัติ การอ่านครั้งแรกในโหมดต่อเนื่องจะใช้เวลาสูงสุด 16 ms และการอ่านครั้งถัดไประหว่าง 120 ms ถึง XNUMX ms ขึ้นอยู่กับความละเอียด
เซ็นเซอร์สามารถวัดตามช่วงเวลา (ความละเอียด) 4 ลักซ์, 1 ลักซ์ และ 0,5 ลักซ์ BH1750 แนะนำในเอกสารข้อมูลให้ใช้ความละเอียด 1 ลักซ์ ซึ่งช่วยให้แยกแยะความสว่างที่ต่ำกว่า 10 ลักซ์ได้ (ซึ่งตรงกับเวลาพลบค่ำ) และมีภูมิคุ้มกันต่อเสียงรบกวนที่อาจส่งผลต่อการวัดได้มากกว่า
ความละเอียด 1 lux และ 4 lux ใช้ข้อมูล 16 บิตเพื่อแสดงส่วนจำนวนเต็ม จึงสามารถวัดค่าได้สูงสุด 65535 lux (วันที่มีแดดจ้าโดยไม่มีแสงส่องโดยตรง) โหมด 0,5 ลักซ์ใช้บิตที่มีนัยสำคัญน้อยที่สุดสำหรับส่วนทศนิยม (วัดจาก 0,5 ลักซ์ถึง 0,5 ลักซ์) ดังนั้นด้วยบิตที่เหลือ 15 บิตจึงเป็นไปได้ที่จะแสดงค่าสูงสุด 32767 ลักซ์ (ภายนอกโดยไม่มีแสงโดยตรง)
โดยปกติ หน้าต่างแสงที่ใช้วัดแสงโดยรอบจะสอดคล้องกับสเปกตรัมที่มองเห็นได้ทั้งหมด และมีเป้าหมายเพื่อให้เกิดการกระจายความไวในสเปกตรัมที่เทียบได้กับสเปกตรัมของมนุษย์ หากช่องแสงลดลง (วัดแสงในช่วงความยาวคลื่นที่ต่ำกว่า) ความไวของ BH1750 จะเพิ่มขึ้น (สูงสุด 0,11 ลักซ์) ด้วยโหมดการยกเลิกการปรับอิทธิพลของหน้าต่างแสงโดยการเพิ่มเวลาที่อ่านได้ ตามสัดส่วน เนื่องจากในโหมดพิเศษ (ขนาดใหญ่) นี้ จะมีการอ่านค่าแยกกัน บริบทจะต้องอนุญาตโดยไม่ต้องเปลี่ยนแปลงเงื่อนไขการวัดเป็นพิเศษ (เช่น เซ็นเซอร์จะต้องคงความเสถียรมาก จะต้องไม่เคลื่อนไปยังพื้นที่ที่มีสภาพแสงแตกต่างกัน)
รหัสการดำเนินงาน BH1750
Estado
5>
-
0B00000000
(0x00
) พลังงานต่ำหรือโหมดไม่ได้ใช้งาน -
0B00000001
(0x01
) เปิด. -
0B00000111
(0x07
) รีเซ็ต ล้างบันทึกข้อมูล BH1750
ความละเอียด
5>
-
0B00010011
(0x13
) การวัดต่อเนื่องที่ความละเอียด 4 ลักซ์ (ระหว่าง 16 ms และเวลาในการอ่าน) -
0B00010000
(0x10
) การวัดต่อเนื่องที่ความละเอียด 1 ลักซ์ (เวลาในการอ่าน 120 ms) -
0B00010001
(0x11
) การวัดต่อเนื่องที่ความละเอียด 0,5 ลักซ์ (เวลาในการอ่าน 120 ms) -
0B00100011
(0x23
) การวัดที่ความละเอียด 4 ลักซ์ (เวลาในการอ่าน 16 ms) -
0B00100000
(0x20
) การวัดที่ความละเอียด 1 ลักซ์ (เวลาในการอ่าน 120 ms) -
0B00100001
(0x21
) การวัดที่ความละเอียด 0,5 ลักซ์ (เวลาในการอ่าน 120 ms)
การปรับการเปลี่ยนแปลงในหน้าต่างออปติคอล
5>
-
0B011MT
[0,1,2,3,4] รีจิสเตอร์ MTREG (Measurement Time REGister) บิตต่ำ -
0B01000MT
[5,6,7] MTREG ลงทะเบียนบิตสูง
อ่าน BH1750 จาก Arduino
เพื่อวัดแสงโดยรอบด้วย BH1750 จาก แพลตฟอร์มฮาร์ดแวร์ ห้องสมุดถูกใช้ ลวด ที่จัดการการสื่อสารกับ บัส 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 สะดวกสบายยิ่งขึ้นค่ะ แพลตฟอร์มฮาร์ดแวร์รหัสการดำเนินการที่เกี่ยวข้องมากที่สุดจะพบได้ในเอกสารส่วนหัวต่อไปนี้
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 ลักซ์ และโหมดการอ่านต่อเนื่อง ตัวอย่างนี้แสดงโดยใช้คอนโซลอนุกรม แพลตฟอร์มฮาร์ดแวร์แต่ละผลลัพธ์ที่ได้มาจากค่าที่วัดได้
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 lux หรือ 4 lux บิตสุดท้าย (LSB) มีค่าเท่ากับ 20, สุดท้าย 21, 2 ถัดไป2…ในโหมด 0,5 lux บิตสุดท้าย (LSB) มีค่าเท่ากับ 2-1, สุดท้าย 20, 2 ถัดไป1...
ตามโครงสร้างข้อมูลนี้ และพิจารณาว่าต้องทำการอ่านสองครั้ง I2C ของไบต์ เพื่อให้ได้ค่า 16 บิต คุณต้องโหลดบิตที่สำคัญที่สุดของไบต์ บิตแรกที่จะอ่าน และหมุนไปทางซ้าย 8 บิตในโหมดความละเอียด 1 ลักซ์ และในโหมดความละเอียด 4 ลักซ์ และ เพียง 7 บิตใน 0,5 ลักซ์ หากต้องการรวมวิธีการอ่านในโหมด 0,5 ลักซ์ คุณสามารถโหลดไบต์ที่สำคัญที่สุดลงในจำนวนเต็มที่ไม่ได้ลงนาม หมุน 8 บิตไปทางซ้าย โหลดไบต์ที่มีนัยสำคัญน้อยที่สุดแล้วหมุนจำนวนเต็มที่ไม่ได้ลงนามทั้งหมดไปทางซ้าย 1 บิต ขวา เก็บรักษา ค่าของส่วนทศนิยมที่บ่งชี้ถึง LSB (บิตที่มีนัยสำคัญน้อยที่สุด) เพื่อนำไปใช้ในภายหลัง
ตามตรรกะ สำหรับโหมด 1 ลักซ์หรือ 4 ลักซ์ จำเป็นต้องใช้จำนวนเต็มที่ไม่ได้ลงนาม (unsigned int
) เพื่ออะไร แพลตฟอร์มฮาร์ดแวร์ อย่าจอง MSB (บิตที่สำคัญที่สุด) สำหรับเครื่องหมายและสามารถดำเนินการโดยตรงกับค่าที่แท้จริงของการวัดไม่ใช่จำนวนลบ ใน Arduino เนื่องจาก ไม่จำเป็นเนื่องจากจำนวนเต็มใช้ 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.
แสดงความคิดเห็น