Project Overview
This project creates a smart night light that turns on when motion is detected and gradually dims over time. The light uses an RGB LED or LED strip and features smooth fade-out effects, making it perfect for bedrooms, hallways, and children’s rooms.
Difficulty: Beginner
Estimated time: 1-2 hours
Estimated cost: $15-25
How It Works
A PIR sensor detects motion. When motion is detected, the LED turns on at full brightness. After a set period without motion, the light gradually dims over several seconds rather than turning off abruptly. An optional ambient light sensor (LDR) can be added so the light only activates when it’s dark enough.
Materials Needed
- Arduino Nano or Arduino Uno (1)
- HC-SR501 PIR sensor (1)
- RGB LED (common cathode) or WS2812B LED strip (3-5 LEDs)
- LDR (photoresistor) (optional, for daylight detection)
- 10kΩ resistor (for LDR voltage divider)
- 220Ω resistors (3 for RGB LED)
- Project enclosure (small box or 3D-printed housing)
- Jumper wires
- USB power supply (5V 1A)
Circuit Diagram
Option 1: RGB LED (Common Cathode)
| Component | Pin | Arduino Pin | PIR Sensor | VCC | 5V | PIR Sensor | GND | GND | PIR Sensor | OUT | Digital Pin 2 | RGB LED (Red) | Anode | Digital Pin 9 (through 220Ω) | RGB LED (Green) | Anode | Digital Pin 10 (through 220Ω) | RGB LED (Blue) | Anode | Digital Pin 11 (through 220Ω) | RGB LED | Cathode | GND | LDR | One leg | 5V | LDR | Other leg | Analog Pin A0 and 10kΩ resistor to GND |
|---|
Arduino Code
// PIR Night Light with Auto Dimming
// Uses RGB LED with smooth fade-out effect
const int pirPin = 2;
const int redPin = 9;
const int greenPin = 10;
const int bluePin = 11;
const int ldrPin = A0; // Optional
// Color settings (warm white)
int redValue = 255;
int greenValue = 180;
int blueValue = 100;
// Timing
unsigned long lastMotionTime = 0;
const unsigned long holdTime = 30000; // 30 seconds before dimming
const unsigned long fadeDuration = 5000; // 5 second fade-out
bool lightsOn = false;
int currentBrightness = 0;
unsigned long fadeStartTime = 0;
void setup() {
Serial.begin(9600);
pinMode(pirPin, INPUT);
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
// Turn off lights initially
setBrightness(0);
Serial.println("Night Light Ready");
Serial.println("Waiting 60 seconds for PIR warm-up...");
delay(60000);
}
void setColor(int r, int g, int b) {
analogWrite(redPin, r);
analogWrite(greenPin, g);
analogWrite(bluePin, b);
}
void setBrightness(int percent) {
// percent: 0-100
int r = map(percent, 0, 100, 0, redValue);
int g = map(percent, 0, 100, 0, greenValue);
int b = map(percent, 0, 100, 0, blueValue);
setColor(r, g, b);
currentBrightness = percent;
}
bool isDark() {
int ldrValue = analogRead(ldrPin);
// Adjust threshold based on your environment
return ldrValue < 500; // Dark when reading < 500
}
void fadeOut() {
unsigned long elapsed = millis() - fadeStartTime;
if (elapsed >= fadeDuration) {
setBrightness(0);
lightsOn = false;
} else {
int brightness = 100 - (elapsed * 100 / fadeDuration);
setBrightness(brightness);
}
}
void loop() {
// Check if it's dark enough (optional)
if (!isDark() && lightsOn) {
// It's daytime, turn off lights immediately
setBrightness(0);
lightsOn = false;
}
bool motionDetected = digitalRead(pirPin) == HIGH;
if (motionDetected && isDark()) {
lastMotionTime = millis();
if (!lightsOn) {
// Turn on lights immediately
setBrightness(100);
lightsOn = true;
Serial.println("Motion detected - Lights ON");
} else if (currentBrightness < 100) {
// Fade back up if dimming was in progress
setBrightness(100);
Serial.println("Motion detected - Fade cancelled");
}
}
if (lightsOn) {
// Check if it's time to dim
if (millis() - lastMotionTime > holdTime) {
if (fadeStartTime == 0) {
fadeStartTime = millis();
Serial.println("No motion - Starting fade-out");
}
fadeOut();
} else {
// Reset fade timer if motion occurs during fade
fadeStartTime = 0;
}
}
delay(50);
}
Code for WS2812B LED Strip
#include <FastLED.h>
#define LED_PIN 6
#define NUM_LEDS 5
#define BRIGHTNESS 128
CRGB leds[NUM_LEDS];
const int pirPin = 2;
const int ldrPin = A0;
unsigned long lastMotionTime = 0;
const unsigned long holdTime = 30000;
const unsigned long fadeDuration = 5000;
bool lightsOn = false;
int currentBrightness = 0;
unsigned long fadeStartTime = 0;
void setup() {
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(0);
pinMode(pirPin, INPUT);
Serial.begin(9600);
delay(60000);
}
void setBrightness(int percent) {
int brightness = map(percent, 0, 100, 0, BRIGHTNESS);
FastLED.setBrightness(brightness);
FastLED.show();
currentBrightness = percent;
}
void setColor(CRGB color) {
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = color;
}
FastLED.show();
}
void loop() {
int ldrValue = analogRead(ldrPin);
bool isDark = ldrValue < 500;
bool motionDetected = digitalRead(pirPin) == HIGH;
if (motionDetected && isDark) {
lastMotionTime = millis();
if (!lightsOn) {
setColor(CRGB::White);
setBrightness(100);
lightsOn = true;
} else if (currentBrightness < 100) {
setBrightness(100);
}
fadeStartTime = 0;
}
if (lightsOn) {
if (millis() - lastMotionTime > holdTime) {
if (fadeStartTime == 0) {
fadeStartTime = millis();
}
unsigned long elapsed = millis() - fadeStartTime;
if (elapsed >= fadeDuration) {
setBrightness(0);
lightsOn = false;
} else {
int brightness = 100 - (elapsed * 100 / fadeDuration);
setBrightness(brightness);
}
}
}
delay(50);
}
Installation Steps
- Assemble circuit: Build on breadboard and test with USB power.
- Upload code: Load code to Arduino and adjust color values as desired.
- Calibrate LDR: Read ambient light values in dark and bright conditions, adjust threshold accordingly.
- Test motion detection: Walk past sensor and verify light turns on.
- Enclose components: Place Arduino and wiring in a small enclosure. Drill holes for PIR sensor lens and LED.
- Position sensor: Place unit at 0.5-1m height (night lights are typically placed low) facing the area to monitor.
- Final test: Verify fade-out effect and daylight detection.
Customizing Colors
Adjust the RGB values for different color temperatures:
- Warm white (2700K): R=255, G=180, B=100
- Cool white (4000K): R=255, G=235, B=205
- Soft amber: R=255, G=140, B=50
- Night vision safe (red): R=255, G=0, B=0
- RGB cycle mode: Add code to cycle through colors
Project Extensions
- Multiple LEDs: Use addressable LED strip for longer runs.
- Color temperature sensing: Add a color sensor to match room lighting.
- Bluetooth control: Add HC-05 module to control color and brightness from phone.
- Sleep mode: Use deep sleep to reduce power consumption during the day.
- Music sync: Add microphone module for sound-reactive lighting.
Conclusion
This smart night light provides gentle illumination when you need it and automatically fades out, making it perfect for bedrooms and hallways. The gradual dimming effect is much more pleasant than abrupt switching off.
