FIELD MANUAL · § BUILD · V1 ROADMAP FM 18-DOF / V1 BUILD
★ PROJECT HEXAPOD ★ V1 BUILD ★ INTERNAL

Version 1.

12 DAYS · 22 TASKS · ESP32 + 18 SERVOS · USB SERIAL · WALK 1 m

● SAFETY FIRST

Before you touch the LiPo: fire blanket and CO₂/dry-powder extinguisher within arm's reach, pack in a LiPo bag during every charge, 30 A inline fuse on the positive lead, LVC buzzer on the balance plug, single ground reference between buck and ESP32. Do not skip these.

Goal: from a cold start, send F over USB serial and the robot walks 1 metre forward in under 30 seconds on a tripod gait without falling. S stops it. LiPo below 7.2 V auto-halts the system with a buzzer. That's V1. Everything else (vision, autonomy, personality, Telegram, Pi 5) is later.

01 · Build calendar (12 days)

DayPhaseWhat you ship that night
Day 0A · Pre-flightBench safe, BOM inventoried, ESP32 blinks + prints boot banner
Day 1B · Power harnessBuck output stable at 6.0 V under 5 A; LiPo charged + stored in bag
Day 2B · First PWMI²C scan finds 0x40 + 0x41; one servo sweeps on command
Day 3B · All servosAll 18 servos pass individual bench test; duds flagged
Day 4C · ServoBus + trimsServoBus.setAngle() works; per-servo trims captured
Day 5C · IKLeg IK math passes host unit tests
Day 6D · One legOne leg assembled, foot traces a 3D path correctly
Day 7D · Remaining legsAll 6 legs assembled and calibrated
Day 8D · IntegrationAll servos wired; robot stands on its own
Day 9E · In-air gaitTripod gait alternates correctly while suspended
Day 10E · First stepRobot takes one weight-bearing step on the floor
Day 11F · CLI + LVCF/B/L/R/S commands work; LVC trips at 7.2 V
Day 12F · ACCEPTANCE1-metre walk passes; e-stop verified live

02 · Phase A — Pre-flight (Day 0)

PHASE A · GET READY Day 0 · ~2 hours
T1BOM inventory + bench safety
Lay out every part. Tick against the project site BOM. Confirm tools (iron, multimeter, side-cutters, USB-micro cable, ESD mat). LiPo bag, fire blanket, extinguisher on the bench.
✓ acceptEverything physically present; safety kit on bench.
T2PlatformIO project scaffold
Install VS Code + PlatformIO. Connect ESP32, verify /dev/cu.usbserial-* appears. Create firmware/platformio.ini with the esp32dev and native environments and the Adafruit PWM Servo Driver lib. Add a 1 Hz blink to main.cpp with a boot banner.
✓ acceptGPIO 2 LED blinks at 1 Hz; serial shows HEXAPOD V1 / boot / hello at 115200.

03 · Phase B — Power + first PWM (Days 1–3)

