BH1750 Light Sensor

A digital ambient light sensor that reports illuminance straight in lux, 1 to 65535 lx, over I2C.

  • Measurement range1 to 65535 lx (0.11 to 100000 lx with MTreg adjusted)
  • Chip supply voltage2.4 V to 3.6 V (3.0 V typical), 4.5 V absolute maximum
  • Supply current120 µA typical (190 µA max) measuring; 0.01 µA typical powered down
  • Resolution and timeH-res 1 lx at 120 ms; H-res mode 2 0.5 lx at 120 ms; L-res 4 lx at 16 ms (typical)
BH1750 Light Sensor, A digital ambient light sensor that reports illuminance straight in lux, 1 to 65535 lx, over I2C.
In short

The BH1750 is ROHM's I2C ambient light sensor that outputs illuminance directly in lux from 1 to 65535 lx, with a spectral response close to the human eye and 1 lx steps in its recommended 120 ms high-resolution mode (ROHM BH1750FVI datasheet Rev.D, pp. 1, 2, 5). On a GY-302 module, wire VCC to 3.3 V or 5 V (the board regulates it to 3.3 V), GND to GND, and SDA and SCL to the I2C pins. Leave ADDR low for address 0x23, or pull it high for 0x5C (p. 10).

The BH1750FVI is a 16-bit digital ambient light sensor from ROHM. Instead of a raw photodiode voltage it returns illuminance in lux over I2C, with a spectral response close to the human eye's, rejection of 50 Hz and 60 Hz light flicker, and little dependence on the light source, whether incandescent, fluorescent, halogen, white LED or sunlight (ROHM datasheet Rev.D, p. 1). It needs no external calibration: divide the 16-bit reading by 1.2 to get lux in its default mode (p. 7).

The chip itself runs from 2.4 V to 3.6 V and is rated 4.5 V absolute maximum (p. 1), so most makers buy it on a GY-302 breakout, which adds a 3.3 V regulator, 4.7 kΩ pull-ups on SDA and SCL, and a 1 kΩ pull-down on ADDR on a 1x5 header (VCC, GND, SCL, SDA, ADDR). The module therefore takes 3.3 V or 5 V on VCC, and its I2C lines idle at 3.3 V. On a 5 V Uno that is below the 0.7 × VCC (3.5 V) its I2C pins want for a high; it works because Wire.begin() also turns on the Uno's internal pull-ups to 5 V, which lift the lines a little. For margin, use a level shifter.

It offers three measurement modes, each continuous or one-time: H-resolution at 1 lx steps and 120 ms typical, H-resolution mode 2 at 0.5 lx and 120 ms, and L-resolution at 4 lx and 16 ms (p. 5). ROHM recommends H-resolution mode, whose long integration rejects flicker noise. Changing the measurement time register (MTreg, 31 to 254, default 69) trades speed for sensitivity, reaching 0.11 lx per count in mode 2 for dark rooms (p. 11). It draws 120 µA while measuring and 0.01 µA in power-down (p. 2).

BH1750 Light Sensor pinout

tinkered.ai/components/bh1750BH1750 Light Sens…VCCPowerGNDGroundSCLI2C SCLSDAI2C SDAADDRDigital
PinFunctionType
VCCVCC: 3.3-5 V (into the board's 3.3 V regulator)3–5 Vpower in
GNDGNDpower in
SCLI2C SCLbidirectional
SDAI2C SDAbidirectional
ADDRDigitalinput

How to wire the BH1750 Light Sensor

Pin by pin, for the board you have.

BH1750 Light SensorArduino UnoNote
VCC5V
GNDGND
SDASDA
SCLSCL
Open this circuit on an Arduino UnoThe full Arduino Uno guide

BH1750 Light Sensor code

Every example here compiles for its board.

Libraries: claws/BH1750
// BH1750 Light Sensor on Arduino Uno: wiring and a free simulation at https://www.tinkered.ai/components/bh1750
#include <Arduino.h>
#include <Wire.h>
#include <BH1750.h>

BH1750 lightMeter;   // ADDR unwired: 0x23

void setup() {
  Serial.begin(115200);
  Wire.begin();
  // the address goes to begin(): its own argument (0x23 by default) overrides the constructor's
  if (!lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x23)) {
    Serial.println("BH1750 not found: check VCC, SDA/SCL and ADDR");
    while (true) delay(10);
  }
}

