Hardware | BH1750FVI Light Intensity Sensor 간단 사용기



1. Lux

아래 그림을 보면, Lux 라는 것은 표면적에 받는 광량 정도 될 듯 합니다.


Lumen 과 Lux 의 차이를 보면, 광원의 세기를 Lumen 이라고 하고, 단위 면적 당 빛의 세기를 Lux 라고 정의하면 될 듯 하네요.


참고로, 우리가 일상에서 느끼는 광량을 Lux 로 표현하면 다음과 같습니다.


집 안에서의 밝기를 Lux 광량으로 보면, 다음과 같습니다. 100 - 300 정도가 눈의 피로 면에서는 적당할 듯 합니다.




2. BH1750FVI

위의 Lux 이야기를 한 이유는, 어쩌다 얻게 된 Digital Ambient Light Intensity Sensor Module 을 다루기 위해서 입니다. 기술적인 내용은 아래 사이트를 참고 하였습니다. (지금 방문해 보니, 이상한 사이트로 점프하네요. 주의 하시길!)

* Using the BH1750 (GY-30) Sensor with Arduino

HB1750 (GY-30) 의 기술 스펙은 다음과 같습니다.

GY-30 BH1750FVI Digital Ambient Light Intensity Sensor Module

* 16 bit lux sensor
* I2C interface with readout in Lux
* 6-pin male header
* detect a wide range from 0.11 ~ 100000 lux
* visible light sensitivity with peak at 560nm
* ± 45 degree angle of sensitivity to 50%
* 50/60Hz light noise rejection
* compatible with most white light sources
* ± 20% measurement variation
* sensor operating voltage : 2.4 ~ 3.6V
* On-board 3.3V regulator and logic level translators
* 3.3 and 5V compatible

특이하게도, 이 모듈은 3가지 mode 가 존재하며, 특별히 지정하지 않으면 HIGH 인 상태이고, 지정을 하게 되면, 매우 밝거나 어두운 상태에서 그에 맞는 측정이 가능합니다. 센서의 예민함을 생각해 보면, 이렇게 mode 를 달리해서 leveling 을 하는 것이 맞아 보입니다.

----------------------------------------------------------------------
 ID | Mode  | Integration | Resolution | Notes 
    |       | time        |            | 
----------------------------------------------------------------------
  0 | LOW   | 16 ms       | 4.0 Lux    | to measure very bright light
  1 | HIGH  | 120 ms      | 1.0 lux    | default
  2 | HIGH2 | 120 ms      | 0.5 lux    | to measure very dim light
----------------------------------------------------------------------

외관은 다음과 같습니다.


뒷면은 다음과 같습니다.


가장 중요한 센서 부위를 확대해 보면 아래와 같습니다. O / D / N / W 라는 글씨가 세겨져 있네요.


...라고 생각할 수 있으나, datasheet 를 살펴 보면, Product No. 와 Lot No. 임을 알 수 있습니다. 즉, 위의 사진에서 고개를 옆으로 돌린 다음 읽어 보면, AA 는 해당 chip 의 product 번호 이고, 0322 은 lot 번호 입니다.

* BH1750FVI PDF




3. Wiring

모듈화 되어 있으므로 arduino 와의 연결은 다음과 같이 하면 됩니다.

----------------------------------------------------------------------
 Arduino Nano | BH1750FVI |                  Note
----------------------------------------------------------------------
     GND      |    GND    | Ground                                    
----------------------------------------------------------------------
              |    AD0    | Address                                   
              |           | Default is pulled LOW = 0x23. HIGH = 0x5C 
----------------------------------------------------------------------
      A4      |    SDA    | I2C Data                                  
----------------------------------------------------------------------
      A5      |    SDL    | I2C Clock                                 
----------------------------------------------------------------------
     3V3      |    VCC    | Power (3.3V or 5V)                        
----------------------------------------------------------------------

아래와 같이 빵판에서 arduino nano 와 연결 하였습니다.


실제 연결한 모습.




4. I2C Address

I2C 프로토콜을 사용하므로, 우선 I2C 주소를 찾고 싶어 졌습니다. ic2detect 를 arduino 에 로딩 합니다.


실제 코드는 다음과 같습니다. 다른 예제에서도 항상 사용하는 그 코드 입니다.

