Building a Servo-Controlled Automated Curtain System with Arduino

How to Connect a Micro Servo Motor to Arduino / Visits:4

Why a Micro Servo Motor Changes Everything

There is something deeply satisfying about watching a tiny plastic-and-metal device rotate exactly 90 degrees and stop on command. The micro servo motor—that ubiquitous little workhorse found in everything from RC planes to robotic arms—has become the go-to actuator for makers who want precise angular control without the bulk of stepper motors or the complexity of closed-loop DC systems. When you pair it with an Arduino, you suddenly have the ability to move physical objects with a few lines of code.

An automated curtain system is the perfect weekend project to showcase what a micro servo can do. It is practical, visible, and genuinely useful. Unlike a blinking LED or a spinning fan, a curtain that opens and closes on schedule feels like you have built something that belongs in a smart home. And the best part? The entire mechanism can be driven by a servo that costs less than a cup of coffee.

This article walks through the full build: the hardware you need, how the micro servo actually works under the hood, the wiring, the code, the mechanical linkage, and the little pitfalls that will save you an afternoon of frustration. By the end, you will have a working prototype and a clear understanding of why the micro servo is the star of this show.

Understanding the Micro Servo Motor

What Makes It "Micro"?

A standard hobby servo like the SG5010 weighs around 40 grams and can pull several kilogram-centimeters of torque. A micro servo—think SG90, MG90S, or TS90—weighs between 9 and 15 grams and delivers roughly 1.5 to 2.5 kg·cm at 4.8V. The footprint is typically 23mm x 12.2mm x 29mm. That tiny size is exactly why it is perfect for a curtain system: you can hide it inside a curtain rod bracket, a 3D-printed housing, or even behind the fabric itself.

How It Actually Works

Inside a micro servo you will find four key components:

  1. A small DC motor – spins fast but with low torque.
  2. A gear train – usually nylon or metal, reducing speed and multiplying torque.
  3. A potentiometer – connected to the output shaft, it reports the current angle.
  4. A control circuit – reads the PWM signal and drives the motor until the potentiometer matches the commanded position.

This is a closed-loop system. When you send a 1.5ms pulse every 20ms, the servo interprets that as "go to 90 degrees." The control board compares the potentiometer reading to that target and spins the motor in the correct direction until the error is zero. That is why a servo holds its position even when you try to push it—it is constantly correcting.

The PWM Signal Explained

Arduino's Servo library abstracts this, but you should know the raw timing:

  • 0 degrees → 1.0 ms pulse
  • 90 degrees → 1.5 ms pulse
  • 180 degrees → 2.0 ms pulse

The pulse repeats every 20 ms (50 Hz). Some micro servos accept 0.5–2.5 ms for a wider range, but stick to 1.0–2.0 ms unless you enjoy hearing gears grind.

Hardware and Tools You Will Need

