top of page
Writer's pictureRamesh G

LUX Meter Using BH1750 and OLED Display


In this project, we will make a Arduino based LUX Meter Using BH1750 and OLED Gauge Display. Sometime we need to measure the exposure of light but a lux meter costs is high. Here to learn low cost and accurate ambient lighting sensor BH1750 interface with arduino with OLED Gauge display and enjoyed it. In this Project Push Button added for HOLD the Lux meter display value if pressed and Reading value displayed again push button pressed.


Circuit Diagram


Components Required

Arduino Uno - 1 no

OLED 0.96 SSD1306 - 4 PIN - 1no

BH1750 GY-302- 1no

Push button switch- 1 no

BH1750

Refer previous project for more detail : https://www.dofbot.com/post/iot-cloud-bh1750-lux-monitor

A digital Lux Meter is a device to measure the intensity of a source of light. A lux meter will be used in photography to estimate how bright the flash is and also the encircling ambient lighting.



BH1750 is a digital ambient light sensor that is used commonly used in mobile phones to manipulate the screen brightness based on the environment lighting. This sensor can accurately measure the LUX value of light up to 65535lx.

A digital Lux Meter is a device to measure the intensity of a source of light. A lux meter will be used in photography to estimate how bright the flash is and also the encircling ambient lighting.


working principle of lux meter

Most of the lux meter consists of a body, photocell or light sensor, and display. The light that falls on to the photocell or sensor contains energy that is transformed into electric current. Indeed, the measure of current depends on the light that strokes the photocell or light sensor. Lux meters read the electrical current calculate the appropriate value, and show this value on its display.


BH1750 Features

  • Power Supply: 2.4V-3.6V (typically 3.0V)

  • Less current consumption: 0.12mA

  • Measuring Rang: 1-65535lx

  • Communication: I2C bus

  • Accuracy: +/-20%

  • Built in A/D converter for converting analog illuminance in the digital data.

  • Very small effect of IR radiation

  • Highly responsive near to human eye.

This is a BH1750 light intensity sensor breakout board with a 16 bit AD converter built-in which can immediately output a digital signal, there is no need for complex calculations. This is more accurate and simpler to use the version of the simple LDR which only outputs a voltage that needs to be calculated to obtain meaningful data.

First, connect the VCC and GND of the BH1750 Light Sensor to 3V3 and GND of Arduino Then connect the SCL and SDA pins of the sensor to corresponding pins of Arduino A5 &A4 Pin using jumper wires.

Then, connect the SCL, SDA, GND, and VCC pin of the OLED display to the corresponding BH1750 sensor pins.


Let's talk about lux and Illuminance:

The lux (symbol: lx) is the SI derived unit of illuminance, measuring luminous flux per unit area. It is equal to one lumen per square meter. In photometry, this is used as a measure of the intensity, as perceived by the human eye, of light that hits or passes through a surface. It is analogous to the radiometric unit watt per square meter, but with the power at each wavelength weighted according to the luminosity function, a standardized model of human visual brightness perception. In English, "lux" is used as both the singular and plural form.

Illuminance: Illuminance is a measure of how much luminous flux is spread over a given area. One can think of luminous flux (measured in lumens) as a measure of the total "amount" of visible light present, and the illuminance as a measure of the intensity of illumination on a surface. A given amount of light will illuminate a surface more dimly if it is spread over a larger area, so illuminance is inversely proportional to the area when the luminous flux is held constant.

One lux is equal to one lumen per square meter:

1 lx = 1 lm/m2 = 1 cd·sr/m2.

A flux of 1000 lumens, concentrated into an area of 1 square meter, lights up that square meter with an illuminance of 1000 lux. However, the same 1000 lumens, spread out over 10 square meters produces a dimmer illuminance of only 100 lux.




OLED SSD1306-I2C 128X64 Display Module 0.96 inch