PHASE B · ELECTRONS Days 1–3 · ~3 evenings
T3Build the power harness
Crimp XT60 to the LiPo lead (12 AWG silicone). Splice the 30 A blade fuse inline on the + lead. Wire LVC buzzer to the balance plug at 3.6 V/cell trip. Wire fused XT60 female to buck IN+/IN-. Confirm polarity with multimeter before LiPo plug-in.
⚠ lipoCharging stays in the LiPo bag, on a fire-safe surface, within sight. No exceptions.
✓ acceptNo exposed copper; continuity test clean; LVC sounds on a test trip.
T4LiPo storage charge + safety check
Measure cell voltages on balance plug — ~3.85 V each. If any cell <3.0 V or cells differ by >0.1 V, stop and inspect. Charge to full (4.2 V/cell) on IMAX B6, balance mode, 1 C = 3.3 A.
✓ acceptPack at 8.40 ± 0.05 V; cells within 0.02 V; stored in bag.
T5Buck converter calibration
Trim pot fully CCW. Plug LiPo, multimeter on OUT. Slowly turn pot CW until exactly 6.0 V. Lock pot with nail polish or paint pen. Apply a 5 A load and confirm sag < 200 mV.
✓ acceptBuck reads 6.00 V no-load, ≥ 5.8 V at 5 A; trim mechanically locked.
T6I²C scan finds 0x40 and 0x41
Wire ESP32 GPIO 21/22 to both PCA9685s' SDA/SCL. Solder the A0 jumper on the second board (sets it to 0x41). Run an I²C scan from main.cpp.
✓ accept0x40 and 0x41 both reported every scan cycle.
T7Drive one servo from the ESP32
Wire one MG996R to PCA9685 ch 0. Tie PCA9685 V+ to buck OUT+, GND to buck OUT-, and tie buck OUT- to ESP32 GND (single ground reference). Run the servo sweep sketch (0 → 90 → 180 → 90 every 3.6 s).
✓ acceptServo sweeps smoothly; no jitter at 90°; buck output stays ≥ 5.8 V during stall.
T8Bench-test all 18 servos
One at a time, swap each servo into ch 0 and run the sweep. Listen for grinding, dead spots, sticky centring. Label each S00–S17 with masking tape. Note duds in docs/servo-test-log.md.
✓ accept18 working servos labelled and laid out by leg group.

04 · Phase C — Servo abstraction + IK (Days 4–5)

PHASE C · CODE FOUNDATIONS Days 4–5 · ~2 evenings
T9Implement ServoBus
Create ServoBus.h/.cpp wrapping both PCA9685s. Single API: setAngle(idx 0..17, deg), center(idx), centerAll(), disableAll(). Reads per-servo trims from data/trims.h. (Full code in the markdown plan.)
✓ acceptSingle-channel sweep works through ServoBus; no other channel twitches.
T10Per-servo trim calibration
Jig each servo with a horn over a printed protractor. Run "centre all". Measure offset from true 90° for each of the 18. Update kServoTrim[] in data/trims.h. Re-verify.
✓ acceptAll 18 servos centre within ±1° on ServoBus.center().
T11Leg IK math + host unit tests
Create Leg.h/.cpp with 3-DOF planar IK (coxa rotation + femur/tibia 2-link planar). Native unit tests under test/test_leg_ik/. Run on host: pio test -e native.
✓ acceptpio test -e native reports 2/2 passing.

05 · Phase D — Mechanical build (Days 6–8)

PHASE D · BUILD THE BODY Days 6–8 · ~3 evenings
T12Parts + heat-set inserts
Print/source body + 6× leg sets in PETG (0.4 mm nozzle, 0.2 mm layer, 40% infill, 3 walls). Install M3 brass heat-set inserts at every screw boss with the soldering iron at ~200 °C.
✓ acceptAll inserts flush; no cracked prints; parts grouped by leg.
T13Assemble one leg + range check
Coxa → femur → tibia. M3 × 8 mm screws into inserts. Servo horns held with OEM short screws. Plug into PCA9685 ch 0/1/2. Command center(0..2); tune one tooth or update trim if neutral pose is off. IK demo: foot lands within 5 mm of commanded XYZ.
✓ acceptLeg holds neutral; IK places foot within 5 mm of target.
T14Remaining 5 legs
Repeat T13 five more times. Channel mapping: leg 0 → 0–2, leg 1 → 3–5, leg 2 → 6–8, leg 3 → 9–11, leg 4 → 12–14, leg 5 → 15–17 (last 2 channels on second PCA9685).
✓ acceptAll 6 legs hold symmetric neutral pose.
T15Mount legs + PCA9685s + wiring
Bolt each leg to body. Convention: leg 0 = right-front, then clockwise viewed from above. Mount angles 60°, 0°, -60°, -120°, 180°, 120°. Velcro both PCA9685s under the body. Short I²C trunk to ESP32. Chain V+ and GND with 14 AWG to the buck output rail.
✓ acceptTidy, labelled wiring; nothing crosses a moving joint.
T16First standing pose
In main.cpp, call bus.centerAll(), then idle. Power up with the robot in the air, then lower it onto a flat surface. Tune trims one last time if a leg looks off.
✓ acceptRobot stands on its own under centerAll().

