An LDR (Light Dependent Resistor), typically manufactured from Cadmium Sulphide (CdS), is a passive two-terminal component whose electrical resistance drops inversely as incident light intensity increases. In total darkness, a standard GL5528 LDR exhibits a 'dark resistance' ranging from 1 MΩ to 10 MΩ. Under bright, direct sunlight (approximately 10,000 lux), that same resistance plummets to 1 kΩ or lower, allowing significantly more current to flow through the circuit.

This behavior relies on photoconductivity. When photons with sufficient energy strike the CdS semiconductor lattice, they excite bound electrons into the conduction band, creating electron-hole pairs that facilitate current flow. Because of the material's specific bandgap, CdS cells feature a spectral response peaking around 540 nm (green-yellow light), which closely mimics the human eye's sensitivity. However, they suffer from slow response times—typically 20 ms to 50 ms—making them useless for high-speed optical data transmission but perfectly adequate for ambient light tracking, streetlamp triggering, and display backlight dimming.

Wiring the LDR Sensor to a Microcontroller

The most common beginner mistake is treating a bare LDR like an active sensor module. A raw LDR outputs resistance, not voltage. It has no polarity, no VCC pin, and no GND pin. To interface it with the analog-to-digital converter (ADC) of an Arduino, ESP32, or Raspberry Pi Pico, you must build a voltage divider circuit using a fixed resistor.

Module vs. Bare Component: Many cheap 'LDR modules' sold online feature 4 pins (VCC, GND, DO, AO). The DO (Digital Out) pin simply fires HIGH or LOW based on a threshold set by an onboard LM393 comparator and potentiometer. The AO (Analog Out) pin provides the raw divided voltage. If you need actual light intensity measurements, always read the AO pin, never the DO pin.

For a bare GL5528 LDR, a 10 kΩ fixed resistor is the standard pairing. This provides the widest usable voltage swing across typical indoor and outdoor lighting conditions. Place the LDR on the high side (connected to VCC) and the fixed resistor on the low side (connected to GND). The analog output is read from the node between them. As light increases, the LDR's resistance drops, and the output voltage rises.

LDR Voltage Divider Wiring & Specifications
Node / Pin Connection Supply Range & Notes
LDR Leg 1 Microcontroller VCC (3.3V or 5V) Max power dissipation is typically 100mW. Keep VCC ≤ 5V.
LDR Leg 2 Microcontroller Analog Pin (e.g., A0) High-impedance input. Keep wire runs under 12 inches to avoid noise.
Fixed Resistor (10kΩ) Between Analog Pin and GND 1% tolerance metal film recommended for stable baseline.
Filter Capacitor (Optional) 100nF Ceramic between Analog Pin and GND Creates a hardware low-pass filter to kill 50/60Hz mains flicker.

Output Signal Math: From Raw ADC to Lux

To convert the microcontroller's raw ADC integer into a meaningful physical unit (Lux), you must pass the value through three distinct mathematical stages. We will assume a 10-bit ADC (like the Arduino Uno) with a 5V reference, a 10 kΩ fixed resistor, and a GL5528 LDR.

Step 1: ADC Raw to Voltage

First, convert the 0-1023 integer back into the actual voltage sitting at the analog pin.

V_out = (ADC_raw / 1023.0) * V_ref

Example: If the ADC reads 682 and V_ref is 5V, V_out = (682 / 1023) * 5 = 3.33V.

Step 2: Voltage to LDR Resistance

Next, use the voltage divider formula, rearranged to solve for the LDR's current resistance. Because the LDR is on the high side (VCC), the formula is:

R_ldr = R_fixed * ((V_cc / V_out) - 1)

Example: R_ldr = 10000 * ((5.0 / 3.33) - 1) = 10000 * 0.501 = 5015 Ω.

Step 3: Resistance to Lux (The Log-Log Curve)

CdS photoresistors do not have a linear response; their resistance-to-lux relationship is logarithmic. The standard datasheet approximation formula is R = A * Lux^(-γ). By rearranging this and using the known resistance at 10 lux (R_10), we get the working formula for illuminance:

Lux = (R_10 / R_ldr)^(1 / γ) * 10

For a typical GL5528, the resistance at 10 lux (R_10) is roughly 15,000 Ω, and the slope factor (γ) is approximately 0.7.

