DIY Servo Light Painting Machine

DIY Servo Light Painting Machine | Arduino LED Art Robot for Kids | MakeMindz
📷 Arduino · Servo Motors · Long Exposure

DIY SERVO LIGHT PAINTING MACHINE

Two servo motors sweep a glowing LED through the dark while a camera captures the light trail — your robot draws glowing art in thin air! 💡🎨

⏱️ 3–4 Hours 🔧 Medium Build 🎓 Age 12+ 💰 ~₹1,400 📷 Photography Art
SV-X SV-Y LED ARDUINO UNO Controls both servos 📷 Long Exposure Exposure: 10s
🌑 Dark Room Turn off all lights before starting
📷 Open Shutter Camera captures every LED position
💡 LED Paints Servos sweep the light — art appears!

🔬 HOW LIGHT PAINTING WORKS

Light painting is a photography technique where you keep the camera shutter open in a dark room while a light source moves. Every position the light visits gets recorded permanently in the photo — even though you can't see the full picture until the shutter closes!

By attaching the LED to two servo motors forming an X–Y gantry, the Arduino can move the LED to any position in a 2D grid — drawing shapes, letters, or patterns with perfect accuracy, every single time.

📐 X–Y Servo Gantry

Servo 1 sweeps left–right (X axis). Servo 2 tilts up–down (Y axis). Together they position the LED anywhere in a 2D space.

💡 LED as Paintbrush

The RGB LED is the brush — turn it ON at specific positions and OFF elsewhere to control exactly which parts of the shape get drawn.

📷 Long Exposure Magic

Camera shutter stays open 8–15 seconds while the LED moves through the entire pattern. When the shutter closes, the shape appears fully formed!

🧮 Coordinate Arrays

Shapes are stored as lists of (X, Y, LED_on) coordinates — like a connect-the-dots drawing but in servo angles.

📷 Real-World Connection: Professional light painters use this exact technique by hand — walking through dark rooms with LEDs and coloured wands. Your robot automates it perfectly, producing the same shape identically every single time!

🛒 PARTS SHOPPING LIST

Everything available on Amazon India or Robu.in. Total build cost ~₹1,400:

🔵
Arduino Uno R3 Controls both servos and the RGB LED from one board.
⚙️
2× MG90S Metal Gear Servo One sweeps X-axis (pan), one tilts Y-axis (tilt). Metal gears for precision.
💡
RGB LED (Common Cathode) The paintbrush — switches colour mid-drawing for multicolour art!
🔩
330Ω Resistors ×3 One on each RGB channel (R, G, B) to protect the LED.
🏗️
Pan-Tilt Servo Bracket Kit Pre-made 2-axis bracket that mounts both servos — much easier than building from scratch!
🧵
Small LED Holder / Arm Extension Mounts the LED at the tip of the tilt servo arm, pointing forward.
🟡
Push Button Press to start a drawing sequence — gives you time to walk away and start the camera!
📺
16×2 LCD + I²C Module (optional) Shows the current pattern name and which frame is being drawn.
📦
Dark Box / Stage (40cm × 40cm) A cardboard box painted black inside — the "drawing stage" the machine sits in.
🔌
Jumper Wires + Breadboard + 9V Battery For all wiring. 9V battery or USB power bank powers the Arduino.

CIRCUIT DIAGRAM

Simple and clean — just two servos and one RGB LED connected to one Arduino Uno:

