Overview
The BH1750 is a digital ambient-light sensor from ROHM that outputs lux values directly over I2C — no math, no voltage-to-lux conversions, no photoresistor guesswork. It's a 16-bit measurement in a tiny SMD package, with a range of ~1 to 65,535 lux and excellent spectral response to human-visible light. That makes it a go-to choice for auto-brightness displays, sun trackers, greenhouse controllers, smart-home lighting, and anywhere you need real photometric readings.
ShillehTek's pre-soldered BH1750 module includes an onboard regulator and I2C pull-ups, so it runs reliably on both 3.3V and 5V systems. The ADDR pin selects the I2C address: float or tied LOW gives 0x23, and tied HIGH gives 0x5C — so you can run two BH1750s on the same bus.
This manual covers specifications, the pinout, wiring for Arduino, ESP32, Raspberry Pi, and the Pico, a working "hello world" code example for each platform, and FAQs about measurement modes, saturation, and calibration.
At a Glance
Specifications
| Parameter | Value |
| Sensor IC | ROHM BH1750FVI |
| Operating Voltage (module) | 3.3V - 5V (onboard regulator) |
| Chip Voltage | 2.4V - 3.6V (regulated internally) |
| Communication | I2C |
| I2C Addresses | 0x23 (ADDR = LOW) / 0x5C (ADDR = HIGH) |
| Measurement Range | 1 - 65,535 lux |
| Resolution | 1 lux (H-res) / 0.5 lux (H-res2) / 4 lux (L-res) |
| Conversion Time | ~120 ms (H-res) / ~16 ms (L-res) |
| Spectral Response | Similar to human eye |
| Current Draw | ~120 μA (active) |
| Pin Count | 5 (VCC, GND, SCL, SDA, ADDR) |
Pinout Diagram
Wiring Guide
Arduino Wiring
Connect to the Arduino's hardware I2C pins. Leave ADDR unconnected or tied to GND for the default 0x23 address.
| Module Pin | Arduino Pin |
|---|---|
| VCC | 5V |
| GND | GND |
| SCL | A5 (SCL) |
| SDA | A4 (SDA) |
| ADDR | Not connected (address 0x23) |
ESP32 Wiring
The ESP32's 3.3V rail is perfect for the BH1750 module. Use the default I2C pins.
| Module Pin | ESP32 Pin |
|---|---|
| VCC | 3.3V |
| GND | GND |
| SCL | GPIO 22 |
| SDA | GPIO 21 |
| ADDR | Not connected |
Raspberry Pi Wiring
Use hardware I2C. Enable I2C via sudo raspi-config before running your code.
| Module Pin | Raspberry Pi Pin |
|---|---|
| VCC | 3.3V (Pin 1) |
| GND | GND (Pin 6) |
| SCL | GPIO 3 (Pin 5, SCL) |
| SDA | GPIO 2 (Pin 3, SDA) |
| ADDR | Not connected |
i2cdetect -y 1. The default address is 0x23.
Raspberry Pi Pico Wiring
Connect to I2C0 on GP0/GP1. Works in both MicroPython and C SDK.
| Module Pin | Pico Pin |
|---|---|
| VCC | 3.3V (Pin 36) |
| GND | GND (Pin 38) |
| SCL | GP1 (Pin 2, I2C0 SCL) |
| SDA | GP0 (Pin 1, I2C0 SDA) |
| ADDR | Not connected |
Code Examples
Arduino
// BH1750 - Read ambient light in lux
// Requires: BH1750 library by Christopher Laws
#include <Wire.h>
#include <BH1750.h>
BH1750 lightMeter;
void setup() {
Serial.begin(9600);
Wire.begin();
if (!lightMeter.begin()) {
Serial.println("BH1750 not found. Check wiring.");
while (1);
}
Serial.println("BH1750 ready.");
}
void loop() {
float lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
delay(500);
}
ESP32
// BH1750 on ESP32 via I2C (GPIO21 SDA, GPIO22 SCL)
// Requires: BH1750 library
#include <Wire.h>
#include <BH1750.h>
BH1750 lightMeter;
void setup() {
Serial.begin(115200);
Wire.begin(21, 22);
if (!lightMeter.begin()) {
Serial.println("BH1750 not found.");
while (1);
}
}
void loop() {
float lux = lightMeter.readLightLevel();
Serial.printf("Light: %.1f lx\n", lux);
delay(500);
}
Raspberry Pi
# BH1750 on Raspberry Pi via I2C
# Install: pip install smbus2
# Enable I2C: sudo raspi-config -> Interface Options -> I2C
import smbus2
import time
BH1750_ADDR = 0x23
CONT_H_RES = 0x10 # continuous 1-lux resolution
bus = smbus2.SMBus(1)
bus.write_byte(BH1750_ADDR, CONT_H_RES)
time.sleep(0.2) # first conversion
while True:
data = bus.read_i2c_block_data(BH1750_ADDR, 0x00, 2)
raw = (data[0] << 8) | data[1]
lux = raw / 1.2
print(f"Light: {lux:.1f} lx")
time.sleep(1)
Raspberry Pi Pico (MicroPython)
# BH1750 on Pico via I2C0 (GP0 SDA, GP1 SCL)
from machine import I2C, Pin
import time
BH1750_ADDR = 0x23
CONT_H_RES = 0x10
i2c = I2C(0, sda=Pin(0), scl=Pin(1), freq=100000)
print("I2C scan:", [hex(d) for d in i2c.scan()])
i2c.writeto(BH1750_ADDR, bytes([CONT_H_RES]))
time.sleep_ms(200)
while True:
data = i2c.readfrom(BH1750_ADDR, 2)
raw = (data[0] << 8) | data[1]
lux = raw / 1.2
print("Light: {:.1f} lx".format(lux))
time.sleep(1)