If you are building an automated lighting system, a solar tracker, or a smart-home lux meter, you need to measure ambient light accurately. But grabbing a random sensor from your parts bin and reading an analog pin rarely yields usable data. To get reliable physical units (Lux) instead of arbitrary microcontroller numbers, you must understand the underlying physics, the exact output signal type, and the mathematical scaling required for your specific microcontroller.
The Physics: How Does a Light Sensor Work at the Silicon Level?
At the core of every light sensor is the photoelectric effect, but the physical implementation splits into two distinct categories. In a photoresistor (or Light Dependent Resistor, LDR), the active material is typically cadmium sulfide (CdS). When photons strike the semiconductor lattice, they transfer energy to bound electrons, exciting them into the conduction band. This increases the number of charge carriers, which directly lowers the electrical resistance of the material. The brighter the light, the lower the resistance, dropping from several megaohms in total darkness to a few hundred ohms in direct sunlight.
In silicon-based sensors like photodiodes, phototransistors, and integrated digital ICs (like the BH1750), the mechanism relies on a PN junction. Photons with sufficient energy strike the depletion region of the junction, generating electron-hole pairs. If the junction is reverse-biased (photoconductive mode), these carriers are swept across the junction, creating a measurable photocurrent strictly proportional to the irradiance. Integrated digital sensors take this raw photocurrent, pass it through an internal transimpedance amplifier, and digitize it via an onboard ADC, completely abstracting the analog physics from your microcontroller.
Analog vs. Digital: What the Output Actually Is
The most common mistake in sensor interfacing is conflating analog resistance changes with digital data streams. The output signal dictates your circuit design and your firmware math.
Analog Output: The LDR Voltage Divider
An LDR does not output a voltage; it outputs a variable resistance. To read it with an ESP32 or Arduino, you must build a voltage divider using a fixed resistor (typically 10kΩ). The actual output to your microcontroller's ADC pin is a voltage between 0V and VCC.
1. Circuit Voltage:
V_out = V_cc × (R_fixed / (R_LDR + R_fixed))2. ADC Raw to Voltage (12-bit ESP32):
Voltage = (Raw_ADC / 4095.0) × 3.3V3. Voltage to Resistance:
R_LDR = R_fixed × ((V_cc / Voltage) - 1)4. Resistance to Lux (Approximation):
Lux = 500 / (R_LDR_in_kOhms)
Digital Output: The BH1750 I2C Stream
The Rohm BH1750FVI is a digital ambient light sensor. Its output is not a voltage, but a 16-bit integer transmitted over the I2C bus. Because it contains a built-in photodiode, an op-amp, and an ADC specifically tuned to the human eye's spectral sensitivity curve, it completely bypasses the need for external resistors and complex logarithmic math.
1. Read two bytes from I2C (High byte, Low byte).
2. Combine into 16-bit integer:
Raw = (HighByte << 8) | LowByte3. Raw to Lux:
Lux = Raw / 1.2
Wiring and Pinout Reference
Below is the hardware interface specification for wiring both sensor types to a 3.3V logic microcontroller like the ESP32 DevKit V1. Note the supply ranges: while the BH1750 has an onboard voltage regulator allowing 3.3V to 5V input, the LDR divider should be tied to the microcontroller's native 3.3V rail to prevent overvoltage on the ADC pin.
| Sensor Module | Supply Range | Sensor Pin | ESP32 Pin | Signal Type |
|---|---|---|---|---|
| GL5528 LDR (with 10kΩ pulldown) | 3.3V DC | VCC | 3V3 | Power |
| VOUT (Divider midpoint) | GPIO 34 (ADC1_CH6) | Analog Voltage (0-3.3V) | ||
| GY-302 (BH1750 Breakout) | 3.3V - 5.0V DC | VCC | 5V or 3V3 | Power |
| GND | GND | Ground | ||
| SCL | GPIO 22 | I2C Clock | ||
| SDA | GPIO 21 | I2C Data |
Note: The BH1750 ADDR pin is left floating for the default I2C address (0x23). Tie it to VCC to shift the address to 0x5C if you need two sensors on the same bus.
Calibration, Scaling, and Real-World Interference
Reading the raw data is only half the battle. Environmental interference and spectral mismatch will ruin your data if you do not account for them in hardware or firmware.
Common Interference Sources
- 50/60Hz Mains Flicker: AC-powered LEDs and fluorescent bulbs pulse at 100Hz or 120Hz. An LDR paired with a fast ADC sampling rate will capture this ripple, resulting in wild Lux swings. Fix: The BH1750 solves this in hardware via its integration time (typically 120ms), which averages the light over multiple AC cycles. For an LDR, you must implement a software moving-average filter or sample exactly on the zero-crossings.
- Infrared (IR) Contamination: Cadmium sulfide LDRs are highly sensitive to infrared light. If you place an LDR near an incandescent bulb or a heat source, it will read artificially high because it is 'seeing' the thermal IR radiation. The BH1750 features an integrated IR rejection filter that mimics the human eye, ignoring heat signatures.
- ADC Non-Linearity: The ESP32 ADC is notoriously non-linear at the extreme ends of its 0-3.3V range (below 0.15V and above 3.1V). If your LDR voltage divider pushes into these zones, your Lux calculations will drift.
Calibration and Scaling Requirements
LDRs do not have a linear response to light; they follow a logarithmic curve. To get accurate Lux from a GL5528, you must plot the resistance against known Lux values (using a calibrated commercial light meter) on a log-log graph and extract the gamma slope. Conversely, the BH1750 is factory-calibrated to output Lux directly, but it requires cosine correction. If light strikes the BH1750's glass epoxy housing at a steep angle (greater than 45°), the internal reflections will cause the reading to drop off faster than the actual physical irradiance. For precise setups, mount the sensor perfectly parallel to the light source or use a diffusing PTFE dome.
Decision Matrix: Which Light Sensor Should You Buy?
Do not waste time guessing which component fits your project. Use this decision path to select the right hardware for your specific application constraints.
| If your project requires... | Then choose... | Why? |
|---|---|---|
| Simple day/night detection (is it dark or light?) | Bare GL5528 LDR + 10kΩ Resistor | Costs $0.10. Analog thresholding is trivial for binary triggers like turning on a porch light. |
| High-speed optical encoding or laser tripwires | BPW34 Photodiode + Transimpedance Amp | LDRs are too slow (20ms response time). Photodiodes react in nanoseconds. |
| Accurate ambient room Lux for smart-home displays, grow tents, or screen backlighting | GY-302 BH1750 Module | Provides true Lux via I2C, rejects IR heat, and handles 50/60Hz flicker automatically. |
The Default Pick: GY-302 BH1750 Module
For 90% of embedded maker projects, stop using bare LDRs and buy the GY-302 BH1750 breakout board (typically $2.50 to $4.00 on Amazon or Adafruit). The time you save not writing logarithmic scaling algorithms, not designing voltage dividers, and not fighting IR contamination from room heaters vastly outweighs the minor cost increase over a $0.10 cadmium sulfide cell. Wire it to your I2C bus, divide the 16-bit raw payload by 1.2, and you will have scientifically usable Lux data in under five minutes.






