Light Sensor Circuit: Build an Automatic LED with a Photoresistor
Build a light sensor circuit using a photoresistor (LDR) that automatically turns on an LED when it gets dark. Includes schematic, component list, and Arduino version.
A light sensor circuit uses a photoresistor (LDR) to detect ambient light and automatically turn on an LED when it gets dark. This is the same principle behind automatic night lights, street lights, and garden solar lamps. You can build the basic version with just a few components and no programming, or add an Arduino for precise control and adjustable thresholds.
What you need
Basic version (no Arduino)
| Component | Value | Purpose |
|---|---|---|
| Photoresistor (LDR) | Standard (GL5528 or similar) | Light sensing |
| Fixed resistor | 10 kΩ | Voltage divider partner |
| NPN transistor | 2N2222 or BC547 | Switches the LED |
| LED (5mm) | Any color | Output indicator |
| LED resistor | 220Ω–330Ω | Current limiting for LED |
| Power supply | 5V–9V battery or adapter | Power source |
| Breadboard + wires | Standard | Prototyping |
Arduino version (adds precision)
Same components as above, but the transistor is optional — the Arduino can drive the LED directly from a digital pin and read the LDR on an analog pin.
How the photoresistor works
A photoresistor (light-dependent resistor, LDR) is made of a semiconductor material whose resistance changes with light exposure:
| Condition | LDR resistance | Behavior |
|---|---|---|
| Bright sunlight | ~1 kΩ or less | Very low resistance |
| Indoor lighting | ~5–20 kΩ | Medium resistance |
| Dim light / dusk | ~50–200 kΩ | High resistance |
| Darkness | ~1 MΩ+ | Very high resistance |
The LDR is not polarized — it works in either direction, just like a regular resistor.
The voltage divider principle
The LDR and a fixed resistor form a voltage divider. The midpoint voltage changes with light level:
V_mid = V_supply × R_fixed / (R_LDR + R_fixed)- Bright light: R_LDR is low (~1 kΩ). V_mid ≈ 5V × 10k / (1k + 10k) ≈ 4.5V (high).
- Darkness: R_LDR is high (~1 MΩ). V_mid ≈ 5V × 10k / (1M + 10k) ≈ 0.05V (low).
To make the LED turn on in the dark, we swap the positions — put the LDR on top (connected to positive) and the fixed resistor on the bottom (connected to ground). Now V_mid is high when it's dark and low when it's bright:
V_mid = V_supply × R_LDR / (R_LDR + R_fixed)- Darkness: R_LDR is high → V_mid is high → transistor turns on → LED lights.
- Bright: R_LDR is low → V_mid is low → transistor off → LED off.
Building the basic circuit (no Arduino)
- Set up power: connect your 5V supply to the breadboard power rails (positive and ground).
- Voltage divider: Connect the LDR between the positive rail and a row (call it row A). Connect the 10 kΩ resistor between row A and the ground rail. Row A is now the midpoint — its voltage varies with light.
- Transistor: Place the 2N2222 on the breadboard. Connect the base to row A through a 10 kΩ resistor (to limit base current). Connect the emitter to ground.
- LED: Connect the 220Ω resistor from the positive rail to the LED's anode (long leg). Connect the LED's cathode to the transistor's collector.
- Cover the LDR with your hand — the LED should light up. Uncover it — the LED should turn off.
Adjusting sensitivity
If the LED turns on/off at the wrong light level, change the 10 kΩ fixed resistor:
- Higher value (47 kΩ): LED turns on in dimmer conditions (less sensitive).
- Lower value (4.7 kΩ): LED turns on earlier, in brighter conditions (more sensitive).
For fine-tuning, replace the fixed resistor with a 100 kΩ potentiometer. Turn the pot to set the exact light level where the LED triggers.
Arduino version
Using an Arduino adds precision — you can read exact light levels, set thresholds in code, and add features like hysteresis (to prevent flickering at the threshold).
Wiring
- Connect the LDR between 5V and analog pin A0.
- Connect a 10 kΩ resistor between A0 and GND (completing the voltage divider).
- Connect an LED with a 220Ω resistor from digital pin 8 to GND.
Code
const int LDR_PIN = A0;
const int LED_PIN = 8;
const int DARK_THRESHOLD = 700; // Adjust this value (0-1023)
void setup() {
pinMode(LED_PIN, OUTPUT);
Serial.begin(9600);
}
void loop() {
int lightLevel = analogRead(LDR_PIN);
Serial.print("Light level: ");
Serial.println(lightLevel);
if (lightLevel > DARK_THRESHOLD) {
digitalWrite(LED_PIN, HIGH); // Dark - turn LED on
} else {
digitalWrite(LED_PIN, LOW); // Bright - turn LED off
}
delay(200);
}How to calibrate
- Upload the code and open the Serial Monitor (Tools → Serial Monitor).
- Observe the light level value in bright conditions (might be ~200–400).
- Cover the LDR and note the dark value (might be ~800–950).
- Set
DARK_THRESHOLDto a value between the two (e.g., 700). - Re-upload and test — the LED should turn on when you cover the LDR.
Adding hysteresis (preventing flicker)
Without hysteresis, the LED flickers when the light level is right at the threshold. Fix this by using two thresholds — one to turn on and a lower one to turn off:
const int THRESHOLD_ON = 700; // Turn on when above this
const int THRESHOLD_OFF = 500; // Turn off when below this
bool ledState = false;
void loop() {
int lightLevel = analogRead(LDR_PIN);
if (lightLevel > THRESHOLD_ON) {
ledState = true;
} else if (lightLevel < THRESHOLD_OFF) {
ledState = false;
}
// Between thresholds: keep current state (hysteresis)
digitalWrite(LED_PIN, ledState ? HIGH : LOW);
delay(100);
}Real-world applications
| Application | How it uses light sensing |
|---|---|
| Automatic night lights | LED or lamp turns on when room gets dark |
| Street lights | Turn on at dusk, off at dawn |
| Solar garden lights | Charge during day, light up at night |
| Screen brightness | Phones adjust display brightness to ambient light |
| Security systems | Detect when a beam of light is broken |
| Light meters | Measure light intensity for photography |
Troubleshooting
| Problem | Cause | Fix |
|---|---|---|
| LED is always on | Fixed resistor too low, or LDR getting no light | Increase fixed resistor or check LDR placement |
| LED is always off | Fixed resistor too high, or LDR saturated | Decrease fixed resistor value |
| LED flickers at threshold | No hysteresis | Add dual thresholds (Arduino) or RC filter |
| Very slow response | Normal — LDRs take 10-100ms to change | Use a phototransistor for faster response |
| Arduino reads 0 or 1023 always | Wiring error — divider not connected | Verify LDR and resistor form a divider between 5V and GND |
Summary
A light sensor circuit uses an LDR (photoresistor) whose resistance changes with light level. Paired with a fixed resistor in a voltage divider, it produces a variable voltage that can drive a transistor switch (basic version) or be read by an Arduino analog input (programmable version). The circuit turns an LED on in darkness and off in light. Adjust sensitivity by changing the fixed resistor value; add hysteresis to prevent flickering at the switching threshold.