Reading Light Intensity with the ESP32 LDR Module
Real-time monitoring of the LDR module's raw ADC value and relative light percentage calculated from dark and light reference values in the Serial Monitor. This percentage is not a lux measurement. Teaches the module’s calibration logic. It is ideal to complete this before Project 10, as it is used to determine the threshold value.

Video
Circuit Diagram

Source Code
1// ─────────────────────────────────────────
2// BlueGrays · bluegrays.com
3// Reading Light Intensity with the ESP32 LDR Module
4// ─────────────────────────────────────────
5// Reads the analog output (AO) of the LDR module with the 12-bit ADC and
6// converts it to a 0-100 light percentage using the calibration values.
7// The result is printed to the Serial Monitor (115200 baud) every 0.5 s.
8//
9// Pins:
10// GPIO 34 (classic ESP32) / GPIO 1 (ESP32-S2/S3) -> LDR module AO
11// LDR module VCC -> 3V3, GND -> GND
12
13#if defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
14 const int LDR_PIN = 1; // ESP32-S2/S3: ADC1_CH0
15#else
16 // Classic ESP32 DevKit V1: ADC1_CH6, input-only. GPIO 1 clashes with Serial TX here
17 const int LDR_PIN = 34;
18#endif
19
20// Calibration: measure in your own room and enter the values here. On the LDR module the AO voltage
21// (and raw) DROPS as the light gets brighter.
22const int RAW_DARK = 4000; // Dark raw
23const int RAW_LIGHT = 100; // Light raw
24
25void setup() {
26 Serial.begin(115200);
27 analogReadResolution(12); // Force 12-bit
28 Serial.println("LDR Okuma / LDR Reading");
29 Serial.println("-----------------------------");
30}
31
32void loop() {
33 int raw = analogRead(LDR_PIN);
34 // Clip to the calibration range, dark = 0%
35 int clipped = constrain(raw, RAW_LIGHT, RAW_DARK);
36 int percent = map(clipped, RAW_DARK, RAW_LIGHT, 0, 100);
37
38 Serial.print("Raw: ");
39 Serial.print(raw);
40 Serial.print(" | Light: %");
41 Serial.println(percent);
42
43 delay(500);
44}
45FAQ
What values does the ESP32's ADC return?▾
The ESP32's ADC is 12-bit and returns values ranging from 0 to 4095. Since this differs from the 0–1023 range on the Arduino Uno, you should adjust your thresholds and calculations accordingly.
Analog readings are distorted when Wi-Fi is on. Why?▾
On the ESP32, the ADC2 channel (GPIO 0, 2, 4, 12–15, 25–27) cannot be used while Wi-Fi is enabled. Connecting analog sensors to the ADC1 pins (GPIO 32–39) prevents this issue.
Is the reading the actual lux value?▾
No, this code does not calculate lux; it displays the raw ADC value and a relative light percentage based on the selected dark and light reference values. The LDR's response is not linear and varies from model to model. For precise lux measurement, a calibrated sensor such as the BH1750 is used.
Why does the ESP32 ADC give incorrect readings at the extremes?▾
The ESP32's ADC is not linear near 0 V and 3.3 V. The `analogReadMilliVolts()` function returns calibrated values; for critical measurements, operating within the 0.1–3.1 V range yields the most accurate results.