SERVO LIGHT PAINTING MACHINE — WIRING DIAGRAM ARDUINO UNO 5V GND Pin 9 → Servo X Pin 10 → Servo Y Pin 3 → LED Red Pin 5 → LED Green Pin 6 → LED Blue Pin 2 → Button A4 / SDA (LCD) A5 / SCL (LCD) SERVO X — PAN Left-Right sweep MG90S · Pin 9 SERVO Y — TILT Up-Down angle MG90S · Pin 10 RGB LED Common Cathode R G B 330Ω resistor on each pin 🟡 Start Button Pin 2 + GND 10s delay to start Pattern: STAR Frame 3 of 10 LCD 16×2 I²C CAMERA SETTINGS Exposure: 10–15 sec ISO: 400–800 Aperture: f/8 Mode: Manual / Bulb LEGEND: Servo Signal LED RGB I²C All GNDs share Arduino GND. Servos powered from 5V pin.
📌 COMPLETE PIN REFERENCE — ARDUINO UNO Servo X — Pan (MG90S) ──────────────────────────────── Red wire ──► 5V Brown wire ──► GND Orange wire ──► Pin 9 // X-axis (horizontal sweep) Servo Y — Tilt (MG90S) ──────────────────────────────── Red wire ──► 5V Brown wire ──► GND Orange wire ──► Pin 10 // Y-axis (vertical tilt) RGB LED (Common Cathode) ──────────────────────────────── R pin → 330Ω → ──► Pin 3 // PWM G pin → 330Ω → ──► Pin 5 // PWM B pin → 330Ω → ──► Pin 6 // PWM GND (longest leg) ──► GND Start Button ──────────────────────────────── One leg ──► Pin 2 Other leg ──► GND // INPUT_PULLUP in code LCD (I²C — optional) ──────────────────────────────── SDA ──► A4 SCL ──► A5

📷 HOW TO TAKE A LIGHT PAINTING PHOTO

The machine + the camera work as a team. Here's the exact sequence every time you shoot:

01 🌑 Turn all lights off. Wait for eyes to adjust.
02 📷 Set camera: Manual, 12 sec, f/8, ISO 400.
03 🔲 Point camera at the machine. Open shutter.
04 🟡 Press the start button on your machine.
05 💡 Servos sweep. LED draws the pattern in light.
06 🌟 Shutter closes. Check your photo — art created!
📱 No DSLR? Use your smartphone in Pro mode (or NightSight on Pixel / Night mode on iPhone). Set exposure to maximum (8–15 seconds) in a fully dark room. Most modern phones capture light painting beautifully!

🔧 STEP-BY-STEP BUILD GUIDE

Build the frame first, then wire, then code. Take your time with the physical setup — accurate servo mounting makes the difference between blurry and sharp light trails!

1
BUILD THE PAN-TILT GANTRY

The machine uses a standard 2-axis pan-tilt servo bracket — you can buy a pre-made kit (much easier!) or build your own:

  • Pan-Tilt Kit Route (recommended): Buy a "Pan Tilt Servo Bracket" kit — includes two servo mounts and a camera plate for ~₹180 on Amazon
  • DIY Route: Mount Servo X horizontally on a base. Attach a vertical arm to its horn. Mount Servo Y at the top of that arm horizontally. Attach a short LED arm to Servo Y's horn
  • LED mount: Hot-glue a small piece of straw or tube at the very end of the tilt arm, pointing forward. Insert the RGB LED into this tube, legs trailing behind
  • Mounting base: Screw or glue the whole assembly to a flat wooden or acrylic base plate (~15cm × 15cm)
📐 Key measurement: The LED should sit exactly at the pivot point of the tilt servo's arc — this way it moves in a clean arc rather than drifting sideways. Adjust the arm length until the LED is centred over the tilt servo's shaft.
2
SET UP THE DARK STAGE

The light painting stage is where the magic happens — all stray light must be eliminated:

  • Take a cardboard box about 40cm × 40cm × 40cm and paint the inside completely flat black
  • Cut a viewing window in the front — large enough for your camera lens to look inside
  • Place the servo machine in the centre of the box floor
  • Cut a small cable hole at the back for the Arduino wires
  • Place the camera on a tripod, lens pointing through the viewing window
🌑 Why flat black? Glossy surfaces reflect stray light and create unwanted glow in the photo. Flat/matte black paint absorbs all light — making the only thing visible in the photo the LED trail itself!
3
INSTALL ARDUINO LIBRARY
Library Manager
// Search and install in Arduino IDE:
SketchInclude LibraryManage Libraries

"LiquidCrystal_I2C"   // LCD display (optional)
"Servo"               // Built-in — no install needed
// analogWrite() for LED PWM is built-in too
4
UPLOAD THE LIGHT PAINTER CODE

This is the complete code. It stores shapes as arrays of (X angle, Y angle, R, G, B) coordinates and sweeps the servo through each point:

light_painter.ino
#include <Servo.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

// ── Pin Definitions ────────────────────────────
#define SERVO_X_PIN   9    // Pan  (left–right)
#define SERVO_Y_PIN  10    // Tilt (up–down)
#define LED_R         3    // PWM
#define LED_G         5    // PWM
#define LED_B         6    // PWM
#define BTN_PIN       2    // Start button

Servo servoX, servoY;
LiquidCrystal_I2C lcd(0x27, 16, 2);

// ── LED control ─────────────────────────────────
void setLED(int r, int g, int b) {
  analogWrite(LED_R, r);
  analogWrite(LED_G, g);
  analogWrite(LED_B, b);
}
void ledOff() { setLED(0,0,0); }

// ── Move to angle and paint LED colour ──────────
// Glide smoothly from current position to target
void moveTo(int tx, int ty, int r, int g, int b, int stepMs=12) {
  int cx = servoX.read();
  int cy = servoY.read();
  int steps = max(abs(tx-cx), abs(ty-cy));
  if (steps == 0) return;
  for (int s = 1; s <= steps; s++) {
    servoX.write(map(s, 0, steps, cx, tx));
    servoY.write(map(s, 0, steps, cy, ty));
    setLED(r, g, b);
    delay(stepMs);
  }
}

// Travel without LED (move to start of next stroke)
void travelTo(int tx, int ty) {
  ledOff();
  moveTo(tx, ty, 0,0,0, 6);   // faster travel
}

/* ══════════════════════════════════════════
   SHAPE PATTERNS
   Each row: { angleX, angleY, R, G, B }
   LED off during travel, on during drawing.
   Servo X range: 40–140°
   Servo Y range: 50–120°
   Centre is X=90, Y=85
══════════════════════════════════════════ */

// ── Pattern: STAR ──────────────────────────────
struct Point { int x, y, r, g, b; };

Point starPts[] = {
  {90, 55, 255, 200,   0},  // top point
  {108,78, 255, 200,   0},  // upper-right inner
  {128,68, 255, 200,   0},  // right point
  {114,90, 255, 200,   0},  // lower-right inner
  {122,112,255, 200,   0},  // lower-right point
  {90, 100,255, 200,   0},  // lower-middle inner
  {58, 112,255, 200,   0},  // lower-left point
  {66, 90, 255, 200,   0},  // lower-left inner
  {52, 68, 255, 200,   0},  // left point
  {72, 78, 255, 200,   0},  // upper-left inner
  {90, 55, 255, 200,   0},  // back to top (close)
};

// ── Pattern: HEART ─────────────────────────────
Point heartPts[] = {
  {90, 72,   0, 0, 255},  // top centre
  {73, 60,   0, 0, 255},  // top-left curve
  {56, 66,   0, 0, 255},  // left bump
  {52, 82,   0, 0, 255},  // left side
  {70, 100,  0, 0, 255},  // lower-left
  {90, 115,  0, 0, 255},  // bottom point
  {110,100,  0, 0, 255},  // lower-right
  {128,82,   0, 0, 255},  // right side
  {124,66,   0, 0, 255},  // right bump
  {107,60,   0, 0, 255},  // top-right curve
  {90, 72,   0, 0, 255},  // back to top
};

// ── Draw a pattern from array of points ─────────
void drawPattern(Point* pts, int count, String name) {
  Serial.print("Drawing: "); Serial.println(name);
  lcd.clear(); lcd.print("Drawing: " + name);

  travelTo(pts[0].x, pts[0].y);   // go to start (LED off)
  delay(200);

  for (int i = 0; i < count; i++) {
    lcd.setCursor(0, 1);
    lcd.print("Pt " + String(i+1) + " of " + String(count));
    moveTo(pts[i].x, pts[i].y,
            pts[i].r, pts[i].g, pts[i].b);
  }
  ledOff();
  Serial.println("Done!");
}