Example: Lux = (15000 / 5015)^(1 / 0.7) * 10 = (2.99)^1.428 * 10 = 4.8 * 10 = 48 Lux.

ESP32 ADC Non-Linearity Warning: The ESP32's internal ADC is notoriously non-linear near the 0V and 3.3V rails, and its attenuation curves can skew raw readings by up to 15%. When using an ESP32, always use the analogReadMilliVolts() function in the modern Arduino core to leverage the factory-calibrated eFuse lookup tables, and design your voltage divider so the expected V_out stays between 0.2V and 2.5V. See the Espressif ADC documentation for hardware attenuation mapping.

Calibration, Scaling, and Interference

The math above provides a baseline, but manufacturing tolerances for CdS cells are notoriously wide. The R_10 and γ values can drift by ±20% from batch to batch. If you need accurate lux readings for a specific application (like a plant grow-light monitor), you must perform a two-point calibration.

  1. Place your LDR circuit next to a calibrated commercial lux meter in a dim room (e.g., 20 lux). Record the calculated LDR lux value.
  2. Move both to a bright environment (e.g., 500 lux). Record the new values.
  3. Calculate a linear scaling multiplier in your code to map the LDR's calculated output to the commercial meter's known output across that specific range.

Common Interference Sources:
The most frequent issue makers face is 'noisy' or fluctuating LDR readings indoors. This is rarely a code bug; it is physics. Indoor LED and fluorescent lighting is powered by AC mains, causing the light output to flicker at 100 Hz or 120 Hz (twice the 50/60 Hz line frequency). While the LDR's slow 20ms response time naturally averages out some of this, the high-impedance ADC input of a microcontroller can still sample the peaks and troughs of the ripple.

The Fix: Solder a 100 nF (0.1 µF) ceramic capacitor directly across the analog pin and GND. This creates a hardware RC low-pass filter with the 10 kΩ divider resistor, yielding a cutoff frequency of roughly 159 Hz, effectively smoothing out the mains flicker before the ADC ever sees it. Additionally, be aware that CdS cells exhibit significant temperature drift; resistance can shift by 10-15% across a 0°C to 50°C ambient range.

LDR Sensor FAQ

How to calibrate an LDR sensor for accurate lux readings?

Because factory datasheets only provide typical curves, true accuracy requires empirical calibration. Write a test sketch that outputs the raw calculated lux to the serial monitor. Place a calibrated lux meter (or a high-end smartphone ambient light sensor app) next to the LDR. Take readings at three distinct light levels: deep shadow (~5 lux), typical office lighting (~300 lux), and direct sunlight (~10,000 lux). Adjust the R_10 constant in your code until the software output matches the physical meter at the middle range, then apply a software multiplier to align the high and low extremes.

Why is my LDR sensor reading fluctuating under indoor lights?

This is caused by 100/120 Hz AC mains flicker inherent to indoor lighting. The microcontroller's ADC is sampling the light wave's peaks and valleys faster than the LDR's physical response time can average them out. To fix this, add a 100nF ceramic capacitor between the analog input pin and ground to create a hardware low-pass filter. If hardware modification isn't possible, implement a software exponential moving average (EMA) filter in your code, taking 20 rapid samples and averaging them before updating your main loop variable.

LDR sensor vs BH1750: Which should I use for light metering?

Use the BH1750 if you need precise, calibrated lux measurements. The BH1750 is an active I2C digital sensor with a built-in ADC, internal calibration, and an integrated IR-rejection filter, outputting direct lux values with ±10% accuracy. Use an LDR sensor only when you need a cheap, simple, high-voltage-tolerant analog trigger (like a dusk-to-dawn relay), or when you are constrained to basic analog pins and don't want to deal with I2C pull-up resistors and address conflicts.

Can I wire an LDR sensor directly to a Raspberry Pi GPIO?

No, not directly. The Raspberry Pi (unlike the Pico) lacks a built-in analog-to-digital converter (ADC) on its GPIO header. An LDR outputs a variable analog voltage via a divider, which a digital Pi GPIO pin cannot read. To use an LDR with a standard Raspberry Pi, you must either route the analog signal through an external ADC chip (like the MCP3008 via SPI), or use a 555-timer astable circuit where the LDR controls the capacitor charge rate, allowing the Pi to measure light intensity by timing the digital pulse frequency.