The BH1750 light sensor is one of the most popular digital ambient light sensors used in hobby electronics and professional projects. Whether you’re building an automatic lamp controller, a smart greenhouse monitor, or a weather station, the BH1750 gives you accurate lux readings over I2C without the headaches of analog conversion. In this comprehensive guide, you’ll learn everything you need to interface the BH1750 with both Arduino and ESP32, from wiring to code to real-world deployment.
What Is the BH1750 Light Sensor?
The BH1750 is a 16-bit digital ambient light sensor IC manufactured by ROHM Semiconductor. Unlike analog LDR (Light Dependent Resistor) modules that require ADC conversion and calibration, the BH1750 directly outputs light intensity in lux units via the I2C protocol. This makes it incredibly easy to integrate with any microcontroller that supports I2C communication.
The sensor is sensitive to visible light and has a spectral response close to the human eye, making its lux readings highly accurate for human-centric lighting applications. It’s widely used in smartphones, tablets, and embedded systems for automatic brightness control.
Key Specifications
- Supply Voltage: 2.4V to 3.6V (VCC pin), logic level 1.8V to 3.6V
- Measurement Range: 1 to 65,535 lux
- Resolution: 1 lux (standard mode), 0.5 lux (high resolution mode)
- Interface: I2C (up to 400 kHz Fast Mode)
- I2C Addresses: 0x23 (ADDR pin LOW) or 0x5C (ADDR pin HIGH)
- Measurement Time: 120 ms (high resolution), 16 ms (low resolution)
- Operating Temperature: -40°C to +85°C
- Current Consumption: 0.12 mA (active), 0.01 mA (power down)
- No External Components Required
The GY-302 breakout board (the most common BH1750 module) includes an onboard 3.3V regulator and level shifters, making it safe to use directly with 5V Arduino boards without a separate level converter.
How It Works
The BH1750 uses a photodiode array that converts incident light into a current proportional to the lux level. This current is then integrated and digitized by a built-in 16-bit ADC. The digital result is transmitted over I2C to your microcontroller. Here’s the internal flow:
- Photodiode captures incoming photons and generates a current
- Integration circuit collects the charge over a set measurement time
- ADC converts the charge to a 16-bit digital value
- I2C output register holds the result ready for reading
The raw register value is divided by 1.2 to get the lux reading: Lux = Raw Value / 1.2. In high-resolution mode 2, this becomes Lux = Raw Value / 2.4.
Wiring BH1750 with Arduino
Connecting the BH1750 (GY-302 module) to an Arduino Uno or Nano is straightforward. The module uses I2C, so only 4 wires are needed:
| BH1750 Pin | Arduino Pin | Description |
|---|---|---|
| VCC | 3.3V or 5V | Power supply |
| GND | GND | Ground |
| SDA | A4 (SDA) | I2C Data |
| SCL | A5 (SCL) | I2C Clock |
| ADDR | GND or 3.3V | I2C address select |
Note for Arduino Mega: SDA is pin 20, SCL is pin 21. For Arduino Leonardo: SDA is pin 2, SCL is pin 3.
The GY-302 module already has 4.7kΩ pull-up resistors on SDA and SCL lines, so you don’t need external pull-ups when using this breakout board.
Wiring BH1750 with ESP32
The ESP32 runs at 3.3V logic, which is perfectly compatible with the BH1750. The default I2C pins on most ESP32 dev boards are:
| BH1750 Pin | ESP32 Pin | Description |
|---|---|---|
| VCC | 3.3V | Power supply |
| GND | GND | Ground |
| SDA | GPIO 21 | I2C Data |
| SCL | GPIO 22 | I2C Clock |
| ADDR | GND | I2C address 0x23 |
You can reassign I2C pins on ESP32 using the Wire.begin(SDA_PIN, SCL_PIN) function, giving you full flexibility for custom PCB designs.
Installing the Library
The easiest library for BH1750 is the BH1750 by Christopher Laws, available directly in the Arduino Library Manager. To install it:
- Open Arduino IDE
- Go to Sketch → Include Library → Manage Libraries
- Search for “BH1750”
- Click Install on “BH1750 by Christopher Laws”
Alternatively, for PlatformIO, add lib_deps = claws/BH1750@^1.3.0 to your platformio.ini.
Arduino Code & Explanation
Here’s a complete working sketch for Arduino to read lux values from the BH1750 every second:
#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 successfully");
} else {
Serial.println("Error initializing BH1750");
while (1); // Halt if sensor not found
}
}
void loop() {
if (lightMeter.measurementReady()) {
float lux = lightMeter.readLightLevel();
Serial.print("Light: ");
Serial.print(lux);
Serial.println(" lx");
}
delay(1000);
}
Code Explanation:
BH1750::CONTINUOUS_HIGH_RES_MODE— enables continuous measurement at 1 lux resolutionlightMeter.measurementReady()— checks if the sensor has completed a measurementlightMeter.readLightLevel()— returns the lux value as a float
Open the Serial Monitor at 9600 baud and you’ll see live lux readings updating every second.
ESP32 Code & IoT Integration
The ESP32 code is nearly identical but includes Wi-Fi capability for IoT use cases. Here’s an example that reads BH1750 values and publishes them to an MQTT broker:
#include <Wire.h>
#include <BH1750.h>
#include <WiFi.h>
#include <PubSubClient.h>
const char* ssid = "YOUR_WIFI_SSID";
const char* password = "YOUR_WIFI_PASSWORD";
const char* mqttServer = "broker.hivemq.com";
const int mqttPort = 1883;
const char* mqttTopic = "zbotic/light";
BH1750 lightMeter;
WiFiClient espClient;
PubSubClient client(espClient);
void setup() {
Serial.begin(115200);
Wire.begin(21, 22); // SDA=21, SCL=22
lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("nWiFi connected!");
client.setServer(mqttServer, mqttPort);
}
void loop() {
if (!client.connected()) {
client.connect("ESP32_BH1750");
}
client.loop();
if (lightMeter.measurementReady()) {
float lux = lightMeter.readLightLevel();
char luxStr[10];
dtostrf(lux, 6, 2, luxStr);
client.publish(mqttTopic, luxStr);
Serial.printf("Published: %s luxn", luxStr);
}
delay(5000);
}
This setup allows you to monitor ambient light levels remotely — perfect for smart home dashboards (Home Assistant, Node-RED) or automated lighting systems.
Measurement Modes Explained
The BH1750 supports multiple measurement modes that trade off speed against resolution:
| Mode | Resolution | Measurement Time | Best For |
|---|---|---|---|
| CONTINUOUS_HIGH_RES_MODE | 1 lux | 120 ms | General use |
| CONTINUOUS_HIGH_RES_MODE_2 | 0.5 lux | 120 ms | High precision |
| CONTINUOUS_LOW_RES_MODE | 4 lux | 16 ms | Fast updates |
| ONE_TIME_HIGH_RES_MODE | 1 lux | 120 ms | Battery saving |
Pro tip: Use ONE_TIME_HIGH_RES_MODE in battery-powered projects. The sensor automatically powers down after each measurement, reducing current consumption dramatically.
I2C Address Selection
One powerful feature of the BH1750 is that you can run two sensors on the same I2C bus by using the ADDR pin:
- ADDR = LOW (GND): I2C address
0x23(default) - ADDR = HIGH (VCC/3.3V): I2C address
0x5C
To use a custom address in code:
BH1750 lightMeter1(0x23); // ADDR pin to GND
BH1750 lightMeter2(0x5C); // ADDR pin to 3.3V
lightMeter1.begin();
lightMeter2.begin();
This is useful in differential light measurement setups, such as comparing sunlight on top of a structure vs. shaded areas below.
Real-World Applications
- Automatic Street/Room Lighting: Turn lights on when lux drops below a threshold (e.g., 50 lux)
- Smart Greenhouse: Monitor sunlight levels and trigger grow lights when clouds reduce natural light
- Solar Panel Optimization: Track irradiance to calculate panel efficiency
- Photography Assistant: Build an Arduino light meter for camera exposure calculation
- Weather Station: Add cloud cover estimation alongside BMP280 pressure data
- Screen Auto-Brightness: Adjust LCD backlight PWM based on ambient lux
- Security Systems: Detect sudden changes in light that might indicate an intrusion
BMP280 Barometric Pressure and Altitude Sensor I2C/SPI Module
Pair with BH1750 to build a complete weather station — measures pressure, altitude, and temperature alongside your light readings on the same I2C bus.
DHT11 Digital Relative Humidity and Temperature Sensor Module
Add temperature and humidity sensing to your BH1750 light project for a comprehensive environmental monitoring station.
Troubleshooting Tips
- “Error initializing BH1750”: Check your wiring. Use an I2C scanner sketch to confirm the sensor is detected at address 0x23 or 0x5C.
- Always reading 0 lux: Ensure the ADDR pin is connected (even to GND). A floating ADDR pin causes unstable addresses.
- Inconsistent readings: Add bypass capacitors (100nF) between VCC and GND close to the sensor pin.
- I2C conflict: If another sensor shares the bus, check for address conflicts. BH1750’s 0x23 clashes with SHT21/SI7021 in some configurations.
- ESP32 I2C timeout: Slow I2C speed by calling
Wire.setClock(100000)before initialization. - GY-302 on 5V Arduino: The module’s onboard regulator handles 5V input. Do NOT apply 5V to the VCC pin of the bare IC — it only accepts 3.6V max.
Frequently Asked Questions
The BH1750 can measure from 1 lux up to 65,535 lux. Direct sunlight is approximately 100,000 lux, so the sensor may saturate in extreme outdoor conditions. For very high brightness, use the sensor in a shaded enclosure.
Yes. Enable I2C on Raspberry Pi via raspi-config, install the smbus2 Python library, and read the sensor using Python. The wiring is the same as ESP32 (3.3V I2C).
In standard conditions, the BH1750 is accurate to ±20% compared to calibrated instruments. This is sufficient for most automation applications. For lab-grade accuracy, use a dedicated calibrated sensor like the TSL2591.
The BH1750 is designed to be insensitive to infrared light, which is a key advantage over LDRs. Its spectral response closely matches the human eye (peak sensitivity around 560nm), making its lux readings perceptually relevant.
The bare IC maximum is 3.6V, but the GY-302 module has a regulator and can accept 3.3V–5V on VCC. For LiPo use, add a voltage regulator to bring 3.7V down to 3.3V, or use the ONE_TIME mode to minimize current draw.
The BH1750 is an excellent choice for any light-sensing project thanks to its digital I2C output, high accuracy, and low power consumption. Whether you’re automating your home lighting or building a professional environmental monitor, this sensor delivers reliable results with minimal code. Explore our full range of sensors and modules at Zbotic and start building today!
Add comment