// ── Setup ───────────────────────────────────────
void setup() {
  Serial.begin(9600);
  servoX.attach(SERVO_X_PIN);
  servoY.attach(SERVO_Y_PIN);
  servoX.write(90);   // centre
  servoY.write(85);   // neutral tilt

  pinMode(LED_R, OUTPUT); pinMode(LED_G, OUTPUT); pinMode(LED_B, OUTPUT);
  pinMode(BTN_PIN, INPUT_PULLUP);
  ledOff();

  lcd.init(); lcd.backlight();
  lcd.print("Light Painter");
  lcd.setCursor(0,1); lcd.print("Press to start!");
  Serial.println("Light Painter ready. Press button to start!");
}

// ── Main Loop ───────────────────────────────────
int patternIndex = 0;

void loop() {
  if (digitalRead(BTN_PIN) == LOW) {
    delay(50);   // debounce
    if (digitalRead(BTN_PIN) == LOW) {

      // 5-second countdown for camera setup!
      for (int i = 5; i > 0; i--) {
        lcd.clear(); lcd.print("Starting in: ");
        lcd.setCursor(0,1); lcd.print(String(i) + " sec...");
        Serial.println("Starting in " + String(i));
        delay(1000);
      }

      // Draw alternating patterns
      if (patternIndex % 2 == 0) {
        drawPattern(starPts,  sizeof(starPts)/  sizeof(Point), "STAR");
      } else {
        drawPattern(heartPts, sizeof(heartPts)/ sizeof(Point), "HEART");
      }
      patternIndex++;

      // Return to centre
      travelTo(90, 85);
      lcd.clear(); lcd.print("Done! Check photo");
      lcd.setCursor(0,1); lcd.print("Press for next!");
      delay(1000);   // wait for button release
    }
  }
}
🎨 How to add your own shapes: Add a new Point array with the X/Y servo angles and RGB colours for each point of your shape. Tip: map your shape on paper first with a 40×70 grid (X: 40–140, Y: 50–120), then read off the coordinates for each corner or curve point!
🌈 Multi-colour drawing: Change the R, G, B values mid-pattern! In the star example, change some points to {x, y, 0, 255, 0} (green) and others to {x, y, 255, 0, 128} (magenta) — each segment of the shape becomes a different colour in the photo!
5
TAKE YOUR FIRST LIGHT PAINTING PHOTO

Everything is ready — here's how to capture your first light painting image:

  • Put your camera on a tripod, aimed at the machine inside the dark box
  • Set to Manual mode: Shutter 12 sec, f/8, ISO 400 (adjust if too bright/dark)
  • Turn off ALL room lights — completely dark is critical
  • Press the camera shutter — it starts counting 12 seconds
  • Immediately press the machine's start button — it counts down 5 seconds then draws
  • Don't move! When the shutter closes, check the photo
✅ Perfect exposure: If the star/heart looks too bright and washed out, reduce ISO to 200. If it's too dim, increase to 800 or slow the servo movement (increase stepMs in moveTo() to 20). The goal is a crisp bright line on a pure black background!

🛠️ TROUBLESHOOTING GUIDE

Light painting has two systems to debug — the machine and the camera:

🔴 Problem🟡 Likely Cause✅ Fix
Photo is completely black Shutter too fast / ISO too low / LED not on Check LED wires and analogWrite values. Try ISO 800, shutter 15 sec
Shape looks wobbly / distorted Servo moves too fast — motion blur Increase stepMs in moveTo() from 12 to 20ms — slower = sharper trails
Shape is too small in frame Servo angle range too narrow Increase the angle spread in your Point array (extend X from 40–140 wider)
Button doesn't trigger start INPUT_PULLUP logic inverted Button must connect pin to GND. Code checks for LOW = pressed — correct
Servo skips positions Power insufficient for two servos Use external 5V power supply for servos, share GND with Arduino
Lines appear between shapes LED not turning off during travelTo() Confirm ledOff() is called in travelTo() before moving to the next start point
Photo shows a straight line, not a shape Only one servo moving — other disconnected Test each servo separately. Check Pin 9 → ServoX and Pin 10 → ServoY wiring

🚀 LEVEL UP YOUR LIGHT PAINTER

Once your machine draws stars and hearts, these upgrades unlock professional light art:

🔤 Write Words

Map out letter coordinates — the machine writes your name in glowing light!

🎵 Music Reactive

Add a microphone — LED colour and speed change with the rhythm of music playing!