Core Electronics

  • Arduino Uno, Nano, or ESP32 (any will do)
  • Micro servo (SG90 is cheapest; MG90S has metal gears and lasts longer)
  • 5V power supply capable of at least 1A (do not power the servo from the Arduino's 5V pin if you value your voltage regulator)
  • Breadboard and jumper wires
  • 1000 µF electrolytic capacitor (across the servo's power rails to smooth current spikes)
  • Optional: RTC module (DS3231) for scheduled operation
  • Optional: LDR (photoresistor) or BH1750 light sensor for daylight-based control
  • Optional: push button or IR remote for manual override

Mechanical Parts

  • Curtain rod and curtain
  • 3D-printed or laser-cut servo mount
  • A small pulley or a 3D-printed spool that fits the servo horn
  • Braided fishing line or thin nylon cord
  • Small screw eyes or eyelets
  • Zip ties, double-sided tape, or hot glue

Tools

  • Soldering iron
  • Multimeter
  • Small screwdriver set
  • Drill with 2mm and 3mm bits
  • Calipers (helpful for measuring the curtain rod diameter)

Wiring the Circuit

Power First, Signal Second

The single most common mistake beginners make is powering a micro servo directly from the Arduino's 5V pin. A micro servo can draw 200–600 mA when moving, and stall current can exceed 1A. The Arduino's onboard regulator will overheat and reset. Always use a separate 5V supply.

Wiring steps:

  1. Connect the servo's red wire to the external 5V supply positive rail.
  2. Connect the servo's brown or black wire to the common ground.
  3. Connect the Arduino's GND to the same common ground.
  4. Connect the servo's orange or yellow signal wire to Arduino pin 9 (or any PWM-capable pin).
  5. Place the 1000 µF capacitor between the 5V and GND rails near the servo.

If you are using an ESP32, note that its PWM frequency and resolution differ. The ESP32Servo library handles this cleanly.

Adding a Sensor or RTC

For a light sensor, wire the LDR in a voltage divider with a 10k resistor to analog pin A0. For the DS3231, connect SDA to A4 and SCL to A5 on an Uno (or 21/22 on an ESP32).

The Code: From Basic Sweep to Scheduled Automation

Minimal Working Example

cpp

include <Servo.h>

Servo curtainServo;

const int SERVOPIN = 9; const int CLOSEDANGLE = 10; const int OPEN_ANGLE = 170;

void setup() { curtainServo.attach(SERVOPIN); curtainServo.write(CLOSEDANGLE); delay(1000); }

void loop() { curtainServo.write(OPENANGLE); delay(5000); curtainServo.write(CLOSEDANGLE); delay(5000); }

This sweeps the curtain open and closed every five seconds. It is ugly and impractical, but it proves the mechanism works.

Smooth Motion with Easing

Jerky movement will yank your curtain rod off the wall. Use a simple linear interpolation:

cpp void moveSlowly(int from, int to, int stepDelay) { int step = (from < to) ? 1 : -1; for (int angle = from; angle != to; angle += step) { curtainServo.write(angle); delay(stepDelay); } curtainServo.write(to); }

Set stepDelay to 15–25 ms for a natural, quiet motion. Anything faster sounds like a tiny robot having a panic attack.

Adding Real Scheduling

With a DS3231 RTC:

cpp

include <RTClib.h>

RTC_DS3231 rtc;

void loop() { DateTime now = rtc.now(); int hour = now.hour(); int minute = now.minute();

if (hour == 7 && minute == 0) { moveSlowly(CLOSEDANGLE, OPENANGLE, 20); } if (hour == 19 && minute == 30) { moveSlowly(OPENANGLE, CLOSEDANGLE, 20); } delay(1000); }

Add a bool flag to prevent the servo from re-triggering every second during that minute.

Light-Based Control

cpp int lightLevel = analogRead(A0);

if (lightLevel > 600) { moveSlowly(CLOSEDANGLE, OPENANGLE, 20); } else if (lightLevel < 200) { moveSlowly(OPENANGLE, CLOSEDANGLE, 20); }

Add hysteresis (different thresholds for opening and closing) or your curtain will oscillate like it is having an existential crisis at dusk.

Mechanical Design: Where Most Projects Fail

Torque Math You Cannot Ignore

An SG90 delivers about 1.5 kg·cm at 4.8V. If your curtain weighs 500 grams and the cord wraps around a 1 cm radius spool, you need 0.5 kg·cm just to lift it. That leaves a 3x safety margin—acceptable. But if your curtain is heavy blackout fabric weighing 2 kg, the SG90 will stall. Upgrade to an MG996R or a geared NEMA 17.

The Pulley and Cord Approach

The cleanest method:

  1. Mount the servo above one end of the curtain rod.
  2. Attach a small spool (10–15 mm diameter) to the servo horn.
  3. Run a continuous loop of braided fishing line through eyelets at both ends of the rod.
  4. Attach the curtain's leading edge to one side of the loop with a small clip.
  5. When the servo rotates, the loop moves, pulling the curtain.

This gives you bidirectional control with a single servo and no springs.

Alternative: Direct Drive with a Lever Arm

For lightweight curtains on a short rod, a 5 cm lever arm attached to the servo horn can push the curtain's first ring directly. Simpler, but limited to about 15–20 cm of travel.

Mounting Tips

  • Do not rely on hot glue alone for the servo mount. Use screws or zip ties.
  • Leave a small amount of slack in the cord. Too tight and the servo stalls at the endpoints.
  • Add a rubber grommet where the cord exits the housing to prevent fraying.
  • Test the full range of motion by hand before powering the servo.

Power Management and Noise Reduction

The Capacitor Is Not Optional

When a micro servo starts moving, it draws a sudden current spike. Without a capacitor, this can cause the Arduino to brown out or the servo to jitter. A 1000 µF electrolytic capacitor across the servo's power rails acts as a local energy reservoir.

Jitter and How to Kill It

Some micro servos jitter even when holding position. Causes include:

  • Insufficient power supply current
  • Long signal wires picking up noise
  • PWM frequency conflicts with other libraries (especially on ESP32)

Fixes: - Use a dedicated 5V 2A supply - Keep signal wires under 30 cm - Add a 100 nF ceramic capacitor between signal and ground - Use servo.writeMicroseconds() for finer control

Detaching the Servo

If your servo buzzes when idle, call curtainServo.detach() after movement. The trade-off is that the curtain may drift if the mechanism has any back-drive. For most curtain systems, the friction of the rod is enough to hold position.

Expanding the Project

Wi-Fi Control with ESP32

Swap the Uno for an ESP32 and add a simple web server:

cpp

include <WiFi.h>

include <WebServer.h>

WebServer server(80);

void handleOpen() { moveSlowly(CLOSEDANGLE, OPENANGLE, 20); server.send(200, "text/plain", "Curtain opened"); }

Now you can open your curtains from your phone. Add MQTT and you are one step from full Home Assistant integration.

Voice Control

Route the ESP32 through Alexa or Google Home using fauxmoESP or Espalexa. Saying "Alexa, open the curtains" never gets old.

Solar Tracking

Mount a small solar panel or use two LDRs on either side of a divider. Compare their readings and rotate the curtain to follow the sun. This is overkill for a bedroom but delightful for a greenhouse.

Troubleshooting Checklist

| Symptom | Likely Cause | Fix | |--------|-------------|-----| | Servo twitches constantly | Insufficient current | Add capacitor, use separate 5V supply | | Arduino resets when servo moves | Power draw from 5V pin | Move servo power to external supply | | Servo does not reach full angle | Mechanical binding | Loosen cord, check pulley alignment | | Curtain moves in wrong direction | Reversed angles in code | Swap OPENANGLE and CLOSEDANGLE | | Servo buzzes when idle | Holding torque against load | Detach servo or reduce load | | Movement is jerky | Large angle steps | Use moveSlowly() with 15–25 ms delay |

Final Thoughts on the Micro Servo as a Building Block

The micro servo motor is not the strongest actuator, the fastest, or the most precise. But it is small, cheap, easy to control, and available everywhere. For an automated curtain system, those trade-offs land in exactly the right place. You get a quiet, compact mechanism that hides inside a curtain rod and runs on a few hundred milliamps.

More importantly, mastering the micro servo teaches you the fundamentals of closed-loop control, PWM signaling, and mechanical advantage. Those skills transfer directly to robotic arms, camera sliders, animatronic props, and a hundred other projects. The curtain is just the beginning—and honestly, it is one of the most satisfying first builds you can hang on a wall.

Copyright Statement:

Author: Micro Servo Motor

Link: https://microservomotor.com/how-to-connect-a-micro-servo-motor-to-arduino/servo-automated-curtain-arduino.htm

Source: Micro Servo Motor

The copyright of this article belongs to the author. Reproduction is not allowed without permission.

About Us

Lucas Bennett avatar
Lucas Bennett
Welcome to my blog!

Tags