Measuring Light with an LDR

Draft. This tutorial has not been checked against the physical product yet. Confirm wiring, pin assignments and voltage limits against the product documentation before building it.
DifficultyBeginner
CategorySensors
Supported boardsArduino Uno R3 and compatible ATmega328P boards
Time needed40 minutes
PrerequisitesRead a Potentiometer
Tested boardNot yet verified
Tested onNot yet verified
Arduino IDE versionNot yet verified
LibraryNot yet verified

What it does

A light-dependent resistor is a resistor whose value falls as light falls on it. In the dark it might be hundreds of kilohms; in bright light, a few hundred ohms.

That is the whole part. It has no electronics, no output pin and no polarity, and it does not produce a voltage on its own. Which raises the question this tutorial really answers: an Arduino measures voltage, so how do you read a resistance?

The technique is the same one the potentiometer used, and once you have it you can read a thermistor, a soil moisture probe, a force-sensing resistor and half a dozen other parts that work the same way.

Before you begin

Required parts and tools

  • An Arduino Uno or compatible board.
  • One LDR. The Siratek part is a bare two-legged photoresistor, not a module.
  • One 10 kilohm resistor. This is required, not optional.
  • A breadboard and three jumper wires.

Why you need the fixed resistor

An analog pin measures voltage. The LDR changes resistance. On its own, a changing resistance produces no voltage for the pin to read.

Pairing it with a fixed resistor makes a voltage divider: the two share the 5 V between them, in proportion to their resistances, and the point between them moves as the light changes. That junction is what you connect to A0.

With the LDR on the 5 V side and the fixed resistor to ground:

  • Bright light: LDR resistance is low, so it drops little, and the junction sits high. The reading rises.
  • Darkness: LDR resistance is high, so it drops most of the 5 V, and the junction falls. The reading drops.

Swap the two components and the relationship inverts. Neither is wrong; just know which you built.

Without the fixed resistor, A0 is connected to 5 V through the LDR and to nothing else. It will read near maximum whatever the light does, which looks exactly like a broken sensor.

Choosing the fixed resistor

10 kilohms is the usual choice and works for ordinary indoor light. The divider is most sensitive when the fixed resistor is near the LDR’s resistance in the conditions you care about, so for detecting darkness a larger value gives more useful spread, and for bright sunlight a smaller one does.

Start at 10 k. Change it only if your readings bunch up at one end of the range.

It is not a light meter

An LDR gives you more light and less light, not lux. Readings vary between individual parts, with temperature, and with how the component is angled. Anything you build should compare against a threshold you measured in place, never against a number copied from a tutorial, including this one.

Pin reference

Pin or label Connect to Purpose Notes
LDR, either leg Uno 5V Top of the divider An LDR has no polarity
LDR, other leg The junction, and A0 The point that moves Also goes to the fixed resistor
10 k resistor, one end The junction Bottom of the divider Same row as the LDR’s lower leg
10 k resistor, other end Uno GND Return path
An LDR and a 10 kilohm resistor in series between 5V and ground, with the junction between them wired to A0
The fixed resistor is what turns a changing resistance into a changing voltage.

Wiring steps

  1. Unplug the USB cable.
  2. Put the LDR across two breadboard rows. Either way round is fine.
  3. Run a wire from one LDR leg to 5V.
  4. Put one end of the 10 k resistor in the same row as the LDR’s other leg. This shared row is the junction.
  5. Run the resistor’s other end to GND.
  6. Run a wire from the junction row to A0.
  7. Check that the junction row really has three things in it: the LDR leg, the resistor leg and the wire to A0. If A0 is anywhere else, the reading will not move.
  8. Plug the USB cable back in.

Software and libraries

No library is required. analogRead() is part of the Arduino core.

Minimal working example

// Siratek: reading an LDR through a voltage divider.

const int ldrPin = A0;

void setup() {
  Serial.begin(9600);
  Serial.println("Siratek: cover the sensor and watch the reading.");
}

void loop() {
  int reading = analogRead(ldrPin);

  Serial.print("light = ");
  Serial.println(reading);

  delay(200);
}

Run this first and do two things: cup your hand over the LDR, and shine a phone torch on it. Write down the two numbers. Those are the real limits in your room, and every threshold you choose should sit between them.

A light that comes on in the dark

// Siratek: switching an LED on when the light falls below a threshold.

const int ldrPin = A0;
const int ledPin = 9;

// Measure your own. This is the midpoint between covered and lit, in your room.
const int darkBelow = 400;

void setup() {
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}

void loop() {
  int reading = analogRead(ldrPin);
  bool dark = reading < darkBelow;

  digitalWrite(ledPin, dark ? HIGH : LOW);

  Serial.print("light = ");
  Serial.print(reading);
  Serial.println(dark ? "  dark" : "  lit");

  delay(200);
}

Right on the threshold this will flicker, switching on and off as the reading wavers by a count or two. The fix is to use two thresholds rather than one: switch on below 380 and off above 420, so the reading has to move meaningfully before anything changes. That gap is called hysteresis, and it is worth adding to anything that drives a relay or a light.

Expected result

A reading between 0 and 1023 that rises in bright light and falls when covered, with the wiring above.

Typical indoor values might run from a few dozen covered to the high hundreds under a lamp, but do not treat those as targets. What matters is that your own numbers move a long way between covered and lit. A reading that barely shifts means the divider is wrong, not that the room is evenly lit.

The value also wavers by a count or two when nothing changes. That is genuine measurement noise, and averaging eight readings smooths it, exactly as in the potentiometer tutorial.

Troubleshooting

Symptom Likely cause Check or fix
Always near 1023 Fixed resistor missing Fit the 10 k from the junction to GND
Always near 0 5V not connected, or LDR open Check the top of the divider
Reading never moves A0 not on the junction row It must share a row with both components
Reading moves the wrong way LDR and resistor swapped Expected; swap them or invert the test
Only a small range Fixed resistor far from the LDR’s range Try 4.7 k in bright light, 47 k for darkness
Flickers at the threshold Single threshold Use two, with a gap between them
Jumps around constantly Loose leg, or mains flicker nearby Reseat, then average several readings
Different from a friend’s board Parts vary a great deal Normal; always measure your own thresholds

Next steps

  • Easier first: Read a Potentiometer, which is the same divider with a knob instead of light.
  • Related products: the DHT11 for temperature and humidity, or the flame sensor, which uses this same arrangement with an infrared-sensitive part.
  • Next project: a night light that fades up as the room darkens, using PWM rather than a simple on and off.

Sources and attribution

All text, wiring guidance and code in this tutorial are original Siratek work.

  • Arduino core documentation for analogRead().

LDR resistance ranges vary widely between parts and are given here as rough orders of magnitude. Every threshold in this tutorial is presented as something the reader must measure rather than copy. No third-party tutorial text, diagrams, photographs or code has been reproduced here.

Product used in this tutorial: Photoresistor / LDR Sensor
Shop
Sidebar
0 Wishlist
0 Cart