📱 Bluetooth Drawing

Add HC-05 module — draw freehand shapes from a phone app over Bluetooth!

NeoPixel Strip

Replace the single LED with a NeoPixel stick — draw with multiple simultaneous colours!

🖥️ SVG Import

Write a Python script that converts any SVG path into servo angle coordinates automatically!

🎞️ Time-Lapse Mode

Program the machine to draw a different frame each shot — create an animated light painting series!


❓ FREQUENTLY ASKED QUESTIONS

Why does the photo need to be taken in complete darkness?

During a 12-second exposure, any ambient light in the room will add up and appear in the photo — washing out the LED trail or creating a bright background. In complete darkness, the only thing the camera records is the LED's position at every moment it was on, giving you a pure glowing line on pure black.

Can I use my phone camera instead of a DSLR?

Yes! Most modern smartphones have a "Pro" or "Manual" mode that lets you set exposure time to 10–15 seconds. iPhone users can use the Night mode (it automatically does long exposures). Android users look for "Pro" mode in the camera app. Place the phone on a stable surface or mini tripod — any movement during the exposure will blur the result.

How do I make my own shapes beyond star and heart?

Draw your shape on graph paper. Mark key points (corners, curve peaks) and estimate their position on a grid where X goes 40–140 (left to right) and Y goes 50–120 (bottom to top). Create a new Point[] array in the code with those values. Start simple — a triangle, square, or letter E — and work up to complex shapes.

The shape looks right in Serial Monitor but distorted in the photo — why?

Servo angular response isn't perfectly linear, and the tilt servo creates arc movement rather than straight lines. For very precise shapes, add intermediate points along each line segment to break curves into small straight steps. Professional light painting robots solve this with inverse kinematics — a great advanced challenge!

Is this a good science fair or school project?

Outstanding choice — it spans physics (optics, light, camera exposure), engineering (servo control, XY positioning, circuit design), mathematics (coordinate systems, angle mapping), and art (composition, colour, visual design). The photos themselves are beautiful exhibition material. Try varying exposure time and documenting how it affects brightness — that's a clean, measurable experiment.

Can the machine draw with multiple colours in the same shape?

Absolutely — that's one of the most exciting features! Each point in the array can have its own R, G, B values. So the first half of a star can glow cyan, and the second half amber. The camera captures all the colours simultaneously in a single photo because the LED was each colour at each position during the exposure.

Where robotics meets art — in the dark.

#LightPaintingMachine #ArduinoArt #ServoRobot #LongExposure #LightPainting #KidsRobotics #STEMProject #MakeMindz #ArduinoForKids #LightArtRobot

Comments

Product Cards
Buddy Bot eBook
⭐ New 2026 Release
Build Your
Own Robot!
3D design, wiring &
Arduino coding.
Young inventors love it!
🖨️
3D Print
All parts
Wire it
Circuit guide
💻
Code it
Arduino IDE
🤖
Watch it
Walk & react
📋 Your Details
Enter your name
Valid 10-digit no.
Enter a valid email
Special Website Offer
₹499 300
🌍 International: $5 USD
One-time · Instant digital delivery
🔒 Secured by Razorpay · Your data is safe
📄 Download Free Sample Copy
🔒 Secured by Razorpay · Your data is safe
🍓
Raspberry Pi Pico Mastery
21 Projects
⚡ Launch Price — 80% OFF
Learn Pico
Build 21 Projects!
MicroPython · Wokwi
IoT · Certificate
Perfect for beginners!
🖥️
Wokwi
No hardware
🐍
MicroPy
From zero
🔨
21 Projects
IoT + sensors
📄
Certificate
Verified cert
📋 Your Details
Enter your name
Valid 10-digit no.
Enter a valid email
Special Launch Offer
₹999 200 80% OFF
🌍 International: $5 USD
One-time · Lifetime access · No subscription
🔒 Secured by Razorpay · UPI · Cards · NetBanking
🎉

You're in!

Payment successful! Your Buddy Bot eBook is ready. Time to build!

📖 Access Your eBook Now
🎉

Enrolled!

Payment successful! Lifetime access to all 21 Pico Projects is yours!

🍓 Go to My Course