Light sensors are some of the simplest and most useful components in IoT projects — automatic lighting, plant monitors, weather stations, and security systems all need some way to measure brightness. But the two most common options, the LDR and the BH1750, work in fundamentally different ways. This guide explains the differences and helps you pick the right one.
🔗Quick Recommendations
- Simple light/dark detection (lamp on at sunset, wake on daylight): LDR — cheapest, simplest, no library needed.
- Accurate lux measurements (data logging, grow lights, display brightness): BH1750 — calibrated digital output, consistent between units.
- Multiple light zones on one bus: BH1750 — two sensors on I2C with different addresses, no extra ADC pins used.
🔗Comparison Table
| Feature | LDR (Photoresistor) | BH1750 |
|---|---|---|
| Output type | Analog (voltage divider) | Digital (I2C) |
| Measurement | Relative (0–4095 ADC) | Calibrated lux ($1\text{--}65{,}535\,\text{lx}$) |
| Accuracy | Uncalibrated — varies between units | Calibrated to human-eye spectral response |
| Resolution | 12-bit ADC (ESP32) | $1\,\text{lx}$ in high-resolution mode |
| Interface | 1 analog GPIO + voltage divider | I2C (SDA + SCL) |
| I2C address | N/A | 0x23 (default) or 0x5C |
| Supply voltage | $3.3\text{--}5\,\text{V}$ | $2.4\text{--}3.6\,\text{V}$ |
| Library needed | No | Yes (BH1750 by Christopher Laws) |
| Price | Very cheap (~$0.10) | Budget (~$1–2) |
| Multi-sensor | Uses one ADC pin each | Two on same I2C bus, no extra pins |
🔗When the LDR Is Enough
The LDR is a passive resistor whose resistance drops as light increases. You read it through a voltage divider connected to an ADC pin. The raw value tells you "brighter" or "darker" but not how many lux you are measuring.
This is perfectly fine when:
- You only need light vs. dark (threshold-based decisions)
- You are comparing readings from the same sensor over time (relative changes)
- You want the simplest possible circuit (two components, no library)
- You are on a tight budget or prototyping quickly
The main limitations:
- No calibration — two LDRs under the same light give different ADC values
- Non-linear response — the relationship between resistance and lux is logarithmic, making precise measurement difficult
- Uses an ADC pin — the ESP32 has a limited number of ADC1 channels (ADC2 is unavailable when WiFi is active)
- Temperature sensitive — resistance shifts with ambient temperature
Tip: If you are using WiFi, remember that only ADC1 (GPIOs 32–39) works reliably on the ESP32. ADC2 pins conflict with the WiFi driver.
🔗When to Choose the BH1750
The BH1750 is a digital sensor that outputs a calibrated lux value over I2C. It matches the spectral sensitivity of the human eye, so the readings correspond to how bright a scene actually looks to a person.
Choose the BH1750 when:
- You need actual lux values (for data logging, display auto-brightness, or comparing locations)
- You want consistent readings between different sensor units
- You are already using I2C for other devices (BME280, OLED, etc.) — no extra pins needed
- You need two light sensors — the BH1750 supports addresses
0x23and0x5Con the same bus
The BH1750 is only slightly more expensive than an LDR breakout board, and for most I2C-based projects it is the more practical choice.
🔗Other Light Sensors Worth Knowing
If neither the LDR nor BH1750 fits your project, there are a few other options:
| Sensor | What It Adds | Interface | I2C Address | Notes |
|---|---|---|---|---|
| TSL2591 | Very high dynamic range ($188\,\mu\text{lx}$ to $88{,}000\,\text{lx}$) | I2C | 0x29 | Separate visible + IR channels; great for outdoor use |
| VEML7700 | Wide range with auto-gain ($0\text{--}120{,}000\,\text{lx}$) | I2C | 0x10 | Simpler API than TSL2591; good general-purpose upgrade |
| MAX44009 | Ultra-low power ($0.65\,\mu\text{A}$) | I2C | 0x4A / 0x4B | Ideal for battery-powered projects |
These are all I2C sensors with Adafruit or SparkFun libraries available. They follow the same wiring pattern as the BH1750 (VCC, GND, SDA, SCL) and can share the bus with other I2C devices.
🔗I2C Address Quick Reference
If you are combining light sensors with other I2C devices, check for conflicts:
| Sensor | Default | Alternate |
|---|---|---|
| BH1750 | 0x23 | 0x5C |
| TSL2591 | 0x29 | — |
| VEML7700 | 0x10 | — |
| MAX44009 | 0x4A | 0x4B |
None of these conflict with common temperature/humidity sensors (BME280 at 0x76, SHT31 at 0x44) or OLED displays (0x3C).
🔗Which Should You Pick?
| Your Situation | Recommended | Why |
|---|---|---|
| First project, learning GPIOs | LDR | No library, teaches voltage dividers and ADC basics |
| Automatic outdoor lighting | LDR | Simple threshold detection is all you need |
| Data logging / science project | BH1750 | Calibrated, repeatable lux values |
| Plant grow light monitoring | BH1750 | Consistent readings for comparing light levels |
| Battery-powered sensor node | MAX44009 | Ultra-low power draw |
| Outdoor weather station | TSL2591 | Handles full sunlight without saturating |
| Already using I2C, want to add light | BH1750 | Shares the bus, no extra pins |
🔗Next Steps
- Read our individual guides: LDR, BH1750
- Combine a light sensor with a relay for automatic lighting control
- Add light data to a weather station alongside temperature and humidity
- Display light levels on an OLED screen