void loop() {
  if (lightMeter.measurementReady()) {
    float lux = lightMeter.readLightLevel();
    Serial.print("Light: ");
    Serial.print(lux, 1);
    Serial.println(" lx");
  }
  delay(200);
}
Compiled for arduino:avr:uno on 2026-10-30

Before you wire it

Do
  • VCC to the board's 5V or 3V3, GND to its GND. SDA/SCL to the board's I2C pins (Uno A4/A5, ESP32 GPIO21/22, Pico GP4/GP5, Nucleo D14/D15, NodeMCU D2/D1). No extra pull-ups: the module has 4.7 kΩ on both.
  • Leave ADDR unwired for 0x23. For 0x5C wire ADDR to 3V3, never to 5V.
  • Call Wire.begin() first: the library does not;
  • Pass the address to begin(): lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x5C). begin()'s own address argument defaults to 0x23 and overrides the one given to the constructor, so BH1750 lightMeter(0x5C); lightMeter.begin(); talks to 0x23;
  • Check what begin() returns.
  • Continuous modes: read with readLightLevel() once measurementReady() is true (or every 120 ms or more).
  • One-time modes: call configure(BH1750::ONE_TIME_HIGH_RES_MODE) before each reading, then wait for measurementReady(), then readLightLevel(). The chip powers down after a reading and measures nothing more until told.
  • Two modules: one with ADDR on 3V3, two BH1750 objects, each begin() given its address.
Don’t
  • No measurementReady(true) on an AVR board (Uno, Nano, Mega) with an MTreg above 182: the library computes 180 * MTreg in a 16-bit int, which overflows, and it never returns true. Use measurementReady().
  • On a GY-302 module, VCC takes the board's 5V or 3V3: the module's regulator feeds the chip 3.3 V. A bare BH1750FVI chip needs 2.4 V to 3.6 V and must never see more than 4.5 V (ROHM datasheet, p. 1).
  • The module pulls SDA and SCL up to its own 3.3 V with 4.7 kΩ. Add no extra pull-ups. On a 5 V Uno that is below the 0.7 × VCC (3.5 V) its I2C pins want for a high; it works because Wire.begin() also turns on the Uno's internal pull-ups to 5 V, which lift the lines a little. For margin, use a level shifter.
  • ADDR picks the address: 0x23 when low, 0x5C when high (p. 10). The module's 1 kΩ pull-down holds it low when unwired. For 0x5C wire ADDR straight to 3V3, never to 5 V; a weak pull-up resistor loses against the 1 kΩ pull-down and leaves the address at 0x23.
  • Read no faster than the mode's measurement time: 120 ms typical (180 ms max) in H-resolution modes, 16 ms (24 ms max) in L-resolution mode (p. 2). One-time modes power the chip down after each reading, so send the mode command again before every read (p. 5).
  • Keep the sensor's window clear and level with the enclosure's opening. ROHM's MTreg adjustment exists to compensate for an optical window's loss (p. 11).

Specifications

Measurement range
1 to 65535 lx (0.11 to 100000 lx with MTreg adjusted)ROHM BH1750FVI datasheet Rev.D, p. 1
Chip supply voltage
2.4 V to 3.6 V (3.0 V typical), 4.5 V absolute maximumROHM BH1750FVI datasheet Rev.D, p. 1
Supply current
120 µA typical (190 µA max) measuring; 0.01 µA typical powered downROHM BH1750FVI datasheet Rev.D, p. 2
Resolution and time
H-res 1 lx at 120 ms; H-res mode 2 0.5 lx at 120 ms; L-res 4 lx at 16 ms (typical)ROHM BH1750FVI datasheet Rev.D, pp. 2, 5
Lux conversion
lux = 16-bit count ÷ 1.2 (H-resolution mode, default MTreg)ROHM BH1750FVI datasheet Rev.D, pp. 7, 11
Measurement accuracy
Sensor out / actual lux 0.96 to 1.44 (1.2 typical); ±20 % variationROHM BH1750FVI datasheet Rev.D, pp. 1, 2
Peak wavelength
560 nmROHM BH1750FVI datasheet Rev.D, p. 2
I2C addresses
0x23 (ADDR low, ≤ 0.3 VCC), 0x5C (ADDR high, ≥ 0.7 VCC)ROHM BH1750FVI datasheet Rev.D, p. 10
I2C clock
Up to 400 kHzROHM BH1750FVI datasheet Rev.D, p. 2
Operating temperature
-40 °C to 85 °CROHM BH1750FVI datasheet Rev.D, p. 1
Supply voltage
3–5 V
Maximum supply voltage
5.5 V
Interface
I2C
I2C address
0x23
On-board I2C pull-ups
Yes (4.7 kΩ)
Dimensions
13.5 × 18.5 × 11.6 mm
Weight
2 g

