BH1750 Light ยท Astro Tech Blog

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.

BH1750 Light Sensor Pinout

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 PinNameConnection
VCCPower5V or 3.3V
GNDGroundGND
SCLI2C ClockA5 (Uno/Nano), SCL (Mega)
SDAI2C DataA4 (Uno/Nano), SDA (Mega)
ADDRAddress selectGND (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). Returns false if 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

ModeResolutionMeasurement TimePower
CONTINUOUS_HIGH_RES_MODE1 lx120 msContinuous
CONTINUOUS_HIGH_RES_MODE_20.5 lx120 msContinuous
CONTINUOUS_LOW_RES_MODE4 lx16 msContinuous
ONCE_HIGH_RES_MODE1 lx120 msSingle (auto power-down)
ONCE_HIGH_RES_MODE_20.5 lx120 msSingle (auto power-down)
ONCE_LOW_RES_MODE4 lx16 msSingle (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

  1. Connect the BH1750 module to the Arduino as shown in the schematic.
  2. Install the BH1750 library by Christopher Laws via the Library Manager.
  3. Copy the code into the Arduino IDE.
  4. Select the correct board and port (Tools > Board and Tools > Port).
  5. Upload the sketch to the Arduino.
  6. Open the Serial Monitor (Tools > Serial Monitor, set baud rate to 9600).
  7. Observe the light level in lux printed every 500 ms.
  8. 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 to 0x5C by connecting ADDR to VCC. The begin() 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.