Night light with a light sensor on an Arduino Uno
A light-dependent resistor in a divider fades a lamp up when the room goes dark. Drag the slider on the sensor. The whole build, an Arduino Uno and 6 more parts, runs here in your browser on the firmware below; open it in the editor to change the wiring or the code and run it again.
Teaching? Assign it to your class in one click.
Beginner About 15 minutes to build and run. Runs in your browser. Free, and no account needed.
The parts retail for about $32. On Mokxi they're free.
Step by step, with the wiring and the common mistakes: Arduino LDR Night Light (Photoresistor)
What you'll learn
- A light sensor in a voltage divider
- Hysteresis: two thresholds with a gap
- Fading an LED with PWM
- Keeping state between loop passes
- Printing only when something changes
- Difficulty: Beginner
- Time: About 15 minutes
- Board: Arduino Uno R3
- Parts: 8
How it works
A light-dependent resistor and a 10k resistor form a voltage divider, and A0 reads its middle. Light lowers the sensor's resistance, so a bright room reads high and a covered sensor reads low.
The sketch uses two thresholds. It switches to night when the reading drops below 380, and back to day only when it rises above 580. In between, nothing changes, so the lamp does not flutter.
At night the lamp on pin 9 fades up to full in steps of 8 every 20 ms. The indicator LED on pin 8 follows the sensor right away.
Parts list
8 parts, plus the jumper wires. They retail for about $32; on Mokxi they're free.
- 1 × Arduino Uno R3In Starter Kit, Claw Machine Kit, Vending Machine Kit.
- 1 × Full-size breadboard
- 1 × Light sensor
- 1 × Resistor, 10k ΩIn Starter Kit, Claw Machine Kit, Halloween Prop Kit.
- 2 × Resistor, 220 ΩIn Starter Kit, Claw Machine Kit, Halloween Prop Kit.
- 1 × LED, yellowIn Starter Kit, Halloween Prop Kit, Logic Lab Kit.
- 1 × LED, whiteIn Starter Kit, Halloween Prop Kit, Logic Lab Kit.
Kits that can build it
These 10 starter kits have every part in the circuit. Each kit's page lists what else it can build.
- ELEGOO UNO R3 Super Starter Kit
- ELEGOO UNO R3 Most Complete Starter Kit
- Freenove Ultimate Starter Kit
- ELEGOO UNO R3 Basic Starter Kit
- SunFounder Starter Kit for Arduino Uno R3
- SunFounder Inventor Lab Kit
- REXQualis UNO R3 Super Starter Kit
- LAFVIN Super Starter Kit
- keyestudio Super Starter Kit
- Adafruit MetroX Classic Kit
Wiring table
Every connection, pin by pin, read from the circuit itself. Each row joins the pin on the left to the pin on the right, by a jumper wire or a breadboard strip.
| Part and pin | Connects to |
|---|---|
| Resistor, 220 Ω (1) pin 1 | Arduino Uno R3 pin 9 |
| Resistor, 220 Ω (2) pin 1 | Arduino Uno R3 pin 8 |
| Light sensor pin 1 | Arduino Uno R3 pin 5V |
| Resistor, 10k Ω pin 2 | Arduino Uno R3 pin GND |
| LED, yellow pin C | Arduino Uno R3 pin GND |
| LED, white pin C | Arduino Uno R3 pin GND |
| Light sensor pin 2 | Arduino Uno R3 pin A0 |
| Resistor, 10k Ω pin 1 | Arduino Uno R3 pin A0 |
| LED, yellow pin A | Resistor, 220 Ω (1) pin 2 |
| LED, white pin A | Resistor, 220 Ω (2) pin 2 |
The code
The firmware exactly as the editor opens it. Change a line there and press Run: it compiles in the browser.
// Night lamp: a real light sensor fades a lamp up when the room goes dark.
//
// A0 the middle of the divider: 5 V, the LDR, A0, 10k, GND
// pin 9 the lamp, through 220 ohm to GND
// pin 8 the indicator, through 220 ohm to GND
//
// The light-dependent resistor and the fixed 10k make a divider, and A0 reads
// the middle of it. Light on the cell drops its resistance, so the middle goes
// up: a bright room reads high and a covered cell reads low. That is the whole
// sensor, and it is why an LDR always comes with a resistor.
//
// # The threshold, and why there are two of them
//
// One threshold gives a lamp that flutters on and off while the light sits on
// it. Two (switch on below DARK, switch off above LIGHT, and do nothing in
// between) is hysteresis, and it is what every thermostat, every light
// sensor and every comparator circuit with a bit of feedback does. The gap
// here is about a fifth of the range, which is wide enough that a hand moving
// past the cell does not set it off.
//
// # The fade
//
// Pin 9 is one of the PWM outputs, so analogWrite gives any brightness from 0
// to 255. It walks there rather than jumping: a night light that snaps on is a
// torch. Eight counts every twenty milliseconds is about six tenths of a second
// end to end, and the indicator on pin 8 follows the sensor instantly, so the
// two disagree for exactly as long as the ramp takes.
const int SENSOR = A0;
const int LAMP = 9;
const int INDICATOR = 8;
// Out of 1023. Below DARK it is night; above LIGHT it is day.
const int DARK = 380;
const int LIGHT = 580;
const int STEP = 8;
const int FULL = 255;
int level = 0;
bool night = false;
int said = -1;
void setup() {
pinMode(LAMP, OUTPUT);
pinMode(INDICATOR, OUTPUT);
analogWrite(LAMP, 0);
Serial.begin(115200);
Serial.println("Mokxi Arduino Uno: night lamp");
Serial.println("drag the slider on the LDR to change the light in the room");
}
void loop() {
int light = analogRead(SENSOR);
// Two thresholds with a gap between them, so the lamp does not flutter.
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);
if (level == want && level != said) {
said = level;
Serial.print(night ? "dark (" : "light (");
Serial.print(light);
Serial.print("): lamp at ");
Serial.println(level);
}
delay(20);
}
Code walkthrough
The key functions of the sketch, and what each one does.
setup sketch.ino
Sets the lamp and indicator pins as outputs, makes sure the lamp starts off, and opens serial at 115200 with two hint lines.
void setup() {
pinMode(LAMP, OUTPUT);
pinMode(INDICATOR, OUTPUT);
analogWrite(LAMP, 0);
Serial.begin(115200);
Serial.println("Mokxi Arduino Uno: night lamp");
Serial.println("drag the slider on the LDR to change the light in the room");
}loop sketch.ino
Reads the light, then updates night using DARK and LIGHT so it changes only when crossing the far threshold. It sets the indicator, then steps level toward 255 or 0 by STEP and writes it to the lamp. When the fade finishes, it prints the reading and the lamp level once. A 20 ms wait ends each pass.
void loop() {
int light = analogRead(SENSOR);
// Two thresholds with a gap between them, so the lamp does not flutter.
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);
if (level == want && level != said) {
said = level;
Serial.print(night ? "dark (" : "light (");
// ... 7 more lines in the editorTroubleshooting
The usual mistakes with this circuit, and the fix for each.
- The lamp never turns on This project
Check the divider: 5 V, the sensor, A0, the 10k resistor, ground. The reading must drop belowDARK, 380. - The lamp turns on and off at the wrong light level This project
AdjustDARKandLIGHT. Keep a gap between them. - The reading barely changes, or sits stuck near 0 or the top of the range. Light sensor
An LDR is a resistor, so use it in a divider with a fixed resistor, about 10k, and read the middle node. Without the divider the analog pin sees nothing useful. - Readings go the wrong way: higher in the dark. Light sensor
Which side the LDR sits on decides the direction. LDR on the supply side gives a higher reading in the light. LDR on the ground side gives a lower reading in the light. Swap them if needed. - The LED is dim, burns out, or the pin reads wrong because the resistor value is off. Resistor
Read the color bands again. A 220 ohm to 330 ohm resistor suits a typical LED on 5 V. 10k is a common pull-up or pull-down value. Check with a multimeter if unsure. - A pull-up or pull-down resistor is missing, so the input floats and reads random values. Resistor
Tie the input to 5 V or ground through about 10k. Or use INPUT_PULLUP and wire the switch to ground. - The LED does not light, or it lights once and then dies. LED
LEDs have polarity. The longer leg (anode) goes toward the positive side. Always add a series resistor, about 220 ohms to 1 k ohm on a 5 V pin. - A blue or white LED stays dark on 3.3 V. LED
Blue and white LEDs drop about 3 V, so 3.3 V leaves almost nothing for the resistor. Use a 5 V supply, or a smaller resistor and a red or green LED.
Change it and keep it
Open it in the editor, change the circuit or the code, and keep your version in a free account.