From the ROHM BH1750FVI (generic GY-302 module)'s datasheet, published by ROHM BH1750FVI (generic GY-302 module).

Common mistakes

  1. Powering a bare BH1750FVI chip from 5 V

    The chip runs from 2.4 V to 3.6 V and is rated 4.5 V absolute maximum (ROHM datasheet, p. 1). Only a module with a regulator, such as the GY-302, takes 5 V on VCC. ADDR on that module must also go to 3.3 V, not 5 V.

  2. Address 0x5C set in the constructor only

    With the common claws/BH1750 library, begin()'s own address argument defaults to 0x23 and overrides the constructor's. Pass the address to begin(), for example begin(BH1750::CONTINUOUS_HIGH_RES_MODE, 0x5C), and wire ADDR high for 0x5C (p. 10).

  3. Forgetting Wire.begin()

    The popular library does not start the I2C bus itself. Call Wire.begin() before lightMeter.begin(), or the sensor never answers.

  4. One-time mode reads stuck at the old value

    In one-time modes the chip measures once and powers down (ROHM datasheet, p. 5). Send the one-time mode command again before every reading, then wait at least 120 ms in H-resolution mode (p. 2).

  5. Expecting lab-grade accuracy

    ROHM specifies a measurement variation of ±20 % (p. 1), with sensor output 0.96 to 1.44 times actual lux at 1000 lx (p. 2). It is excellent for relative light levels and automatic brightness; calibrate against a reference meter if absolute lux matters.

BH1750 Light Sensor questions

What is the BH1750 I2C address?

0x23 when ADDR is low and 0x5C when ADDR is high (ROHM datasheet, p. 10). On a GY-302 module ADDR is pulled down, so an unwired module answers at 0x23. Wire one module's ADDR to 3V3 to put two on the same bus.

Does the BH1750 work with 5 V and 3.3 V boards?

The GY-302 module does: its regulator feeds the chip 3.3 V from a 3.3 V or 5 V VCC, and its I2C pull-ups hold the lines at 3.3 V, which an Uno reads as a high only with the help of the internal pull-ups Wire.begin() turns on. The bare chip itself is a 2.4 V to 3.6 V part (ROHM datasheet, p. 1), so never wire a bare chip or the module's ADDR to 5 V.

Why does my BH1750 read 0 or -1, or not get detected?

Check VCC, GND, SDA and SCL, call Wire.begin() before the sensor's begin(), and make sure the address in code matches ADDR (0x23 low, 0x5C high, p. 10). A reading of 0 in the dark is genuine: dark output is 0 to 3 counts (p. 2). Waiting less than the 120 ms measurement time between reads (p. 2) also returns stale or empty values.

How do I convert the BH1750 reading to lux?

In H-resolution mode with the default MTreg of 69, divide the 16-bit count by 1.2 (ROHM datasheet, pp. 7, 11). In H-resolution mode 2 the step is halved, 0.5 lx per count (p. 5). Libraries such as claws/BH1750 return lux already.

BH1750 vs an LDR: which should I use?

An LDR gives a resistance you must calibrate yourself and that varies from part to part. The BH1750 returns calibrated lux over I2C, rejects 50/60 Hz flicker and follows the eye's response (ROHM datasheet, p. 1). Use an LDR for a cheap dark or light switch, the BH1750 when you need real lux values.

Can the BH1750 measure bright sunlight?

Its default range tops out at 65535 lx (ROHM datasheet, p. 1). Lowering MTreg to 31 reduces sensitivity to 0.45 times default and extends the range, and ROHM states up to 100000 lx with this adjustment (pp. 1, 11). Direct summer sun can exceed that.

Build something with the BH1750 Light Sensor

  • Automatic display brightness

    Dim an LCD, OLED or LED strip as the room gets darker.

    Build this
  • Smart plant light

    Switch a grow lamp on when daylight falls below a lux threshold.

    Build this
  • Daylight logger

    Log illuminance through the day to an SD card or the cloud with an ESP32.

    Build this
  • DIY lux meter

    Show lux on an OLED for checking desk or photography lighting.

    Build this
For AI assistants

This page as plain Markdown, for ChatGPT, Claude or your own agent. /components/bh1750.md

What will you build with it?