Smart Curtain Motor: Automate with Servo and Light Sensor
Automating your home’s curtains or blinds is one of the most satisfying smart home upgrades — your room darkens automatically at bedtime and brightens gently with sunrise, all without pressing a button. A smart curtain motor built with a servo motor, LDR or BH1750 light sensor, and ESP32 or ESP8266 costs less than Rs. 800, compared to Rs. 8,000-15,000 for branded motorised blinds from Hunter Douglas or Somfy.
This project guide covers two approaches: a servo-based mechanism for lightweight curtains and thin rod rails, and a DC gear motor approach for heavier drape curtains with track systems. Both integrate with Home Assistant, support voice control via Alexa or Google Home, and can automate based on sunlight levels, time schedules, or room occupancy.
Curtain Mechanism Types
Choose your mechanism based on the type of window covering:
- Servo motor (MG996R): Best for thin rod curtains, lightweight fabrics. The servo rotates the rod which moves the curtains via rings. Suitable for curtains up to 2 kg total weight.
- DC gear motor (12V, 60 RPM): Best for heavy drape curtains on track systems. A spool and fishing line pull the curtain hooks along the track. Handles curtains up to 5 kg.
- Stepper motor (NEMA 17): Precision position control for Roman blinds or venetian slat angle adjustment. More complex but very accurate.
- Roller blind actuator: For existing roller blinds, a stepper or DC motor attaches to the roller tube and winds/unwinds the blind.
For typical Indian homes with standard cotton or polyester curtains on steel/wooden rods, the MG996R servo approach is the simplest and most reliable first project.
Components and Tools
For the servo-based version:
- ESP8266 NodeMCU or ESP32 development board
- MG996R servo motor (180-degree rotation, metal gears, 9-12 kg-cm torque)
- LDR (light dependent resistor) with 10k pull-down resistor, or BH1750 digital light sensor
- 5V 2A power supply (servo draws up to 1.5A under load)
- Curtain rod coupling or 3D-printed adapter to mount servo on rod end
- Optional: HC-SR501 PIR motion sensor for occupancy-based automation
Recommended Product
ESP32 with OLED Display
The ESP32 LoRa board with built-in OLED shows the curtain position percentage and current light level right on the display — no phone needed to check status. Its dual-core processor handles smooth servo PWM without jitter.
Servo-Based Curtain Controller
The servo rotates the curtain rod, which moves curtains via the curtain rings. Here is the basic wiring and Arduino code:
Wiring:
- Servo Signal (orange/yellow wire) → GPIO 14 (D5 on NodeMCU)
- Servo VCC (red) → 5V from external power supply
- Servo GND (black/brown) → GND (common with ESP)
- LDR one end → 3.3V; other end → A0 and 10k resistor to GND
#include <Servo.h>
Servo curtainServo;
const int SERVO_PIN = 14; // D5
const int LDR_PIN = A0;
const int OPEN_ANGLE = 180; // Fully open position
const int CLOSE_ANGLE = 0; // Fully closed position
// Light threshold: open if LDR reading > 600 (bright day)
const int LIGHT_THRESHOLD = 600;
bool curtainIsOpen = false;
void openCurtain() {
for (int pos = curtainServo.read(); pos <= OPEN_ANGLE; pos++) {
curtainServo.write(pos);
delay(15);
}
curtainIsOpen = true;
}
void closeCurtain() {
for (int pos = curtainServo.read(); pos >= CLOSE_ANGLE; pos--) {
curtainServo.write(pos);
delay(15);
}
curtainIsOpen = false;
}
void setup() {
curtainServo.attach(SERVO_PIN);
Serial.begin(115200);
}
void loop() {
int lightLevel = analogRead(LDR_PIN);
if (lightLevel > LIGHT_THRESHOLD && !curtainIsOpen) {
openCurtain();
} else if (lightLevel < LIGHT_THRESHOLD - 100 && curtainIsOpen) {
closeCurtain();
}
delay(5000); // Check every 5 seconds
}
The 100-point hysteresis prevents rapid open/close toggling around the threshold value — a common issue in automations without hysteresis.
Light Sensor Automation
The LDR is a simple analog sensor, but the BH1750 digital sensor gives lux readings that are far more consistent and do not vary with supply voltage changes:
#include <Wire.h>
#include <BH1750.h>
BH1750 lightMeter;
void setup() {
Wire.begin(4, 5); // SDA = GPIO4, SCL = GPIO5 for ESP8266
lightMeter.begin();
}
void loop() {
float lux = lightMeter.readLightLevel();
// Open at sunrise (above 500 lux), close at dusk (below 50 lux)
if (lux > 500 && !curtainIsOpen) openCurtain();
if (lux < 50 && curtainIsOpen) closeCurtain();
delay(10000);
}
Calibrate your thresholds to local conditions. In Indian summer, direct sunlight through a window can exceed 50,000 lux. For east-facing windows in Mumbai or Pune, 500 lux corresponds roughly to 30-40 minutes after sunrise — a comfortable opening time.
ESPHome Cover Entity
ESPHome has a cover component with open/close/stop/set_position support that maps perfectly to Home Assistant’s curtain UI:
esphome:
name: smart-curtain
platform: ESP8266
board: nodemcuv2
servo:
- id: curtain_servo
output: curtain_pwm
restore: true
min_level: 2.5%
max_level: 12.5%
output:
- platform: esp8266_pwm
id: curtain_pwm
pin: D5
frequency: 50 Hz
cover:
- platform: template
name: "Living Room Curtain"
lambda: |-
if (id(curtain_servo).position >= 0.95) return COVER_OPEN;
if (id(curtain_servo).position <= 0.05) return COVER_CLOSED;
return COVER_OPEN;
open_action:
- servo.write:
id: curtain_servo
level: 100%
close_action:
- servo.write:
id: curtain_servo
level: 0%
stop_action:
- servo.detach: curtain_servo
sensor:
- platform: adc
pin: A0
name: "Window Light Level"
update_interval: 10s
Recommended Product
ESP8266 WiFi Relay Module 2-Channel
For a DC motor curtain drive system, a 2-channel relay module provides forward/reverse motor control — one relay connects motor+ to 12V for opening, the other relay reverses polarity for closing. Works with any 12V DC gear motor.
DC Gear Motor for Heavy Curtains
For curtains heavier than 2 kg, a 12V DC gear motor with H-bridge control provides more torque. An L298N module drives the motor in both directions and includes current protection:
const int MOTOR_IN1 = 5; // D1
const int MOTOR_IN2 = 4; // D2
const int MOTOR_EN = 0; // D3 - PWM speed control
void openCurtain(int seconds) {
digitalWrite(MOTOR_IN1, HIGH);
digitalWrite(MOTOR_IN2, LOW);
analogWrite(MOTOR_EN, 180); // 70% speed
delay(seconds * 1000);
stopMotor();
}
void closeCurtain(int seconds) {
digitalWrite(MOTOR_IN1, LOW);
digitalWrite(MOTOR_IN2, HIGH);
analogWrite(MOTOR_EN, 180);
delay(seconds * 1000);
stopMotor();
}
void stopMotor() {
digitalWrite(MOTOR_IN1, LOW);
digitalWrite(MOTOR_IN2, LOW);
analogWrite(MOTOR_EN, 0);
}
Calibrate seconds for your specific curtain track length. For a 2-metre track, typically 3-5 seconds at 70% motor speed. Add limit switches (microswitches) at the fully open and fully closed positions to prevent the motor from running against the end stop — this extends motor life significantly.
Home Assistant Integration
With ESPHome, your smart curtain appears as a cover entity with a visual slider in the Home Assistant dashboard. Build useful automations:
Sunrise open automation:
automation:
- alias: "Open Bedroom Curtain at Sunrise"
trigger:
- platform: sun
event: sunrise
offset: "+00:30:00" # 30 mins after sunrise
action:
- service: cover.open_cover
target:
entity_id: cover.bedroom_curtain
Night privacy close:
automation:
- alias: "Close All Curtains at Sunset"
trigger:
- platform: sun
event: sunset
offset: "-00:15:00" # 15 mins before sunset
action:
- service: cover.close_cover
target:
entity_id:
- cover.bedroom_curtain
- cover.living_room_curtain
Recommended Product
Raspberry Pi Zero W
Host Home Assistant on a Raspberry Pi Zero W for full local smart curtain control. Sunrise/sunset automations use your GPS coordinates — no internet lookup required. Complete local smart home hub for under Rs. 2,500.
Frequently Asked Questions
Which servo motor is best for Indian cotton curtains?
The MG996R (metal gear, 9-12 kg-cm torque, Rs. 180-250) is recommended for cotton or polyester curtains up to 150 cm width. For wider curtains or heavier fabrics like blackout lining, use two MG996R servos — one at each end of the rod — controlled simultaneously via the same signal wire.
How do I mount the servo to an existing curtain rod?
The easiest method is a 3D-printed coupler that fits your rod diameter (typically 19 mm or 25 mm). Alternatively, use a PVC pipe coupler with the servo horn glued inside. The coupler goes between the wall bracket and the first curtain ring — rod rotation moves all rings together.
Can I use voice commands to control the curtain?
Yes. With ESPHome + Home Assistant, use the Emulated Hue integration or the official Home Assistant skill for Alexa/Google Home. Say “Alexa, open the bedroom curtain” or “Hey Google, close the living room blinds” for natural voice control.
Will the servo position be retained after a power cut?
ESPHome’s restore: true option saves the last servo position to flash memory and restores it after power restoration. This prevents the curtain from snapping to an unknown position when power returns after Indian load shedding.
The servo makes a buzzing noise even when not moving. How to fix?
Servo buzz (jitter) when stationary is caused by PWM signal noise. Use the servo.detach action after reaching the target position — this removes the PWM signal and stops the buzzing. The curtain stays in position due to the mechanical gears.
Can I control the curtain partially — open 50%?
Yes. The ESPHome cover entity supports set_position (0-100%). In Home Assistant, the cover slider lets you set any percentage. Automate it: “Open to 30% during afternoon nap to block direct sun but allow ventilation.”
Automate Your Curtains Today
Build a smart curtain system for under Rs. 800 — sunrise opens and sunset closes, all automatic. Browse ESP modules, servo motors, and sensors at Zbotic.
Add comment