06 · Phase E — Gait (Days 9–10)

PHASE E · MAKE IT WALK Days 9–10 · ~2 evenings
T17Body — IK-based neutral stance
Create Body.h/.cpp holding the 6 Leg objects with their mount angles. stand() commands every foot to neutral via IK. Hook into main.cpp.
✓ acceptStable, symmetric stance; weight evenly distributed.
T18Tripod gait — in-air verification
Fill in Body::tick() with the tripod state machine: legs 0/2/4 alternate with 1/3/5; swing legs lift 20 mm, push legs sweep ±30 mm. Hard-code Forward in setup(). Hold the robot in the air and verify the alternation visually.
✓ acceptCorrect tripod alternation in mid-air; no leg jams.
T19First weight-bearing step
Place robot on a non-slippery surface (rug or rubber mat, not tile). Power on with Forward hard-coded. Should take 1+ tripod steps. Tune: drop kStrideMm 30 → 20 if it slips; drop kLiftMm 20 → 12 if it tips.
✓ acceptRobot advances ≥ 100 mm without falling (within 2 tuning iterations).

07 · Phase F — Control + safety (Days 11–12)

PHASE F · SHIP IT Days 11–12 · ~2 evenings
T20Serial CLI parser
Create Cli.h/.cpp: reads single characters from Serial, dispatches F/B/L/R to Body::setCommand() and S/\n/\r to Stop. Plug into loop().
✓ acceptAll five commands work; robot responds within one gait phase (~400 ms).
T21LVC monitor + e-stop
Wire a 22 kΩ / 10 kΩ divider from the LiPo + rail to ESP32 GPIO 34. Create Power.h/.cpp: reads the divider, returns isLow() at < 7.2 V. In loop(), on low: stop, disableAll(), print LVC!, halt forever.
⚠ verifyWith a bench supply, sweep 8.0 V → 7.0 V slowly. ESP32 should trip between 7.15 and 7.25 V.
✓ acceptE-stop trips in the LVC window; all servos go limp; system halts until reboot.

T22 · ACCEPTANCE — 1-metre walk

Charge LiPo to full. Robot in the centre of a 1.2 m clear lane. Connect USB; open serial monitor. Start a stopwatch. Send F. When the front of the robot crosses the 1 m mark, send S. Note elapsed time. V1 passes if:
  • Robot walked ≥ 1 m
  • Elapsed time < 30 s
  • Robot did not fall
  • S halted it within one gait phase
  • LiPo still above 7.5 V at the end

All five pass → V1 is done. Commit firmware, take the hero shot, tick off Phase 1 in the companion site, and start dreaming about the Pi 5 brain.

08 · What V1 explicitly does NOT include

Held back to keep the build shippable in 12 days. All of these belong to V2 and beyond: Bluetooth / WiFi gamepad control · FPV camera · obstacle avoidance · IMU stabilization · autonomous patrol · personality / mood state · Telegram messaging · LLM agent loop · Pi 5 brain · charging dock. The architecture is set up to absorb all of them without rebuilding V1 — the ESP32 stays as the spinal cord, a Pi 5 will join later as the brain.

NEXT MOVE

Tonight is Day 0 · Task 1. Lay out the BOM, photograph it, set up the bench, and confirm the safety kit is in arm's reach.

The complete plan with full code for every firmware task is in docs/superpowers/plans/2026-05-17-hexapod-v1-walking-build.md. This HTML is the readable map; the markdown is the workshop manual you keep open in another tab while you build.