#include "Wire.h"
#include "i2cdetect.h"
 
void setup() {
	Wire.begin();
    Serial.begin(115200);
    Serial.println("i2cdetect example\n");
    Serial.print("Scanning address range 0x03-0x77\n\n");
}
 
void loop() {
    i2cdetect(); // default range from 0x03 to 0x77
    delay(2000);
}

실행을 시켜 보니, 0x23 주소를 사용하고 있군요.

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- 23 -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

혹시, 다른 I2C 모듈과 같이 사용하는데, I2C 주소가 0x23 번에서 충돌이 난다 할 때에는 AD0 핀을 HIGH (전압 인가) 해주면, 다른 주소인 0x5c 를 사용할 수 있게 됩니다.


실제로 AD0 를 HIGH 로 만들고, i2cdetect 를 돌려 보면, 아래와 같이 I2C 주소가 찍힙니다.

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- 5c -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --

Arduino IDE Monitor 에서의 스샷도 같이 올려 봅니다.



5. Raw Access

Library 를 사용하지 않고, 쌩으로 접근하는 code 입니다. 이를 이용하여 Lux 광량을 측정해 봅니다. 자세히 보면, default mode (HIGH) 에서 integration time 이 120ms 이므로, 그 기준으로 측정하여 값을 계산 합니다.

#include "Wire.h"
// GY-30
// BH1750FVI
// in ADDR 'L' mode 7bit addr

#define ADDR 0b0100011
// addr 'H' mode
// #define ADDR 0b1011100

void setup() {
  // put your setup code here, to run once:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  
  Wire.begin();
  Wire.beginTransmission(ADDR);
  Wire.write(0b00000001);
  Wire.endTransmission();
}

void loop() {
  // put your main code here, to run repeatedly:
  int val = 0;
  
  // reset
  Wire.beginTransmission(ADDR);
  Wire.write(0b00000111);
  Wire.endTransmission();
  Wire.beginTransmission(ADDR);
  Wire.write(0b00100000);
  Wire.endTransmission();
  
  // typical read delay 120ms
  delay(120);
  
  Wire.requestFrom(ADDR, 2); // 2byte every time
  
  for (val = 0; Wire.available() >= 1; ) {
    char c = Wire.read();
    
    //Serial.println(c, HEX);
    val = (val << 8) + (c & 0xFF);
  }
  
  val = val / 1.2;
  Serial.print("lx: ");
  Serial.print(val);
  Serial.println(" OK");
  delay(100);
}

Serial Monitor 로 보면 다음과 같은 결과가 나옵니다.


그래프화 해 봤습니다. 기민하게 잘 반응해 주며, 나름 사용할 만 합니다.




6. Library

위의 source 코드는 정말 쌩으로 만든 코드이고, 아래는 library 를 이용한 코드 입니다.

* claws / BH1750

Library Manager 를 이용하여, Christopher Laws 라는 분이 만든 코드를 이용해 봅니다.


자동으로 인스톨 됩니다. "BH1750.h" 에 자세한 로직과 계산은 들어가 있을 것이고, 이를 차용한 코드 입니다.

#include "Wire.h"
#include "BH1750.h"

BH1750 lightMeter;

void setup(){
	Serial.begin(115200);
	
	// Initialize the I2C bus (BH1750 library doesn't do this automatically)
	// On esp8266 devices you can select SCL and SDA pins using Wire.begin(D4, D3);
	Wire.begin();
	
	lightMeter.begin();
	Serial.println(F("BH1750 Test"));
}

void loop() {
	float lux = lightMeter.readLightLevel();
	Serial.print("Light: ");
	Serial.print(lux);
	Serial.println(" lx");
	delay(1000);
}

별 차이는 없는 듯 합니다만, 아마 좀더 정확한 값을 보여줄 것 같습니다.




7. Reference

참고한 사이트 들은 아래와 같습니다.

* RobTillaart / BH1750FVI_RT

* claws / BH1750

* GY-30 BH1750FVI Digital Ambient Light Intensity Sensor Module

* GY-30 Digital Light Intensity Measuring Module

* Using the BH1750 (GY-30) Sensor with Arduinoㅜ

참 쉽죠?!


FIN

댓글