This is a 0.96 inch Blue OLED display module. The display module can be interfaced with any microcontroller using SPI/IIC protocols. It is having a resolution of 128x64. The package includes display board,display, 4 pin male header presoldered to board.

OLED (Organic Light-Emitting Diode) is a self light-emitting technology composed of a thin, multi-layered organic film placed between an anode and cathode. In contrast to LCD technology, OLED does not require a backlight. OLED possesses high application potential for virtually all types of displays and is regarded as the ultimate technology for the next generation of flat-panel displays.



Download Data sheet


Installing the Arduino Library

Installing SSD1306 OLED Library – Arduino

Download u8glib Library , we need to use this library for OLED

Download BH1750_Library , we need to use this library for Lux Sensor

Follow the next steps to install those libraries.

In your Arduino IDE, to install the libraries go to Sketch > Include Library > Add .ZIP library… and select the library you’ve just downloaded.


After installing the required libraries, copy the following code to your Arduino IDE.


Subscribe and Download code.



Arduino Code:

//----------------------------------------Include Library

#include <Wire.h>

#include "U8glib.h"

#include <ErriezBH1750.h>

//----------------------------------------


//----------------------------------------Initialize u8g

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_NONE|U8G_I2C_OPT_DEV_0); // I2C / TWI

//----------------------------------------


///----------------------------------------BH1750 I2C address

// ADDR line LOW/open: I2C address 0x23 (0x46 including R/W bit) [default]

// ADDR line HIGH: I2C address 0x5C (0xB8 including R/W bit)

BH1750 sensor(LOW);

//----------------------------------------


//----------------------------------------Variable and button pin declarations

#define Button_Pin 4

bool Button;

//----------------------------------------


//----------------------------------------Variable for LUX Value

uint16_t read_lux;

uint16_t result_lux;

byte lux_HR;

//----------------------------------------


int x_LUX_val; //--> X position to display LUX value


//----------------------------------------Variables for Gauge Chart

int xmax=128;

int ymax=62;

int xcenter=xmax/2;

int ycenter=ymax/2+10;

int arc=ymax/2;

int angle=0;

int p, w, m;

u8g_uint_t xx=0;

//----------------------------------------Variables for Gauge Chart


//----------------------------------------Variable for Mode

// Mode = 1 for realtime reading of sensor values (LUX).

// Mode = 2 to capture sensor value (LUX).

int Mode = 1;

//----------------------------------------


bool Blink_Cap; //--> Variables to make the sensor value flashes on the capture mode.


unsigned long previousMillis = 0; //--> will store last time was updated

const long interval = 250; //--> interval (milliseconds)


//========================================================================VOID ShowLux_With_GaugeChart(uint8_t angle)

