Introduction
In this lesson, we will give the ESP32 a simple sense of light.
When the room is bright, the LED stays off. When the sensor gets dark, the ESP32 turns the LED on automatically.
This project combines several important ideas from earlier lessons: analog input, voltage dividers, Serial Monitor debugging, thresholds, and digital output.
What you will learn
By the end of this tutorial, you should understand:
- What an LDR is
- How light changes resistance
- Why the ESP32 needs a voltage divider to read an LDR
- How to read light level using
analogRead() - How to use Serial Monitor to choose a threshold
- How to build an automatic night light
What is an LDR?
LDR stands for Light Dependent Resistor. It is also called a photoresistor.
An LDR changes resistance depending on how much light hits its surface:
- Bright light: lower resistance
- Darkness: higher resistance
The ESP32 cannot directly read resistance. It reads voltage. So we must convert the changing resistance into a changing voltage.
That is why we use a voltage divider.
For a visual model of the divider, threshold, and LED state, open the interactive lab: LDR Voltage Divider.
LDR voltage divider
A voltage divider uses two resistive elements to create a voltage at the middle point.
For this project:
3.3V
|
LDR
|
GPIO34
|
10k resistor
|
GND
GPIO34 reads the voltage at the middle point.
As the light changes, the LDR resistance changes. That changes the voltage at GPIO34, and the ADC converts that voltage into a number.
Hardware required
- ESP32 DevKit
- LDR photoresistor
- 10k resistor
- LED
- 220 ohm resistor
- Breadboard
- Jumper wires
- USB cable
Wiring
Connect the LDR circuit:
3.3V -> LDR -> GPIO34 -> 10k resistor -> GND
Connect the LED circuit:
GPIO2 -> LED -> 220 ohm resistor -> GND
Use 3.3V for the sensor circuit. Do not connect 5V to the ESP32 analog input.
Read the light sensor
Start by printing the raw sensor value.
const int ldrPin = 34;
void setup()
{
Serial.begin(115200);
}
void loop()
{
int lightValue = analogRead(ldrPin);
Serial.print("Light value: ");
Serial.println(lightValue);
delay(200);
}
Open Serial Monitor and test the sensor:
- Shine light on the LDR
- Cover the LDR with your hand
- Watch how the value changes
Your values may be different from another circuit. That is normal. Different LDRs, resistor values, and room lighting conditions produce different readings.
Choose a threshold
A threshold is the value where your program decides between two states.
For example:
const int threshold = 1800;
The correct threshold depends on your actual readings. Use Serial Monitor first, then choose a value between the bright reading and the dark reading.
Example:
Bright room: 2600
Covered sensor: 900
Good threshold: around 1800
If your divider is reversed, the value may increase in darkness instead of decreasing. That is fine. You can either swap the LDR and resistor positions or change the comparison in code.
Automatic night light code
const int ldrPin = 34;
const int ledPin = 2;
const int threshold = 1800;
void setup()
{
Serial.begin(115200);
pinMode(ledPin, OUTPUT);
}
void loop()
{
int lightValue = analogRead(ldrPin);
Serial.print("Light value: ");
Serial.println(lightValue);
if (lightValue < threshold)
{
digitalWrite(ledPin, HIGH);
}
else
{
digitalWrite(ledPin, LOW);
}
delay(200);
}
The program reads the light value, compares it with the threshold, and controls the LED.
Add simple hysteresis
If the sensor value stays near the threshold, the LED may flicker on and off. One common fix is hysteresis.
Use two thresholds:
const int darkThreshold = 1600;
const int brightThreshold = 2000;
bool ledState = false;
Then:
if (lightValue < darkThreshold)
{
ledState = true;
}
else if (lightValue > brightThreshold)
{
ledState = false;
}
digitalWrite(ledPin, ledState ? HIGH : LOW);
This gives the system a small buffer zone, so the LED does not rapidly switch when the reading is noisy.
Common mistakes
If the value does not change:
- Check the GPIO34 connection
- Check the 3.3V and GND rails
- Make sure the 10k resistor is actually connected to the middle point
- Confirm Serial Monitor baud rate
If the LED logic feels reversed, change < threshold to > threshold, or reverse the voltage divider.
Real engineering use cases
Light sensing is used in:
- Automatic night lights
- Street light controllers
- Display brightness adjustment
- Light meters
- Smart agriculture
- Security systems
This simple project is a beginner version of a very common control pattern: sense the environment, compare with a threshold, and control an output.
Engineering challenge
Change the project so the LED brightness changes gradually with light level instead of only turning on or off.
Hint: map the LDR value to a PWM value from 0 to 255.
Next lesson
Next, we will read real environmental data using a temperature and humidity sensor. That lesson introduces sensor libraries and digital sensor communication.