Building a simple digital light meter using Arduino and BH1750FVI sensor
|
A light meter is a device that measures the intensity of light. It finds applications in schools, hospitals, production areas, passageways and more to measure and maintain proper lighting levels. It is often used by photographers to determine the proper exposure for a photograph. Today we are going to build a simple light meter using an Arduino board and a BH1750 digital light sensor. The measured lighting level or intensity is displayed on eight seven segment LED displays, in both Lux and Foot-candle units.
Hardware
Shawon Shahryiar posted a project article before about making a lux meter using a simple LDR. His project used an inexpensive photo sensor to detect the light intensity. In order to convert the measured light intensity into Lux, he needed to calibrate the photo sensor first using an external reference photometer. This project is an improvement over that as it uses the BH1750FVI sensor to measure the ambient lighting level. BH1750FVI is a calibrated digital light sensor IC that measures the incident light intensity and converts it into a 16-bit digital number. It can measure ambient light intensity ranging from 0 to 65535 Lux (L). The Lux is an SI unit for illuminance and is equal to one lumen per square meter. The BH1750FVI sensor directly gives output in Lux. The spectral response function of the sensor is approximately close to that of the human eye. The sensor output can be accessed through an I2C interface. The 7-bit I2C address is 0x23 if the ADDR pin is grounded, or 0x5C if ADDR is tied to VCC. In this project, I am using the BH1750FVI sensor module from Elecrow.
For the display part, I am using the SPI7SEGDISP8.56-1R module, which is an 8-digit serial seven segment LED display based on the MAX7219 IC. It requires only 3 I/O pins and provides full control of all the LED segments. The Arduino board used in this project is called Crowduino, which is 100% compatible with Arduino Duemilanove. A tact switch connected to Digital Pin 2 (interrupt 0) of Crowduino is used as ‘Mode’ select to toggle between Lux (L) and Foot-candle (Fc) units of display. The following picture shows the connections of the BH1750FVI sensor board, the SPI7SEGDISP8.56-1R display, and the tact switch to the Arduino board.
I have soldered the tact switch and the BH1750FVI sensor module on a general purpose prototyping board, which plugs onto the Crowduino board using male headers. An easier way to setup the hardware for this project would be to use an Arduino prototyping shield. Since I didn’t have a spare proto shield, I made one by myself. The following picture shows the complete hardware setup for this project.
Software
The LedControl library allows you to easily interface MAX7219-driven seven segment LED displays to Arduino. Read my tutorial post on MAX7219 and Arduino for more details on this. The sensor data is read using the Wire library. The sensor is configured for a measurement resolution of 1 Lux. Read the datasheet of BH1750FVI for more details about this sensor. The Mode tact switch operates in interrupt mode. When the power is first turned on, the light meter displays light intensity in Lux (L). The sensor can measure light intensity up to 65535 Lux. Pressing the Mode switch changes the unit of measurement to Foot-candle (Fc). The Mode switch is used to switch back and forth between Lux and Foot-candle units. Here is the complete Arduino sketch for this project. Note that you need to download the LedControl library and link to this project.
/* ####################################################### Project: Arduino Light Meter Description: This project measures ambient light intensity and displays it on seven segment LEDs in Lux or Foot Candel units. The BH1750 sensor is used for measuring light intensity. Written by: Raj Bhatt (June 17, 2013) www.embedded-lab.com ####################################################### BH1750 sensor module connections: -- ----------------------------------- BH1750 Arduino VCC ---------------> 5V SCL ---------------> Analog pin 5 (A5) SDA ---------------> Analog pin 4 (A4) ADD ---------------> Leave it open GND ---------------> GND ####################################################### MAX7219 based LED display connections ------------------------------------- MAX7219 Arduino VCC ---------------> 5V DIN ---------------> Digital Pin 7 LOAD ---------------> Digital Pin 6 CLK ---------------> Digital Pin 5 GND ---------------> GND This software is licensed under a Creative Commons Attribution-ShareAlike 3.0. */ #include "Wire.h" #include "math.h" #include "LedControl.h" LedControl lc=LedControl(7,5,6,1); // Pin 7 to Data In, 5 to Clk, 6 to LOAD int BH1750_Device = 0x23; // I2C address for light sensor int iCheck = 0; // iCheck = 0 for Lux, iCheck = 1 for Foot-Candles unsigned int Lux, Scaled_FtCd; float FtCd, Wattsm2; int IntPin = 0; // Pin 2 //variables to keep track of the timing of recent interrupts unsigned long button_time = 0; unsigned long last_button_time = 0; void setup() { Wire.begin(); Serial.begin(9600); lc.shutdown(0,false);// turn off power saving, enables display lc.setIntensity(0,12);// sets brightness (0~15 possible values) lc.clearDisplay(0);// clear screen Configure_BH1750(); //Attach the interrupt to the input pin and monitor for ANY Change attachInterrupt(IntPin, stateChange, FALLING); delay(300); } void loop() { int i; Lux = BH1750_Read(); FtCd = Lux/10.764; Wattsm2 = Lux/683.0; Serial.print(Lux,DEC); Serial.println("[lx]"); Serial.print(FtCd,2); Serial.println("[FC]"); Serial.print(Wattsm2,4); Serial.println("[Watts/m^2]"); delay(1000); Disp_Data(); } unsigned int BH1750_Read() // { unsigned int i=0; Wire.beginTransmission(BH1750_Device); Wire.requestFrom(BH1750_Device, 2); while(Wire.available()) // { i <<=8; i|= Wire.read(); } Wire.endTransmission(); return i/1.2; // Convert to Lux } void Disp_Data(){ int ones, tens, hundreds, thousands, ten_thousands; if(iCheck == 0) { ones = Lux%10; tens = (Lux/10)%10; hundreds = (Lux/100)%10; thousands = (Lux/1000)%10; ten_thousands = (Lux/10000)%10; if(ten_thousands == 0) lc.setChar(0, 7, ' ', false); else lc.setDigit(0,7,(byte)ten_thousands,false); if(ten_thousands == 0 && thousands == 0) lc.setChar(0, 6, ' ', false); else lc.setDigit(0,6,(byte)thousands,false); if(ten_thousands == 0 && thousands == 0 && hundreds == 0) lc.setChar(0, 5, ' ', false); else lc.setDigit(0,5,(byte)hundreds,false); if(ten_thousands == 0 && thousands == 0 && hundreds == 0 && hundreds == 0 && tens==0) lc.setChar(0, 4, ' ', false); else lc.setDigit(0,4,(byte)tens,false); lc.setDigit(0,3,(byte)ones,false); lc.setChar(0, 1, 'L', false); lc.setChar(0, 0, ' ', false); } if(iCheck == 1) { Scaled_FtCd = FtCd*1000; ones = Scaled_FtCd%10; tens = (Scaled_FtCd/10)%10; hundreds = (Scaled_FtCd/100)%10; thousands = (Scaled_FtCd/1000)%10; ten_thousands = (Scaled_FtCd/10000)%10; if(ten_thousands == 0) lc.setChar(0, 7, ' ', false); else lc.setDigit(0,7,(byte)ten_thousands,false); lc.setDigit(0,6,(byte)thousands,true); lc.setDigit(0,5,(byte)hundreds,false); lc.setDigit(0,4,(byte)tens,false); lc.setDigit(0,3,(byte)ones,false); lc.setChar(0, 1, 'F', false); lc.setChar(0, 0, 'C', false); } } void stateChange() { button_time = millis(); if (button_time - last_button_time > 250) { iCheck = !iCheck; Disp_Data(); last_button_time = button_time; } } void Configure_BH1750() { Wire.beginTransmission(BH1750_Device); Wire.write(0x10); // Set resolution to 1 Lux Wire.endTransmission(); } |
Download Sketch and LedControl library
Output
The sensor should be faced directly toward the light source that is to be measured. The measurement and display is refreshed every 1 second. The default unit of display is Lux. Press the Mode switch to toggle between the two units. The following pictures show how the light meter data is displayed in both the units.
Read this Wikipedia page for some examples of average luminance under various light conditions.
List of parts used in this project
1. Crowduino Board
2. BH1750 sensor module
3. SPI7SEGDISP8.56-1R serial seven segment LED display board
4. A Tact switch, resistor, headers, wires, and a prototyping board (preferably proto-shield)
|
follower
Hi R-B, this is a nice project! Congrats!
I’m working on a PWS and I’m using the BH1750 to send the solar radiation value. The thing is, as you pointed out, BH1750 is returning a value in Lux and the PWS web server is expecting Watts per square meter.
I’ve investigated a bit about the conversion between those two units and I think that you formula is true if the BH1750 would sense the green light only, see this thread: http://www.edaboard.com/thread143348.html
The thing is that BH1750 has a larger spectrum: from 400nm to 700nm approx. see: http://rohmfs.rohm.com/en/products/databook/datasheet/ic/sensor/light/bh1750fvi-e.pdf
I’ve came up with an empirical formula that I will share with you so you can correct your script:
[W/m^2] = 0.0079 * [Lux] – 0.0902
This is empirical and may induce some not known error.
Thanks!
Thank you for pointing that out. But I have not used Watts/m^2 unit in this project. I think you are referring to my another project that uses chipKit:
http://embedded-lab.com/blog/?p=10663
In this one, I have mentioned in the text that Watts/m^2 is computed at the center of the visible spectrum, which is ~555nm.
Hi dear thanks for this formula. Can I have the source (I would like to use it in a work)
I have seen in your program that you are connection the light sensor to 5V, I have read in the datasheet that it works properly with 3,6V or so…have you had any trouble with that, have I missed anything??
Quite cool your website!!
Pingback: BLOG | New Products Post-Basic Kit for Arduino
Pingback: BLOG | Making a digital light meter using Crowduino