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.

Digital Light Meter using Arduino and BH1750FVI sensor

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 0×23 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.

BH1750FVI sensor breakout board

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.

Sensor and display connections to 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.

Actual hardware setup of the Light meter

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.

Light meter displaying light intensity in Foot-candles

Light meter displaying light amount in Lux

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)

2 comments

Leave a Reply

Your email address will not be published. Required fields are marked *