Embedded project 01 · Intermediate · about 45 minutes
Automatic night light
An LED that fades up as the room gets dark. It is a small build, but it uses almost everything in the course: a voltage divider, a sensor, the ADC, a little code, PWM and an LED with its resistor. Simulate it here first, then build it for real.
Builds on: Embedded systems, Circuit lab 02, PWM, Circuit lab 01
What you need
| Part | Value used here | Why |
|---|---|---|
| Arduino Uno or a compatible 5 V board | 5 V logic, 10-bit ADC | Reads the sensor and runs the program. Other boards work with small changes. |
| Light-dependent resistor (LDR) | — | The light sensor. Values vary a lot between parts, which is why you calibrate. |
| Resistor (R1) | 10 kΩ | Top of the divider. |
| LED | red, about 2 V | The light. |
| Resistor for the LED | 220 Ω | Limits LED current to about 14 mA at full brightness. |
| Breadboard, jumper wires, USB cable | — | Power comes from the USB port. |
The circuit
| From | To |
|---|---|
| 5V pin | one end of the 10 kΩ resistor |
| other end of 10 kΩ | pin A0 and one leg of the LDR |
| other leg of LDR | GND |
| pin 9 | 220 Ω resistor, then LED long leg (anode) |
| LED short leg | GND |
The LDR sits at the bottom of the divider, so a darker room gives a higher reading. Pin 9 is one of the Uno’s PWM pins (marked ~).
Simulate it
Move the light level and follow the signal through every stage. The numbers use exactly the same arithmetic as the sketch below, including Arduino’s whole-number map().
- Light—you set this
- LDR—illustrative model
- Pin A0—divider output
- analogRead—0–1023
- Duty—analogWrite value
- LED current—average
The sketch
This updates as you change the program and its levels. Copy it into the Arduino IDE once you have calibrated the levels for your room.
Build and calibrate it
- Build the divider only. Wire 5V → 10 kΩ → A0, and A0 → LDR → GND. Leave the LED out for now.
- Check it with a multimeter. Measure between A0 and GND. Cover the LDR with your hand: the voltage should rise. Shine a light on it: the voltage should fall.
- Read real values. Upload the calibration sketch below, open the Serial Monitor at 9600 baud (the Arduino IDE’s, or this site’s browser serial monitor), and note the reading in normal room light and with the LDR covered.
void setup() { Serial.begin(9600); } void loop() { Serial.println(analogRead(A0)); delay(250); } - Set your levels. Put BRIGHT_LEVEL a little above your room-light reading and DARK_LEVEL a little below your covered reading. Try them in the simulator above.
- Add the LED. Wire pin 9 → 220 Ω → LED anode (long leg), and the LED cathode (short leg) → GND.
- Upload the night-light sketch and test it by slowly covering the LDR. Point the LED away from the LDR so it does not light its own sensor.
If it does not work
| What you see | Likely cause |
|---|---|
| Reading stuck near 1023 | The LDR is not connected to GND, or R1 and the LDR are swapped and the room is very bright. |
| Reading stuck near 0 | A0 is shorted to GND, or the 5V wire to R1 is missing. |
| Readings jump around wildly | A0 is not connected to the divider at all, so the input is floating. |
| LED never lights | LED fitted backwards, wrong pin in the code, or the levels are set so the reading never passes BRIGHT_LEVEL. |
| LED switches on and off repeatedly at dusk | Its light is reaching the LDR, or (in on/off mode) the ON and OFF levels are too close together. |
Power this project from USB only. Do not connect it to mains lighting. If you later want to drive an LED strip, use a separate low-voltage supply, a logic-level MOSFET and a shared ground; see driving bigger loads.
The LDR model is illustrative (1 MΩ dark to 1 kΩ bright on a logarithmic scale), and the ADC is ideal. Real readings depend on your LDR, so always calibrate with the Serial Monitor. The LED current uses the Circuit lab 01 model: (5 V − 2 V) ÷ 220 Ω while the PWM output is high, averaged over the duty cycle. On an Uno, pin 9’s PWM runs at about 490 Hz, far too fast to see.
Take it further
- Swap the LDR for a 10 kΩ NTC thermistor and make a “too warm” indicator. Explore the curve first in Circuit lab 02.
- Add a pushbutton with
INPUT_PULLUPto force the light on. See reading a button. - Smooth the reading by averaging several
analogReadcalls before using it.