DIY Peacock Robot with 20+ Servo Motors & ESP32

DIY Peacock Robot with 20+ Servo Motors & ESP32 – Robotics Project for Kids | Animated Feather Display
Animatronics · 22 Servos · ESP32 · Natural Feathers

The Peacock Robot
That Dances

22 synchronized servo motors open a full tail fan, ripple feathers in waves, draw spirals and hearts in the air, sway the neck, blink real eyes — all choreographed by a single ESP32. 🦚

Expert Difficulty 4–6 Weekends Build Age 14+ With Adult ~₹12,000–₹18,000 Arduino C++
Begin the Build ↓
Mission Briefing

What Are We Actually Building?

This is the most ambitious robotics project in this entire series — and arguably the most beautiful. A life-sized (or half-sized) peacock sculpture stands on a glossy black stage. Its skeleton is built from aluminium rods and 3D-printed joints. Twenty-two servo motors are embedded throughout the structure, controlled by two PCA9685 servo driver boards daisy-chained to a single ESP32.

When the program runs, the peacock performs a full choreographed display:

  1. The tail fan opens slowly from closed to full spread (approximately 140° arc)
  2. A ripple wave rolls from left to right across all 10 tail feathers simultaneously
  3. The feathers draw a spiral pattern — each one traces an arc like spokes on a spinning wheel
  4. All feathers form a heart shape by curving inward at the right timing
  5. The neck sways gently left to right while the head tilts and turns
  6. Both eyes blink using small servo-actuated eyelid mechanisms
  7. The body bobs up and down slightly with the rhythm
  8. Finally, the tail fans out and closes repeatedly in a graceful dance

Natural peacock feathers are mounted on servo arms so they physically move. Under coloured LED lighting, the iridescent feather eyes shimmer with every movement — exactly like a real peacock display, but controlled entirely by code you write.

🦚 Real science connection: Peacock displays are studied by biologists to understand animal signalling and mate selection. Your robot demonstrates the same mechanical principles of coordinated motion that scientists study in live birds — but you can program it to do patterns that real peacocks never could!
The 22-Servo System

Every Servo's Role

Each servo has a specific job. Two PCA9685 boards daisy-chained handle all 22 channels. Board A = tail and body. Board B = head, neck, and eyes.

Tail Feathers — Board A (Ch 0–9)

ChServoMotion
A0Feather 1 (Far Left)Rotate 0–90°
A1Feather 2Rotate 0–90°
A2Feather 3Rotate 0–90°
A3Feather 4Rotate 0–90°
A4Feather 5 (Left Mid)Rotate 0–90°
A5Feather 6 (Centre)Rotate 0–90°
A6Feather 7 (Right Mid)Rotate 0–90°
A7Feather 8Rotate 0–90°
A8Feather 9Rotate 0–90°
A9Feather 10 (Far Right)Rotate 0–90°

Body & Tail Spread — Board A (Ch 10–15)

ChServoMotion
A10Tail Left SpreadFan left arc 0–70°
A11Tail Right SpreadFan right arc 0–70°
A12Tail ElevationTilt up/down 60–110°
A13Body Sway L/RLean ±20°
A14Body Bob Up/DownRise/fall 10mm
A15Wing L (open/close)0–45° spread

Head & Neck — Board B (Ch 0–5)

