Learn

An LDR night light on an Arduino Uno

  • 192parts on the bench
  • 25boards running now
  • 1.00xreal time, on every board
Arduino Uno: night lightlive0.000 s 0.00x
Click to open it in the editor
The nightlamp example: an LDR divider on A0, a lamp on pin 9 and an indicator on pin 8. Open it in the editor and drag the light slider.

A light-dependent resistor, also called a photoresistor or LDR, changes its resistance with the light that falls on it: low in bright light, high in the dark. On its own that is useless to a microcontroller, which can only read voltages, so it always comes with a second, fixed resistor. The circuit above is a night light on an Arduino Uno: the lamp on pin 9 fades up when the room goes dark and back down when the light returns, and an indicator on pin 8 shows what the sensor thinks right now.

Open it in the editor and drag the slider under the sensor to change the light in the room.

What you need

  • An Arduino Uno
  • A light-dependent resistor
  • A 10 k resistor for the divider
  • Two LEDs and two 220 ohm resistors
  • A breadboard and jumper wires

Wiring

Part and pin
Goes to
Note
LDR
5 V to A0
One leg on 5 V, the other on A0
10 k resistor
A0 to GND
The bottom half of the divider
Lamp LED, through 220 ohm
Pin 9
A PWM pin, so it can fade
Indicator LED, through 220 ohm
Pin 8
Follows the sensor instantly

Why an LDR needs a resistor

The LDR and the 10 k resistor make a voltage divider between 5 volts and ground, and A0 reads the middle. With light on the cell, its resistance drops, so more of the 5 volts appears across the fixed resistor and the reading goes up. Cover it and its resistance climbs, the middle falls, and the reading drops. A bright room reads high; a dark one reads low.

The fixed resistor sets where the circuit is most sensitive. A value close to the LDR’s resistance at the light level you care about gives the biggest change in reading for a change in light. 10 k is a sensible middle for indoor light.

Two thresholds, not one

The obvious sketch switches the lamp on when the reading is below some value and off when it is above. Try it and the lamp flutters whenever the light sits near that value, or a hand passes over the sensor. The fix is hysteresis: two thresholds with a gap between them. The example switches to night below 380 and back to day only above 580, and in between it does nothing at all. Every thermostat works this way.

The fade is the second touch. The lamp does not jump to full brightness; it walks there eight steps every twenty milliseconds, about six tenths of a second end to end, while the indicator on pin 8 follows the sensor instantly. For that short time the two disagree, which is a nice way to see the fade happen.

Hysteresis and the fade, from the nightlamp example (trimmed)
const int DARK = 380;
const int LIGHT = 580;

void loop() {
  int light = analogRead(SENSOR);

  if (!night && light < DARK) {
    night = true;
  } else if (night && light > LIGHT) {
    night = false;
  }
  digitalWrite(INDICATOR, night ? HIGH : LOW);

  int want = night ? FULL : 0;
  if (level < want) {
    level += STEP;
    if (level > want) {
      level = want;
    }
  } else if (level > want) {
    level -= STEP;
    if (level < want) {
      level = want;
    }
  }
  analogWrite(LAMP, level);

  delay(20);
}

Try it in the editor

Open the circuit in the editor and change LIGHT to 400, only just above DARK. Slide the light level slowly across the threshold and the lamp starts to hesitate on and off around it, which is the fluttering hysteresis prevents. Put it back to 580 and the gap stops it.

Then select the 10 k resistor under the sensor and change it to 1 k. The readings shift down, and the point at which the room counts as dark moves with them. Choosing that resistor is choosing the light level the circuit is most sensitive to.

For a smoother fade, change STEP from 8 to 2. The lamp now takes over two seconds to come up, more like a real night light.

Common mistakes

Wiring the LDR alone to the pin. Without the fixed resistor there is no divider, the pin floats or sits at 5 volts, and the reading barely changes with the light.

Getting the direction backwards. If the resistor is on top and the LDR on the bottom, bright reads low and dark reads high. Either way works as long as the code agrees with the wiring.

One threshold, and a lamp that flickers at dusk.

Fading on a pin without PWM. Pin 9 can fade; pin 8 can only be on or off, which is why the indicator is there and the lamp is not.

Letting the lamp shine on the sensor. On a real desk, a night light that lights its own LDR switches itself off. Point the lamp away or shade the cell.

Questions

What resistor should I use with an LDR?

Something near the LDR’s resistance at the light level where you want to switch. 10 k suits most indoor projects with the common GL55 series cells.

Is an LDR the same as a photodiode?

No. An LDR is a slow resistor made of a light-sensitive material; a photodiode is a fast semiconductor junction that produces a current. For a night light, the LDR is simpler and plenty fast enough.

Can I read an LDR with an ESP32?

Yes, with the divider between 3.3 V and GND and the middle on an ADC pin. The readings run from 0 to 4095 rather than 1023, so scale the thresholds to match.

Build this for real

Open the editor, change a value and watch the number move with it. Nothing to install, and no account needed.