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 를 사용할 수 있게 됩니다.
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);
}
별 차이는 없는 듯 합니다만, 아마 좀더 정확한 값을 보여줄 것 같습니다.
참고한 사이트 들은 아래와 같습니다.
* 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
댓글
댓글 쓰기