Light sensors (LDR)
What you’ll learn
- How an LDR (light-dependent resistor) works
- Why it needs a voltage divider
- How to calibrate a light sensor and use a threshold
The LDR
An LDR’s resistance changes with light: high in the dark (hundreds of kΩ or more) and low in bright light (around 1 kΩ or less). The Arduino can’t read resistance directly, only voltage.
The voltage divider
Put the LDR in series with a fixed resistor (often 10 kΩ) and read the voltage in the middle:
5V ── LDR ──┬── 10 kΩ ── GND │ A0With the LDR on top, more light → lower LDR resistance → higher voltage on A0 → bigger number. Swap the two parts and it works the other way round. Many LDR modules contain this divider already and give an analog output (AO), sometimes plus a digital output (DO) with a threshold you set with a small screw.
Calibrate, then threshold
Light levels differ in every room, so don’t guess numbers:
- Print the reading in the dark (cover the sensor) and in normal light.
- Pick a threshold halfway between them.
- Use it:
if (light < threshold) { ... }.
Example: an automatic night light
const int THRESHOLD = 400; // set from your own readings
void setup() { pinMode(LED_BUILTIN, OUTPUT); }
void loop() { int light = analogRead(A0); digitalWrite(LED_BUILTIN, light < THRESHOLD ? HIGH : LOW); delay(50);}(If your wiring gives bigger numbers in the dark, flip the < to >.)
Example: a light-seeking robot
Two LDRs, one on each front corner. Steer towards the brighter side:
int left = analogRead(A0), right = analogRead(A1);if (left > right + 30) { // turn left} else if (right > left + 30) { // turn right} else { // go straight}The + 30 is a dead band: it stops the robot twitching when both sides are nearly equal.
Try it in the virtual Arduino
Press Start simulator, replace diagram.json with the wiring below, paste the sketch, press ▶. Click the light sensor and drag its lux slider while watching the numbers.
{ "version": 1, "author": "RoboLearn", "editor": "wokwi", "parts": [ { "type": "wokwi-arduino-uno", "id": "uno", "top": 0, "left": 0, "attrs": {} }, { "type": "wokwi-photoresistor-sensor", "id": "ldr1", "top": -80, "left": 100, "attrs": {} } ], "connections": [ [ "ldr1:VCC", "uno:5V", "red", [] ], [ "ldr1:GND", "uno:GND.1", "black", [] ], [ "ldr1:AO", "uno:A0", "green", [] ] ], "dependencies": {}}void setup() { Serial.begin(9600);}
void loop() { int light = analogRead(A0); Serial.println(light); delay(200);}Runs on Wokwi, free, no account needed.
Dark or light?Easy
Find the reading at 10 lux and at 1000 lux. Pick a threshold between them.
Night lightMedium
Turn the built-in LED on when it’s dark, using your threshold.
Use the night-light example from the Examples tab with your threshold, and flip < to > if your readings go up as it gets darker.
HysteresisHard
Near the threshold the LED flickers on and off. Fix it with two thresholds: turn on below one value and off only above a higher one.
Show an answer
bool on = false;void loop() { int light = analogRead(A0); if (light < 350) on = true; if (light > 450) on = false; // between 350 and 450: keep the last state digitalWrite(LED_BUILTIN, on ? HIGH : LOW);}Quick check
Finished this lesson?