void ShowLux_With_GaugeChart(uint8_t angle) {

//----------------------------------------draw border of the gauge

u8g.drawCircle(xcenter,ycenter,arc+6, U8G_DRAW_UPPER_RIGHT);

u8g.drawCircle(xcenter,ycenter,arc+4, U8G_DRAW_UPPER_RIGHT);

u8g.drawCircle(xcenter,ycenter,arc+6, U8G_DRAW_UPPER_LEFT);

u8g.drawCircle(xcenter,ycenter,arc+4, U8G_DRAW_UPPER_LEFT);

//----------------------------------------

//----------------------------------------draw the needle

float x1=sin(2*angle*2*3.14/360);

float y1=cos(2*angle*2*3.14/360);

u8g.drawLine(xcenter, ycenter, xcenter+arc*x1, ycenter-arc*y1);

u8g.drawDisc(xcenter, ycenter, 5, U8G_DRAW_UPPER_LEFT);

u8g.drawDisc(xcenter, ycenter, 5, U8G_DRAW_UPPER_RIGHT);

u8g.setFont(u8g_font_chikita);

//----------------------------------------

//----------------------------------------show MIN and MAX labels

u8g.drawStr(0, 5, "MIN");

u8g.drawStr(0, 13, "1");


u8g.drawStr(110, 5, "MAX");

u8g.drawStr(98, 13, "65535");

u8g.drawStr(9, 42, "MIN");

u8g.drawStr(105, 42, "MAX");

//----------------------------------------

//----------------------------------------show gauge label

u8g.setPrintPos(56,24);

u8g.print("LUX");

u8g.setPrintPos(50,32);

u8g.print("METER");

//----------------------------------------

u8g.setFont(u8g_font_unifont);

//----------------------------------------Conditions for displaying LUX value center align on OLED

if (result_lux < 10) {

x_LUX_val = 36;

} else if (result_lux < 100 && result_lux > 9) {

x_LUX_val = 32;

} else if (result_lux < 1000 && result_lux > 99) {

x_LUX_val = 28;

} else if (result_lux < 10000 && result_lux > 999) {

x_LUX_val = 24;

} else if (result_lux > 9999) {

x_LUX_val = 20;

}

//----------------------------------------

//----------------------------------------Mode = 1 for realtime reading of sensor values (LUX).

if (Mode == 1) {

u8g.setPrintPos(x_LUX_val, 60);

u8g.print(result_lux);

u8g.print(".");

u8g.print(lux_HR);

u8g.print(" lx");

}

//----------------------------------------

//----------------------------------------Mode = 2 to capture sensor value (LUX).

if (Mode == 2) {

if (Blink_Cap == false) {

u8g.setPrintPos(x_LUX_val, 60);

u8g.print(result_lux);

u8g.print(".");

u8g.print(lux_HR);

u8g.print(" lx");

} else {

u8g.setPrintPos(0, 60);

u8g.print(" ");

}

//----------------------------------------

}

}

//========================================================================


//========================================================================VOID SETUP

void setup(void) {

u8g.setFont(u8g_font_chikita);

pinMode(Button_Pin, INPUT_PULLUP);


Wire.begin(); //--> Initialize I2C bus

sensor.begin(ModeContinuous, ResolutionHigh); //--> Initialize sensor in continues mode, high 0.5 lx resolution

sensor.startConversion(); //--> Start conversion

}

//========================================================================


//========================================================================VOID LOOP

void loop(void) {

//----------------------------------------Read button

Button = digitalRead(Button_Pin);

if (Button == LOW) {

Mode++;

if (Mode > 2) Mode = 1;

//----------------------------------------Looping to check the button condition until the button is finished pressing to perform the next instruction.

while(Button == LOW) {

Button = digitalRead(Button_Pin);

delay(100);

}

//----------------------------------------

}

//----------------------------------------

//.................................................................................Millis for loop delay

unsigned long currentMillis = millis();


if (currentMillis - previousMillis >= interval) {

previousMillis = currentMillis; //--> save the last time currentMillis

//----------------------------------------Mode = 1 for realtime reading of sensor values (LUX).

if (Mode == 1) {

//----------------------------------------Wait for completion (blocking busy-wait delay)

if (sensor.isConversionCompleted()) {

read_lux = sensor.read(); //--> Read light

result_lux = read_lux / 2;

lux_HR = read_lux % 10;

}

//----------------------------------------

}

//----------------------------------------

if (Mode == 2) Blink_Cap = !Blink_Cap; //--> Toggle Blink_Cap

//----------------------------------------Converts sensor / LUX value to angle value

m = map(result_lux,0,65535,0,90);

//----------------------------------------

//----------------------------------------show needle and dial

xx = m;

if (xx<45){

xx=xx+135;

}

else {

xx=xx-45;

}

//----------------------------------------

//----------------------------------------picture loop (Loop for display on OLED)

u8g.firstPage();

do {

ShowLux_With_GaugeChart(xx);

}

while( u8g.nextPage() );

//----------------------------------------

}

//.................................................................................

}



877 views0 comments

Comentários


bottom of page