ChServoMotion
B0Neck Pan (L/R)±40° from centre
B1Neck Tilt (U/D)±20° nod
B2Head Turn±30° yaw
B3Head Tilt±20° roll
B4Left Eye Blink0–30° eyelid
B5Right Eye Blink0–30° eyelid
⚙️ Why two boards? Each PCA9685 handles 16 servo channels. With 22 servos, one board handles tail + body (channels A0–A15), and the second handles head + neck (channels B0–B5 on the second board's address). Both boards share the same I²C bus from the ESP32 but have different I²C addresses.
Animation Choreography

The 8 Dance Patterns

Each pattern is a mathematical function applied across the 10 tail feather servos. The beauty of this system is that incredibly complex visual effects come from simple trigonometry.

🌊

Ripple Wave

A sine wave travels left to right across the feathers. Each feather's angle is offset by a delay — the wave appears to travel across the whole fan.

angle[i] = centre + amplitude × sin(t + i × delay)
🌀

Spiral

Each feather rotates by a continuously increasing offset, making the whole fan appear to spin like a galaxy, spiralling inward then outward.

angle[i] = base + (i × 14°) + t × speed
❤️

Heart Pattern

Feathers curve inward symmetrically from both edges toward the centre — the tips form the top lobes of a heart, while centre feathers form the bottom point.

angle[i] = heart_curve(i, t)
🌸

Bloom Open

Starting from fully closed, all feathers radiate outward to their final spread positions simultaneously, like a flower blooming in slow motion.

angle[i] = lerp(closed, open, easeOut(t))

Electric Shimmer

Very rapid small oscillations across all feathers at slightly different frequencies create a shimmering, electrified look — perfect under LED lighting.

angle[i] = base + 6 × sin(t × (8+i))
🌈

Rainbow Cascade

Feathers open one at a time from left to right, each waiting for the previous to complete — like a rainbow appearing stroke by stroke.

start_time[i] = i × delay_ms
💃

Dance Sway

Combines body lean left/right with feather ripple and neck sway all in synchrony — the whole robot sways rhythmically like a dancer.

body[A13] = 20 × sin(t × dance_bpm)
🎭

Greeting Bow

Neck bends forward and down while feathers close briefly, then spring open again as the head rises — like a performer taking a bow.

neck_tilt = bow_curve(t); fan = bloom(t+0.5)
Parts Checklist

Everything You Need

Order in stages — start with the electronics and test them before buying structural materials.

🧠 Electronics

~₹450

ESP32 Dev Board

Master controller — dual-core 240MHz, plenty of speed to run all 22 servo calculations simultaneously.

~₹800

2× PCA9685 16-Ch Servo Driver

Each board drives up to 16 servos via I²C. Daisy-chained with different addresses (0x40 and 0x41).

~₹450

5V 10A Power Supply

Servos at full load can draw 500mA each. 22 servos × 0.5A = 11A peak. A 10A supply handles real-world usage comfortably.

~₹200

DC-DC Buck Converter (5V 3A)

Separate 5V regulated supply for ESP32 and logic — never share servo power with the microcontroller.

~₹150

Capacitors (1000µF 16V × 4)

Placed near each servo power rail on the breadboard — absorbs voltage spikes when multiple servos move at once.

~₹100

Toggle Switch + Power LED

Main on/off switch for the 5V servo supply, with a status LED to show the system is live.

⚙️ Servo Motors

~₹3,600

18× MG996R Metal Gear Servo

For all 10 tail feathers (individual rotation) + tail spread arms + body sway + wing. Metal gears essential — plastic strips under load.

~₹480

4× SG90 Micro Servo

Lighter-duty servos for eye blink and head tilt where weight matters more than torque. Small and lightweight.

🏗️ Structure

~₹800

Aluminium Round Rod (6mm, 2m)

Forms the spine, neck, and tail fan spreader arms. Lightweight but rigid. Cut to size with a hacksaw.

~₹600

3D Printed Joints & Servo Mounts

Custom printed brackets that connect servos to the aluminium frame. Print in PETG for strength. Free STL designs on Thingiverse.

~₹400

Glossy Black Acrylic Stage (30×30cm)

The performance platform. Acrylic gives the mirror-reflection effect under LED lighting. Drill mounting holes for the peacock base.

~₹200

M3 Bolts, Nuts, Washers (Assorted)

For securing servo mounts to the aluminium frame. Thread-locking compound prevents vibration from loosening joints during performance.

🦚 Feathers & Decoration

~₹600

20 Real Peacock Tail Feathers

Available from craft shops and bird farms. Use genuine iridescent feathers — the shimmer effect under LED light is breathtaking. Larger "eye" feathers for display, smaller coverts for fill.

~₹300

RGB LED Strip (5V WS2812B, 2m)

Back-lights the stage and feathers from below. Controlled by a second ESP32 GPIO pin. Changes colour to match each dance pattern.

~₹200

Foam Craft Sheet (Blue/Green)

For the body covering — cut to shape and paint with iridescent craft paint to simulate feather texture on the body and neck.

~₹150

Glass Dome Eyes (20mm, amber)

Pre-made realistic bird eyes give the head an authentic alive look. Glue into 3D-printed eye sockets with small SG90 servos behind them for blinking.

Circuit Diagram

Full Wiring Architecture

Two PCA9685 boards share one I²C bus. Board A controls tail feathers and body. Board B controls head, neck, and eyes. Both get power from the 5V 10A supply.

5V / 10A PSU Main Servo Power V+ GND Buck 5V/3A ESP32 logic power ESP32 Dev Board GPIO21 SDA GPIO22 SCL 3.3V GND GPIO4 (LEDs) 5V IN PCA9685 Board A I²C addr: 0x40 Ch 0–9: Feathers 1–10 Ch 10–11: Tail Spread Ch 12: Tail Elevation Ch 13–14: Body Sway Ch 15: Wing L VCC GND SDA SCL A0=0 PCA9685 Board B I²C addr: 0x41 Ch 0: Neck Pan L/R Ch 1: Neck Tilt U/D Ch 2: Head Turn Ch 3: Head Tilt Ch 4: L Eye Blink Ch 5: R Eye Blink A0=1 SDA/SCL shared bus 5V logic 1000µF Servo Motors 10× MG996R — TAIL FEATHERS 6× MG996R — SPREAD+BODY 4× MG996R — NECK+HEAD 2× SG90 — EYE BLINK WS2812B RGB LED Strip Stage backlighting Power rail
I²C bus (SDA/SCL shared)
5V servo power
5V logic (ESP32)
Ground
LED data (GPIO4)

Critical wiring notes: (1) Never share the servo 5V rail with the ESP32 — motor current spikes can reset the microcontroller. (2) Add 1000µF capacitors across the 5V/GND rails near each PCA9685 board. (3) Both PCA9685 boards share the same SDA/SCL lines but have different I²C addresses — set address using the A0 jumper pad on each board (Board A: A0 unsoldered = 0x40, Board B: A0 soldered = 0x41).

Structural Build

Building the Frame

The frame has three sub-assemblies that build independently before being joined.

A

The Spine and Tail Mount

Cut a 40cm length of 6mm aluminium rod as the main spine. At the bottom, bolt it to a 3D-printed base plate that will be screwed to the acrylic stage. At the top (30cm up), attach a 3D-printed T-junction where the neck rod meets the tail fan bracket.

The tail fan bracket is a semi-circular aluminium strip (30cm diameter arc) with 10 servo mounting holes spaced evenly around it. Each MG996R servo mounts upward through these holes, shaft pointing up — this is where the feathers attach.

B

The Neck Assembly

The neck is two servo mechanisms stacked: a pan servo (horizontal rotation) mounted on top of the spine T-junction, and a tilt servo (nod up/down) above that. A 15cm rod connects the tilt servo to the head mount ball.

  • Spine T-junction → Neck Pan servo (Board B, Ch 0)
  • Pan output → Neck Tilt servo arm (Board B, Ch 1)
  • Tilt output → 15cm aluminium rod → Head Ball Joint
C

The Head Assembly

3D print a hollow egg-shaped head (60mm diameter). Mount the Head Turn servo inside the neck connector, and the Head Tilt servo above it. The two SG90 eye-blink servos sit behind the eye sockets with a thin plastic arm that acts as the eyelid.

🎭 Eye realism tip: Add a small warm-white LED behind each glass eye. When the eye is "open" the LED shines through, when it "blinks" the servo closes the lid. The effect of light through a glass dome eye is remarkably lifelike.
D

Body and Wing Mounts

The body is an oval foam core (approx 12×8×6cm) carved from styrofoam and covered with iridescent craft foam. Two holes in the bottom mount it on the spine. The body sway servo (Board A, Ch 13) connects via a push-rod to the body block. Wing rods (aluminium, 12cm) extend from each side with an MG996R at the shoulder joint.

The Magic Touch

Mounting the Natural Feathers

1

Prepare the Feathers

Select 10 matched peacock tail feathers of similar length (ideally 50–70cm). Lay them on a flat surface and sort them by size — the largest go in the centre, slightly smaller ones toward the edges. Trim the quill (stem) at the bottom with sharp scissors to leave 15cm of quill below the feather vane.

2

Create Feather Holders

3D print or cut 10 small tube holders (8mm inner diameter, 6cm long) that can grip each quill tightly. The top of each holder has a slot for the servo horn. Drill one small hole through the side for a set screw that grips the quill without crushing it.

🌿 Alternatively: Use a hot glue gun to bond each quill into a short piece of drinking straw cut to 5cm, then zip-tie the straw to the servo horn. Quick, light, and surprisingly strong.
3

Attach to Servo Horns

Position all 10 tail servos to their 0° position (closed). Attach each feather holder to the corresponding servo horn with the feather resting against the back plate. When the servo rotates to 90°, the feather should swing forward to its display position. Tighten all set screws and test each one manually before programming.

4

Balance Check

With all 10 feathers attached, run the fan-open sequence and check that no feather catches on another. The feathers should overlap slightly when fully open (like a real peacock tail) — this is correct. If any feather is twisted, loosen its holder, straighten it, and re-tighten. Add small neodymium magnets as inter-feather guides if needed to prevent tangling during fast movements.

Full Assembly

Step-by-Step Build Log

1

Set Up the Stage Platform

Drill a 12mm hole in the centre of the acrylic stage for the spine rod. Attach four rubber feet to the underside. Run the 5V power supply cable and LED strip cable through the hole before inserting the base plate. Secure the base plate with M3 countersunk bolts from below.

2

Install the Electronics Box

Mount the ESP32, both PCA9685 boards, buck converter, and capacitors on a small project board attached to the back of the spine rod, approximately 10cm above the stage floor. Connect I²C wires (SDA, SCL, 3.3V, GND) from the ESP32 to both PCA9685 boards. Connect the 5V servo power bus with thick wires (at least 20 AWG) to both boards' V+ and GND terminals.

⚠️ IMPORTANT: Thick power wires are essential. Thin wires will overheat at the currents drawn by 22 servos moving simultaneously. Use minimum 20 AWG for power, and 24 AWG for signal wires.
3

Mount Tail Servos on Fan Bracket

Install all 10 MG996R tail servos into the fan bracket holes. Connect each servo's 3-wire cable to the PCA9685 Board A channels 0–9 respectively (left-to-right = Ch0 to Ch9). Route the cables neatly down the back of the bracket and secure with cable ties every 5cm.

4

Connect Head and Neck Servos

Wire the 4 MG996R neck/head servos and 2 SG90 eye servos to PCA9685 Board B channels 0–5. Test each servo individually using a servo test sketch before attaching the mechanical assembly — confirming correct motion before assembly saves enormous time.

5

Install LED Stage Lighting

Attach the WS2812B LED strip in a ring under the acrylic stage edge, facing inward and upward. Connect its data line to GPIO4 on the ESP32. Install the Adafruit NeoPixel library and test the LEDs with a rainbow cycle before continuing.

💡 For maximum drama: add a second LED strip along the back of the tail fan bracket. When the feathers open, back-lit feather eyes glow spectacularly under the LED colours.
6

Calibrate All Servos

Upload the calibration sketch (provided in the code section below) to find the exact minimum and maximum pulse widths for each of your specific servo units — they vary by ±10% from the nominal values. Record these in a calibration table and enter them as constants in the main code. This step makes the difference between rough and silky-smooth motion.

The Brain

Full ESP32 Peacock Code

This code manages all 22 servos across two PCA9685 boards with smooth interpolation, and cycles through all 8 dance patterns automatically.

Install These Libraries First

# In Arduino Library Manager, install:
# • Adafruit PWM Servo Driver Library  (PCA9685)
# • Adafruit NeoPixel                  (LED strip)
# • Wire.h                             (built-in I²C)
/*
  Peacock Dance Robot — Full Choreography Code
  ESP32 + 2× PCA9685 + 22 Servo Motors + WS2812B LEDs
  Board A (0x40): Tail feathers 0–9, spread 10–11, body 12–14
  Board B (0x41): Neck 0–1, head 2–3, eyes 4–5
*/

#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
#include <Adafruit_NeoPixel.h>
#include <math.h>

// ── Hardware objects ────────────────────────────────────────────
Adafruit_PWMServoDriver boardA = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver boardB = Adafruit_PWMServoDriver(0x41);
Adafruit_NeoPixel strip(30, 4, NEO_GRB + NEO_KHZ800);

// ── Servo pulse width constants (µs → PCA9685 ticks at 50Hz) ───
// IMPORTANT: Calibrate these for YOUR specific servos!
#define SERVOMIN  150    // ~0.5ms pulse = 0°
#define SERVOMAX  600    // ~2.5ms pulse = 180°
#define SERVOMID  375    // ~1.5ms pulse = 90°

// ── Channel assignments ─────────────────────────────────────────
#define NUM_TAIL     10   // channels A0–A9
#define CH_SPREAD_L  10   // Board A
#define CH_SPREAD_R  11
#define CH_TAIL_ELV  12
#define CH_BODY_SWAY 13
#define CH_BODY_BOB  14
#define CH_NECK_PAN  0    // Board B
#define CH_NECK_TILT 1
#define CH_HEAD_TURN 2
#define CH_HEAD_TILT 3
#define CH_EYE_L    4
#define CH_EYE_R    5

// ── State arrays ─────────────────────────────────────────────────
float featherAngle[NUM_TAIL] = {90,90,90,90,90,90,90,90,90,90};  // 90 = centre
float currentAngle[NUM_TAIL];  // actual displayed angle

uint32_t t = 0;   // global animation frame counter
int      currentPattern = 0;
uint32_t patternStart   = 0;
const uint32_t PATTERN_DUR = 12000;  // 12 seconds per pattern

// ── Convert angle (0–180°) to PCA9685 tick value ────────────────
uint16_t angleToPulse(float angle) {
  angle = constrain(angle, 0, 180);
  return (uint16_t) map((long)(angle * 100), 0, 18000, SERVOMIN, SERVOMAX);
}

// ── Write to Board A or B ────────────────────────────────────────
void setServoA(uint8_t ch, float angle) {
  boardA.setPWM(ch, 0, angleToPulse(angle));
}
void setServoB(uint8_t ch, float angle) {
  boardB.setPWM(ch, 0, angleToPulse(angle));
}

// ── Smooth interpolation helper ──────────────────────────────────
float lerpf(float a, float b, float t) { return a + (b - a) * constrain(t,0,1); }
float easeInOut(float t) { return t*t*(3-2*t); }

// ═══════════════════════════════════════════════════════════════
//   PATTERN 0 — RIPPLE WAVE                                     
// ═══════════════════════════════════════════════════════════════
void patternRipple(float phase) {
  float f = phase * 6.28f;
  for (int i = 0; i < NUM_TAIL; i++) {
    featherAngle[i] = 90 + 35 * sin(f + i * 0.62f);
  }
  // Neck follows the wave
  setServoB(CH_NECK_PAN, 90 + 20 * sin(f));
  setServoB(CH_HEAD_TURN, 90 + 15 * sin(f + 0.5f));
  // Peacock colours
  setLEDPattern(0, 150, 137);  // teal
}

// ═══════════════════════════════════════════════════════════════
//   PATTERN 1 — SPIRAL                                          
// ═══════════════════════════════════════════════════════════════
void patternSpiral(float phase) {
  float f = phase * 6.28f;
  for (int i = 0; i < NUM_TAIL; i++) {
    float offset = i * (180.0f / NUM_TAIL);
    featherAngle[i] = 90 + 45 * sin(f + offset * 0.0175f);
  }
  setServoA(CH_BODY_SWAY, 90 + 12 * sin(f * 2));
  setLEDPattern(100, 0, 200);  // purple
}

// ═══════════════════════════════════════════════════════════════
//   PATTERN 2 — HEART                                           
// ═══════════════════════════════════════════════════════════════
void patternHeart(float phase) {
  float t2 = easeInOut(sin(phase * 3.14f) * 0.5f + 0.5f);
  for (int i = 0; i < NUM_TAIL; i++) {
    float norm = (float)i / (NUM_TAIL - 1);  // 0.0 to 1.0 left to right
    float heartY;
    if (norm < 0.5f) {
      float x = norm * 2 - 1;   // -1 to 0
      heartY = sqrt(1 - (x + 0.5f) * (x + 0.5f) * 1.2f);
    } else {
      float x = norm * 2 - 1;   // 0 to 1
      heartY = sqrt(1 - (x - 0.5f) * (x - 0.5f) * 1.2f);
    }
    featherAngle[i] = 90 + (40 * heartY - 20) * t2;
  }
  setServoB(CH_NECK_TILT, 90 - 10 * t2);
  setLEDPattern(220, 20, 60);   // rose red
}

// ═══════════════════════════════════════════════════════════════
//   PATTERN 3 — BLOOM OPEN & CLOSE                              
// ═══════════════════════════════════════════════════════════════
void patternBloom(float phase) {
  float spread = easeInOut(phase < 0.5f ? phase * 2 : (1 - phase) * 2);
  for (int i = 0; i < NUM_TAIL; i++) {
    float delay = abs(i - 4.5f) * 0.08f;   // centre opens first
    float localT = constrain((phase - delay) / (1.0f - delay), 0, 1);
    featherAngle[i] = lerpf(90, 90 + 50 * (i < 5 ? -1 : 1), easeInOut(localT));
  }
  setServoA(CH_SPREAD_L, lerpf(90, 140, spread));
  setServoA(CH_SPREAD_R, lerpf(90, 40,  spread));
  setLEDPattern(0, 180, 80);   // emerald
}

// ═══════════════════════════════════════════════════════════════
//   PATTERN 4 — ELECTRIC SHIMMER                                
// ═══════════════════════════════════════════════════════════════
void patternShimmer(float phase) {
  float f = phase * 12.56f;  // 2 full cycles per pattern
  for (int i = 0; i < NUM_TAIL; i++) {
    featherAngle[i] = 90 + 6 * sin(f * (8 + i * 1.5f) + i * 0.8f);
  }
  setServoA(CH_BODY_BOB, 90 + 8 * sin(f * 3));
  uint32_t cTime = millis();
  uint8_t r = 128 + 127 * sin(cTime * 0.003f);
  uint8_t g = 128 + 127 * sin(cTime * 0.004f + 2.1f);
  uint8_t b = 128 + 127 * sin(cTime * 0.005f + 4.2f);
  setLEDPattern(r, g, b);
}

// ═══════════════════════════════════════════════════════════════
//   PATTERN 5 — RAINBOW CASCADE                                 
// ═══════════════════════════════════════════════════════════════
void patternCascade(float phase) {
  for (int i = 0; i < NUM_TAIL; i++) {
    float startT = i * 0.08f;
    float localT  = constrain((phase - startT) / 0.5f, 0, 1);
    float target  = (i < 5) ? 90 - 40 : 90 + 40;
    featherAngle[i] = (phase < 0.5f)
      ? lerpf(90, target, easeInOut(localT))
      : lerpf(target, 90,  easeInOut(constrain((phase - 0.5f - startT) / 0.5f, 0, 1)));
  }
  setLEDPattern(255, 165, 0);  // gold
}

// ═══════════════════════════════════════════════════════════════
//   PATTERN 6 — DANCE SWAY                                      
// ═══════════════════════════════════════════════════════════════
void patternDance(float phase) {
  float beat = sin(phase * 6.28f * 2);   // 2 sways per cycle
  for (int i = 0; i < NUM_TAIL; i++) {
    featherAngle[i] = 90 + 25 * sin(phase * 6.28f * 2 + i * 0.5f);
  }
  setServoA(CH_BODY_SWAY, 90 + 18 * beat);
  setServoA(CH_BODY_BOB,  90 + 10 * abs(beat));
  setServoA(CH_SPREAD_L,  90 + 30 * (0.5f + 0.5f * sin(phase * 6.28f)));
  setServoA(CH_SPREAD_R,  90 - 30 * (0.5f + 0.5f * sin(phase * 6.28f)));
  setServoB(CH_NECK_PAN,  90 + 25 * beat);
  setLEDPattern(60, 0, 200);  // deep violet
}

// ═══════════════════════════════════════════════════════════════
//   PATTERN 7 — GREETING BOW                                    
// ═══════════════════════════════════════════════════════════════
void patternBow(float phase) {
  float bowT = easeInOut(sin(phase * 3.14f));
  for (int i = 0; i < NUM_TAIL; i++) {
    featherAngle[i] = lerpf(90, 90 + 40 * (i < 5 ? -1 : 1), phase > 0.5f ? (phase - 0.5f) * 2 : 0);
  }
  setServoB(CH_NECK_TILT, 90 - 30 * bowT);  // bow forward
  setServoB(CH_HEAD_TILT,  90 - 15 * bowT);
  setLEDPattern(200, 180, 0);  // gold bow
}

// ── Shared: blink and body update ────────────────────────────────
void updateEyesAndBody(float phase) {
  float f = phase * 6.28f;
  // Periodic eye blink (natural feel)
  bool blink = (sin(f * 0.4f) > 0.96f);
  setServoB(CH_EYE_L, blink ? 60 : 90);
  setServoB(CH_EYE_R, blink ? 60 : 90);
  // Gentle body elevation breathing
  setServoA(CH_TAIL_ELV, 85 + 5 * sin(f));
}

// ── LED stage colour ─────────────────────────────────────────────
void setLEDPattern(uint8_t r, uint8_t g, uint8_t b) {
  for (int i = 0; i < strip.numPixels(); i++) strip.setPixelColor(i, r, g, b);
  strip.show();
}

// ── Apply all feather angles ──────────────────────────────────────
void applyFeathers() {
  for (int i = 0; i < NUM_TAIL; i++) {
    currentAngle[i] = lerpf(currentAngle[i], featherAngle[i], 0.14f);  // smooth lag
    setServoA(i, currentAngle[i]);
  }
}

// ── SETUP ────────────────────────────────────────────────────────
void setup() {
  Serial.begin(115200);
  boardA.begin(); boardA.setOscillatorFrequency(27000000); boardA.setPWMFreq(50);
  boardB.begin(); boardB.setOscillatorFrequency(27000000); boardB.setPWMFreq(50);
  strip.begin(); strip.setBrightness(80); strip.show();

  // Startup: centre all servos
  for (int i = 0; i < 16; i++) { boardA.setPWM(i, 0, SERVOMID); delay(30); }
  for (int i = 0; i < 6;  i++) { boardB.setPWM(i, 0, SERVOMID); delay(30); }
  for (int i = 0; i < NUM_TAIL; i++) currentAngle[i] = 90;
  patternStart = millis();

  setLEDPattern(0, 150, 130);
  Serial.println("🦚 Peacock Robot Ready!");
}

// ── MAIN LOOP ────────────────────────────────────────────────────
void loop() {
  uint32_t now    = millis();
  uint32_t elapsed = now - patternStart;
  float    phase  = (float)(elapsed % PATTERN_DUR) / PATTERN_DUR;

  // Auto-advance patterns
  if (elapsed >= PATTERN_DUR) {
    currentPattern = (currentPattern + 1) % 8;
    patternStart   = now;
    Serial.print("Pattern: "); Serial.println(currentPattern);
  }

  // Dispatch current pattern
  switch (currentPattern) {
    case 0: patternRipple(phase);   break;
    case 1: patternSpiral(phase);   break;
    case 2: patternHeart(phase);    break;
    case 3: patternBloom(phase);    break;
    case 4: patternShimmer(phase);  break;
    case 5: patternCascade(phase);  break;
    case 6: patternDance(phase);    break;
    case 7: patternBow(phase);      break;
  }

  updateEyesAndBody(phase);
  applyFeathers();
  delay(20);  // 50 Hz update rate
}
The Dance Program

Full Performance Sequence

The robot automatically cycles through all 8 patterns in order, spending 12 seconds on each. A full performance takes about 96 seconds before looping. Here's what you'll see:

Time Pattern What the Audience Sees LED
0–12sRipple WaveFeathers undulate like water, neck sways in sync
12–24sSpiralFan appears to rotate like a galaxy arm
24–36sHeartFeather tips form a glowing heart shape
36–48sBloomFull fan opens like a flower blooming
48–60sShimmerHigh-frequency shimmer under cycling RGB lights
60–72sCascadeFeathers open one-by-one left to right, then close
72–84sDance SwayWhole robot dances — body, tail, neck all in rhythm
84–96sGreeting BowPeacock bows forward, fan springs open — then loops

⚠️ Safety Rules — This Is a High-Current Build

  • Adult supervision is mandatory for this project. The 5V 10A power supply can deliver enough current to cause a fire if wiring is incorrect.
  • Always use minimum 20 AWG wire for all power rails. Thin wire overheats at the currents drawn by 22 simultaneous servos.
  • Never leave the robot running unattended — servos that bind against mechanical stops draw continuous stall current and can overheat.
  • Add a 5A inline fuse between the PSU and the servo power bus — this prevents fire if a wiring fault draws excessive current.
  • The aluminium frame is a conductor — ensure no servo wires have bare metal touching the frame. Use heat shrink tubing on all solder joints.
  • Keep the natural feathers away from any heat source, LED strips that run hot, or enclosed spaces — peacock feathers can singe easily.
  • Perform a current test before first full activation: connect an ammeter inline and run each servo group one at a time to measure draw before running all 22 simultaneously.
  • Install the power switch in an easily accessible location so you can cut power immediately if any servo starts smoking or the frame gets hot.
Troubleshooting

When Things Don't Go Right

Some servos don't move or twitch randomly.

This is almost always a power issue. Add 1000µF capacitors directly across V+ and GND at each PCA9685 board. Also check that your 5V 10A PSU is actually delivering 5V under load — measure with a multimeter while all servos move.

The second PCA9685 board (0x41) isn't found.

Confirm the A0 solder bridge is made on Board B. Run an I²C scanner sketch to confirm both addresses appear. Check that SDA and SCL reach both boards — use a T-junction on the breadboard rather than daisy-chaining the wires.

Feathers tangle when the full fan opens.

First confirm all servo angles are within safe ranges (0° to 180° max). Add soft guides between alternate feathers — a strip of thin foam between each pair acts as a separator. The feathers should overlap slightly but not interlock.

Motion is jerky instead of smooth.

Check the interpolation smoothing value in applyFeathers() — increase the lerp factor from 0.14 toward 0.08 for slower smoother motion. Also ensure the main loop runs at a consistent 50ms delay — add timing logic to prevent drift.

The ESP32 resets when many servos move at once.

Servo current spikes are coupling into the ESP32's power supply through shared ground. Add the buck converter for isolated ESP32 power and ensure the servo power and logic power GND rails are joined at only ONE point (the PSU negative terminal).

My PATTERN_DUR is wrong — how do I adjust pattern speed?

Change the PATTERN_DUR constant — it's in milliseconds. 12000 = 12 seconds per pattern. The phase variable (0.0 to 1.0) always represents one complete cycle regardless of duration, so all patterns scale automatically.

Nature vs Robot

Peacock & Robotics Facts

200+

Feathers in a real peacock's train — your robot uses 10 main display feathers, which is enough to create the same visual impression.

140°

The spread angle of a full peacock tail fan — your robot achieves this with the two spread arm servos at channels A10 and A11.

50Hz

The update rate of your PCA9685 servo driver — the same frequency used in industry servo controllers for smooth motion.

2D → 3D

The iridescence of peacock feathers comes from nanostructures, not pigment — the colour changes with viewing angle, making every servo movement create a new colour display.

Future Builds

Next Level Upgrades

LEVEL 2

Sound-Reactive Display

Add a microphone module — the ripple wave frequency follows the BPM of music playing nearby.

LEVEL 2

Bluetooth Remote Control

Connect a phone via Bluetooth to manually trigger any pattern, adjust speed, and control the LED colours live.

LEVEL 3

Audience Interaction

Add a PIR motion sensor — when someone approaches, the peacock activates its greeting bow automatically.

LEVEL 3

Voice Command

Add a INMP441 microphone and wake-word detection: say "Peacock dance!" and the robot performs the full sequence.

LEVEL 4

AI Expression Engine

Train a simple neural network on audience facial expressions — the peacock responds more enthusiastically when the audience smiles.

LEVEL 4

Flock of Peacocks

Build a second peacock and synchronize them over ESP-NOW wireless protocol — a duet performance where both robots mirror each other.

You have just built one of the most complex and visually beautiful robots in this entire project series. You used trigonometry, interpolation, multi-board I²C communication, and real-time choreography — the same skills used by animatronic engineers at theme parks and film studios. The peacock dances because you made it dance. 🦚

DIY Peacock Robot with 22 Servo Motors — Advanced Animatronics STEM Project for Kids 🦚

Tags: peacock robot servo motors · ESP32 animatronic · PCA9685 servo driver · synchronized servos · ripple wave animation · STEM robotics · animatronic bird · natural feathers robot

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