No money? No problem! Help us pay the cloud hosting bills without opening your wallet—just give
this ad link a click!😉💸
Do you want your electronics projects to react automatically to changing light levels in a room? In this tutorial, you will discover how to build an intelligent light detection system using an Arduino Uno, a photoresistor (LDR), and two indicator LEDs.
This guide explains both the technical reasons (the “why”) and the step-by-step implementation (the “what”) behind this popular maker project.
Why Build a Light Detector with a Photoresistor?
Human eyes naturally adapt to daylight and darkness; however, microcontrollers need external sensors to perceive environmental changes. Engineers regularly use photoresistors to automate streetlights, adjust smartphone display brightness, and steer solar panels toward the sun.
1. Why We Need a Voltage Divider Circuit
A photoresistor, commonly known as a Light Dependent Resistor (LDR), alters its electrical resistance in response to ambient brightness. When bright light hits the sensor face, its resistance drops from over 100 kΩ in complete darkness down to just a few hundred ohms.
However, microcontrollers such as the ATmega328P on the Arduino cannot measure electrical resistance directly. Instead, the Arduino’s analog-to-digital converter (ADC) only samples voltage between 0V and 5V.
Therefore, we must convert variable resistance into a proportional voltage signal. To achieve this, we pair the LDR with a fixed 10 kΩ pull-down resistor to create a voltage divider circuit.
VA0=5V × (10 kΩ (RLDR + 10 kΩ))
10 kΩAs light intensity increases, the LDR resistance (RLDR) drops. Consequently, a greater share of the 5V supply falls across the fixed 10 kΩ resistor, driving the voltage at analog pin A0 higher.
2. Why Choose a 10kΩ Resistor?
Because the photoresistor’s resistance swings between roughly 1 kΩ (bright room) and 100 kΩ (dark room), a 10 kΩ resistor sits near the geometric center of that dynamic range. As a result, this value produces the largest possible voltage swing under standard indoor lighting, maximizing sensor sensitivity.
3. Why Use 220Ω Resistors with the LEDs?
Furthermore, standard 5mm LEDs cannot tolerate the direct 5V output of Arduino digital pins. Without current limiting, excessive current would quickly destroy the LEDs and risk burning out the microcontroller’s output driver. For this reason, we insert 220Ω current-limiting resistors in series with both the red and green LEDs, capping the current at a safe 15 to 20 mA.
What Has Been Done: Circuit Design and Hardware Setup
To implement this project, we assemble the hardware around an Arduino board using a breadboard and jumper wires.
Hardware Component List
- 1× Arduino Board (Uno, Nano, or compatible)
- 1× Photoresistor (LDR) (Standard 5mm CDS cell)
- 1× 10kΩ Fixed Resistor (Voltage divider pull-down)
- 2× 220Ω Resistors (Current limiters for LEDs)
- 1× Green LED (Indicates bright light)
- 1× Red LED (Indicates darkness)
- Solderless Breadboard & Jumper Wires
Circuit Architecture
The circuit divides into three distinct functional branches:

- Light Sensor Branch: First, we connect one terminal of the LDR to 5V and the second terminal to analog pin A0. Next, we bridge that same A0 junction through the 10 kΩ resistor to GND.
- Green LED Branch: In addition, we connect digital pin 12 to the anode (longer leg) of the Green LED through a 220Ω resistor, returning the cathode (flat edge) to GND.
- Red LED Branch: Likewise, we connect digital pin 13 to the anode of the Red LED through another 220Ω resistor, terminating its cathode at GND.
(You can inspect the source circuit files at circuit.mmd and the visual schematic at circuit.jpg.)
What Has Been Done: Software and Code Logic
The Arduino sketch, found in photoresistor.ino, coordinates the sensor inputs and LED outputs in real time:
int readPin = A0;
int readVal;
int dv = 250;
int redPin = 13;
int greenPin = 12;
void setup() {
// put your setup code here, to run once:
pinMode(readPin, INPUT);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
readVal = analogRead(readPin);
Serial.println(readVal);
delay(dv);
if (readVal > 400) {
digitalWrite(greenPin, HIGH);
digitalWrite(redPin, LOW);
} else {
digitalWrite(redPin, HIGH);
digitalWrite(greenPin, LOW);
}
}
Step-by-Step Code Walkthrough
- Pin and Variable Configuration: At the top of the program, we assign descriptive variable names to our pins (
readPin = A0,redPin = 13,greenPin = 12). In addition, we declare a delay variable (dv = 250) to control sampling frequency. - Setup Initialization (
setup()): First, thesetup()function configures pinA0as anINPUTto read voltage signals and defines pins12and13asOUTPUTs to power the LEDs. Furthermore, it opens serial communication at9600baud so you can observe live readings in the Arduino Serial Monitor. - Analog Sampling (
analogRead()): Next, insideloop(), the microcontroller samples pinA0. The internal 10-bit ADC quantizes the input voltage (0V–5V) into numerical integer values ranging from0to1023. - Serial Telemetry: Immediately following each sample, the program transmits the raw integer over the USB serial connection and waits 250 milliseconds. Therefore, the system updates smoothly four times per second without flooding the serial buffer.
- Threshold Decision Logic: Finally, an
if-elseblock evaluatesreadValagainst a preset threshold of 400 (representing approximately 1.95V):- Bright Environment (
readVal > 400): The Arduino drives pin12HIGHto light the Green LED and pulls pin13LOWto extinguish the Red LED. - Dark Environment (
readVal <= 400): Conversely, when you cover the LDR or dim the room lights, the reading drops below 400. The microcontroller immediately turns on the Red LED and turns off the Green LED.
- Bright Environment (
Practical Applications and Next Steps
Now that you have built this foundational circuit, you can expand it into several exciting real-world applications:
- Automatic Night Lamps: You can substitute the red LED with a 5V relay module to switch standard AC room lamps on and off automatically.
- Hysteresis Smoothing: You can add software hysteresis (for instance, turning ON at 380 and OFF at 430) to prevent LED flickering when ambient light wavers near the threshold.
- Dual-Axis Solar Trackers: In addition, by placing two LDRs side-by-side, your Arduino can drive a servo motor to track the sun across the sky for optimal solar harvesting.
Summary
In conclusion, this project demonstrates how simple electronic principles yield powerful automation. By pairing a photoresistor with a pull-down resistor in a voltage divider, you convert light into measurable voltage that an Arduino can interpret with ease. Explore the full project files in your repository at photoresistor.ino and README.md to start building today!