BH1750 Ambient Light Sensor
The BH1750FVI is a digital ambient light sensor from ROHM Semiconductor that measures illuminance in lux (0โ65535 lx) directly over an I2C interface. It uses a photodiode with a spectral response close to human eye sensitivity, making it ideal for display backlight control, automatic lighting systems, and solar irradiance monitoring. The sensor has a wide dynamic range and can be configured for low-resolution (4 lx per bit, 16 ms) or high-resolution (1 lx per bit, 120 ms) measurement modes.
For this interfacing you need the following components:
- Arduino board (Uno, Nano, Mega, etc.)
- BH1750 ambient light sensor module (GY-302 or similar)
- Breadboard and jumper wires
- USB cable to connect Arduino to your computer
Schematic
The BH1750 communicates over the I2C bus. Connect it to the Arduino as follows:
BH1750 Module Arduino
------------- -------
VCC --> 5V (or 3.3V)
GND --> GND
SCL --> A5 (Uno/Nano) or SCL (Mega)
SDA --> A4 (Uno/Nano) or SDA (Mega)
ADDR --> GND (address 0x23) or VCC (address 0x5C)
The ADDR pin selects the I2C address. Connect to GND for address 0x23 (default) or to VCC for address 0x5C.
Pin Map
| Module Pin | Name | Connection |
|---|---|---|
| VCC | Power | 5V or 3.3V |
| GND | Ground | GND |
| SCL | I2C Clock | A5 (Uno/Nano), SCL (Mega) |
| SDA | I2C Data | A4 (Uno/Nano), SDA (Mega) |
| ADDR | Address select | GND (0x23) or VCC (0x5C) |
I2C pins vary by Arduino board:
- Uno / Nano / Mini: SDA โ A4, SCL โ A5
- Mega 2560: SDA โ 20, SCL โ 21
- Leonardo: SDA โ 2, SCL โ 3
- Due: SDA โ SDA, SCL โ SCL (dedicated pins)
Install necessary Library
Install the BH1750 library by Christopher Laws via the Library Manager (Tools > Manage Libraries).
Alternatively, using arduino-cli:
arduino-cli lib install "BH1750"
The library depends on the Wire library which is built into the Arduino IDE.
Code with complete explanation
This sketch reads the ambient light level from the BH1750 and prints the value in lux to the Serial Monitor.
#include <Wire.h>
#include <BH1750.h>
BH1750 lightMeter;
void setup()
{
Serial.begin(9600);
Wire.begin();
if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE))
{
Serial.println("BH1750 initialized");
}
else
{
Serial.println("Error: BH1750 not found. Check wiring.");
while (1) {}
}
Serial.println("Ambient Light Sensor Test");
}
void loop()
{
float lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.print(" lx");
// Descriptive label
if (lux < 1)
{
Serial.print(" (Moonless night)");
}
else if (lux < 10)
{
Serial.print(" (Dim indoor)");
}
else if (lux < 100)
{
Serial.print(" (Typical indoor)");
}
else if (lux < 500)
{
Serial.print(" (Bright indoor / overcast)");
}
else if (lux < 1000)
{
Serial.print(" (Direct indoor light)");
}
else if (lux < 10000)
{
Serial.print(" (Full daylight / shade)");
}
else
{
Serial.print(" (Full sunlight)");
}
Serial.println();
delay(500);
}
Code breakdown
#include <BH1750.h>โ includes the BH1750 library for I2C communication.BH1750 lightMeterโ creates a BH1750 object.Wire.begin()โ initializes the I2C bus.lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)โ initializes the sensor in continuous high-resolution mode (1 lx resolution, 120 ms measurement time). Returnsfalseif the sensor is not detected.lightMeter.readLightLevel()โ returns the current illuminance in lux as a float.BH1750::CONTINUOUS_HIGH_RES_MODEโ high resolution (1 lx), 120 ms measurement time, continuous readings.BH1750::CONTINUOUS_HIGH_RES_MODE_2โ high resolution (0.5 lx), 120 ms, continuous.BH1750::CONTINUOUS_LOW_RES_MODEโ low resolution (4 lx), 16 ms, continuous.BH1750::ONCE_HIGH_RES_MODEโ high resolution, single measurement (lowest power).
Measurement modes
| Mode | Resolution | Measurement Time | Power |
|---|---|---|---|
| CONTINUOUS_HIGH_RES_MODE | 1 lx | 120 ms | Continuous |
| CONTINUOUS_HIGH_RES_MODE_2 | 0.5 lx | 120 ms | Continuous |
| CONTINUOUS_LOW_RES_MODE | 4 lx | 16 ms | Continuous |
| ONCE_HIGH_RES_MODE | 1 lx | 120 ms | Single (auto power-down) |
| ONCE_HIGH_RES_MODE_2 | 0.5 lx | 120 ms | Single (auto power-down) |
| ONCE_LOW_RES_MODE | 4 lx | 16 ms | Single (auto power-down) |
For battery-powered projects, use ONCE_HIGH_RES_MODE to take a reading and then put the sensor to sleep automatically.
Using two BH1750 sensors on the same bus
Two BH1750 sensors can share the I2C bus by setting different ADDR pins:
BH1750 sensor1; // ADDR = GND โ address 0x23
BH1750 sensor2; // ADDR = VCC โ address 0x5C
void setup()
{
Wire.begin();
sensor1.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23);
sensor2.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x5C);
}
void loop()
{
float lux1 = sensor1.readLightLevel();
float lux2 = sensor2.readLightLevel();
Serial.print(lux1);
Serial.print(" lx / ");
Serial.print(lux2);
Serial.println(" lx");
delay(500);
}
Steps to perform this interfacing
- Connect the BH1750 module to the Arduino as shown in the schematic.
- Install the BH1750 library by Christopher Laws via the Library Manager.
- Copy the code into the Arduino IDE.
- Select the correct board and port (
Tools > BoardandTools > Port). - Upload the sketch to the Arduino.
- Open the Serial Monitor (
Tools > Serial Monitor, set baud rate to 9600). - Observe the light level in lux printed every 500 ms.
- Cover the sensor with your hand โ the lux value should drop to near zero. Point it at a bright light source โ the value should rise significantly.
Caution
- Measurement time: The high-resolution mode takes 120 ms per reading. Do not call
readLightLevel()more than 8 times per second. In low-resolution mode, the measurement time is 16 ms (60+ readings per second). - Spectral response: The BH1750โs spectral response is designed to match the human eyeโs photopic luminosity function (peak at 555 nm). It under-reports infrared and deep-blue/UV light. It is not suitable for measuring LED grow lights with significant far-red (730 nm) output without calibration.
- I2C address conflict: The default address is
0x23(ADDR = GND). If other I2C devices on the bus use this address, change the BH1750 address to0x5Cby connecting ADDR to VCC. Thebegin()function accepts an optional address parameter:lightMeter.begin(mode, address). - Light saturation: The BH1750 can measure up to 65535 lx in high-resolution mode. Full direct sunlight is approximately 100000 lx. In very bright conditions (direct sun, high altitude, snow reflection), the sensor may saturate or report the maximum value. In these cases, use low-resolution mode or apply a diffuser (e.g., a piece of white paper) over the sensor.
- Power supply noise: The BH1750 has excellent power supply rejection, but long I2C wires (over 30 cm) can pick up noise. Keep wires short or use shielded cable for reliable I2C communication in noisy environments.