Skip to content
Open-source hexapod robot

Build the Hexapod Macaroon

A complete four-phase guide — from 3D printing through electronics, firmware, and calibration. Powered by stronger 25kg servos.

The finished Hexapod Macaroon — the largest of the 3D-printed hexapod family
⚠ Critical: Do NOT tighten servo horn screws during assembly. Leave them loose — you’ll tighten them properly during calibration after setting each servo to its neutral position.

What you’ll build

Degrees of freedom18 (6 legs × 3)
Build time8–12 hours
Skill levelBeginner–Intermediate
ToolsHex key set, small screwdriver
ℹ No soldering required with the pre-assembled Macaroon controller board ↗ — the servos, switch and battery holder plug straight in. You only need a soldering iron and wire strippers if you build your own wiring harness.

Specifications

Degrees of freedom18 — 6 legs × 3 joints (coxa, femur, tibia)
Actuators18 × 25 kg digital servos, 180° travel, 8.4 V capable
ControllerESP32 with dual PCA9685 PWM drivers (I²C 0x40 / 0x41)
Power4 × 18650 Li-ion in 2S2P — 7.4 V nominal, 8.4 V fully charged
Connectivity2.4 GHz WiFi access point — the robot hosts its own network
ControlBinary UDP protocol on 192.168.4.1:1234, plus a web UI on http://192.168.4.1
Real-time streamingAll 18 joints at 50 Hz, with per-joint slew limiting and a 1 s failsafe
Firmware updatesUSB or over-the-air (OTA) over WiFi
Resolution~0.44° per servo tick (410 ticks over 180°)

Safety notes

  • Check battery polarity twice before the first power-up — reversed polarity will destroy the controller board
  • Keep fingers clear of the joints when powered. Eighteen 25 kg servos have enough torque to pinch hard
  • Support the robot on first power-on. It runs its stand-up sequence automatically as soon as a client joins its WiFi, so hold it or stand it on a box with the legs free
  • Treat the Li-ion pack with respect — protected cells only, a proper 2S charger, and never charge unattended
  • If a leg moves somewhere unexpected, cut power with the toggle switch rather than trying to hold the leg back

Print settings

Layer height0.2 mm
Infill20–30%
MaterialPLA / PETG — TPU for foot tips
SupportsSome parts
ℹ All STL files — plus ready-to-print Bambu Studio projects (bambu_studio_*.3mf) — are a free download ↗. Check each STL’s orientation for supports, and print one leg’s worth of parts first to test-fit before committing to all six.

Body components — ×1 set

ℹ Install servos before closing the body. Route wires neatly to avoid pinching. Test-fit all parts before final assembly.
body_basebody_base×1
body_sidebody_side×6
body_topbody_top×1
body_headbody_head×1
body_batterybody_battery×1
body_servo_sidebody_servo_side×12
fencefence Optional×1

Joint components — 3 standard + 3 mirrored

⚠ Left side legs use mirrored joints. Right side legs use standard joints. Refer to assembled robot images for correct orientations.
joint_bottomjoint_bottom×12
joint_crossjoint_cross×6
joint_topjoint_top×12

Leg components — ×6

ℹ Ensure bearings are properly seated. Pins should slide in smoothly without forcing. Verify smooth joint rotation before proceeding.
leg_bottomleg_bottom×6
leg_sideleg_side×12
leg_topleg_top×6

Foot components — 3 standard + 3 mirrored

⚠ Match foot orientation with joint — left = mirrored, right = standard.
foot_bottomfoot_bottom×6
foot_topfoot_top×6
foot_groundfoot_ground×6
foot_tipfoot_tip TPU×6

Hardware

ℹ Organize all hardware into labeled containers before assembly. Standard metric parts — available from Amazon, AliExpress, or local hardware stores.
ItemSpecQtyUse
ScrewM2 × 6mm hex socket36Servo mounting
ScrewM2 × 12mm countersunk180General assembly
NutM2 hex nut216Securing screws
PinM4 × 6mm stainless steel (304)18Joint pivots
BearingMR74-2RS — 4mm ID, 7mm OD, 2.5mm bore18Smooth joint rotation

Assembly order

1
Install servos in body before closing it — route wires neatly to avoid pinching
Body Assembly
2
Assemble joints: bottom → cross → top. Pay close attention to left vs right orientation
Joint Assembly
3
Build each leg — seat bearings, insert pins (should slide smoothly without forcing)
Leg Assembly
4
Attach feet — verify orientation matches the joint (standard or mirrored)
Foot Assembly
5
Attach all 6 completed legs to the body
Whole Assembly
6
Connect servos and controller — then proceed to Electronics and Software before final tightening

Components

ImageComponentSpecQtyNote
ControllerController boardMacaroon ESP32 board — servos driven directly by the batteries1Purchase ↗
ServoServo25kg — 180° rotation, must support 8.4V supply18Same batch
SwitchToggle switchSPST, 12mm diameter1Available with the controller board ↗
Battery18650 battery3.7V Li-ion, 2000mAh+4Protected cells only
Battery HolderBattery holder4-cell (2S2P) with wire leads1Printable holder ↗, or with the controller board ↗
⚠ Use protected 18650 batteries. Unprotected cells can be hazardous — the protection circuit guards against overcharge, over-discharge, and short circuits.

Wiring

1
Connect each 25kg servo to the numbered ports on the controller board — 18 servos total (3 per leg)
2
Install the toggle switch for main power
3
Connect the 4-cell (2S2P) 18650 battery holder to the board’s power input (7.4V nominal)
4
Refer to the wiring diagram below for exact pin assignments
Wiring diagram — servo and power connectionsWiring diagram — board detail
ℹ The custom controller board simplifies wiring significantly — all servo connectors and power management are built in. Available from the RookiDroid shop.

Dependencies

LibraryHow to install
arduino-esp32Add board support URL in Arduino IDE → Boards Manager
Adafruit PWM Servo DriverArduino IDE → Library Manager → search and install
AsyncUDP, ArduinoOTA, EEPROM, WebServerIncluded with arduino-esp32 — nothing extra to install

Upload steps

1
Install Arduino IDE (2.x recommended) from arduino.cc ↗
2
Install arduino-esp32 board support following the Espressif instructions ↗, or add https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json to Preferences → Additional Board Manager URLs
3
Install Adafruit PWM Servo Driver through Arduino Library Manager
4
Download the firmware from Hexapod Arduino ESP32 ↗ and open hexapod_esp32.ino
5
Select board ESP32 Dev Module — Upload Speed 115200, Flash Frequency 80MHz, Partition Scheme Default 4MB with spiffs
6
Select the COM port and upload. Open Serial Monitor at 115200 baud to see the AP address — the robot stands up when a client connects to its WiFi

Default WiFi config

SSID
hexapod_macaroon
Password
hexapod_1234
UDP port
1234
AP address
192.168.4.1
ℹ Change the credentials in config.h (APSSID / APPSK). The hexapod creates its own 2.4 GHz access point — connect to it directly rather than looking for it on your router.

Source files

📄
hexapod_esp32.ino — main sketch with setup() / loop() and shared system state
📄
motion_control.ino — PWM drivers and motion look-up table playback
📄
realtime.ino — real-time pose streaming and its slew limiter
📄
network.ino — WiFi AP, OTA, UDP endpoint and packet parsing
📄
calibration.ino — servo offsets loaded from / saved to EEPROM
📄
web_ui.ino / web_page.h — web calibration interface
📄
hexapod.h / protocol.h — shared state and UDP packet layouts
📄
config.h — WiFi credentials, servo pin mappings, and hardware settings
📄
motion.h — pre-generated motion look-up tables for smooth walking
📄
README.md ↗ — ESP32-specific documentation, including the full UDP command reference

Regenerating the motion tables

ℹ The gaits shipped in motion.h are generated, not hand-written — they come from the path tool ↗, a Python inverse-kinematics generator.
1
Install Python with numpy and Jupyter, then open lut_generator.ipynb from the path_tool folder
2
Adjust the parameters (or add a generator in path_tool.py) and run all cells — the last cell writes a new motion.h next to the notebook
3
Copy that motion.h into software/hexapod_esp32/ and re-upload the firmware
4
A brand-new table also needs an entry in motion_config[] in motion_control.ino — see Adding Custom Motions ↗
⚠ If you change the frame or leg dimensions, update config.json first — every look-up table is derived from it.

Control protocol

ℹ The robot listens on UDP port 1234. Three binary packet types share that port — the first byte selects the protocol, so the firmware dispatches on the magic number before it checks the length. All packets are little-endian and unpadded.
MagicPacketSizePurpose
0xA5Motion command6 BPlay one of the built-in gait look-up tables
0xA6Real-time pose44 BStream raw servo positions for all 18 joints
0xA7Session control6 BEnter/leave real-time mode, relax, keep-alive

Motion commands — 0xA5

ℹ Byte 0 is the magic number, byte 1 the command ID, and bytes 2–5 a 32-bit sequence number.
IDActionLegacy text command
0Stop and hold positionstandby
1Walk forwardwalk0
2Walk backwardwalk180
3Walk right at 45°walkr45
4Walk right at 90°walkr90
5Walk right at 135°walkr135
6Walk left at 45°walkl45
7Walk left at 90°walkl90
8Walk left at 135°walkl135
9Fast walk forwardfastforward
10Fast walk backwardfastbackward
11Turn left in placeturnleft
12Turn right in placeturnright
13Climbing gait forwardclimbforward
14Climbing gait backwardclimbbackward
15Body rotation — pitchrotatex
16Body rotation — rollrotatey
17Body rotation — yawrotatez
18Body twist motiontwist

Session control — 0xA7

ActionNameEffect
0ExitLeave real-time mode, resume look-up table playback from standby
1EnterEnter real-time mode, holding the standby posture
2RelaxDisable both PWM drivers so the servos go limp
3PingKeep-alive; resets the failsafe timer
✦ Real-time pose streaming (0xA6). A 44-byte packet carries raw servo ticks for all 18 joints, bypassing the motion look-up tables — receiving one implicitly enters real-time mode, and each joint slews toward its target by at most max_step ticks per 20 ms cycle. If no packet arrives for 1 second the robot eases back to standby and returns to look-up table control, so send a ping while idle. Sending a motion command (0xA5) also leaves real-time mode, so the two control styles cannot fight over the servos. Hexapod Link ↗ is a desktop app that uses this to drive the robot live.
ℹ Prefer not to build packets yourself? Use the Android app ↗. The firmware also still falls back to plain text commands (the legacy column above) when a packet matches none of the binary layouts — handy for testing from a terminal, but new clients should use the binary protocol. Full field layouts are in the UDP command reference ↗.
✦ OTA updates supported. Connect to the hexapod WiFi network, pick the robot under Arduino IDE → Tools → Port → Network Ports, and upload without USB. OTA is disabled once the robot enters real-time mode or receives a legacy text command — binary motion commands (0xA5) leave it enabled. Reboot the robot to re-enable it.

Troubleshooting

  • Upload fails: use a data-capable USB cable, try another port, confirm board and port, and hold BOOT during upload if needed
  • Servos not responding: check battery voltage (7.4V nominal), servo connections, PCA9685 addresses (0x40 left, 0x41 right) and enable pins (GPIO 19 left, GPIO 26 right). Confirm the servo pin mappings in config.h match your wiring, and test individual servos with posture_calibration()
  • WiFi issues: the hexapod creates an access point — connect to it directly instead of looking for it on your router. Verify SSID/password in config.h and make sure your device supports 2.4 GHz; the IP is always 192.168.4.1
  • OTA not working: real-time mode and legacy text commands turn OTA off — reboot before uploading, stay connected to the hexapod AP, and check your computer’s firewall
✦ The ESP32 firmware includes a web-based calibration interface — no need to edit code or re-upload firmware. All adjustments happen live through your browser.

Target neutral positions (all servos at 90°)

Left legs 1, 2, 3
Joint 1 — Coxa (hip)⊥ body
Joint 2 — Femur (thigh)horizontal
Joint 3 — Tibia (shin)90° to femur
Right legs 1, 2, 3
Joint 1 — Coxa (hip)⊥ body
Joint 2 — Femur (thigh)horizontal
Joint 3 — Tibia (shin)90° to femur
Calibration reference — front view Calibration reference — top view

Calibration procedure

1
Flash firmware with default offsets, insert batteries, turn on power switch
2
Connect your device to the hexapod_macaroon WiFi network (password: hexapod_1234)
3
Open a browser and navigate to http://192.168.4.1
4
Click “Enter Calibration Mode” — motion stops, current offsets load, and a grid of all 18 servos appears (6 legs × 3 joints)
Calibration Web Interface
5
For each misaligned servo, use +/− buttons (1 tick ≈ 0.44°) or type a value — changes apply immediately
6
Compare each leg against the reference images: coxa ⊥ body, femur horizontal, tibia at 90° to femur
7
Click “Save Offsets” — values are written to EEPROM and survive power cycles. Also printed to Serial Monitor as backup
8
Now tighten servo horn screws — with each servo in its correct neutral position, firmly tighten all horn screws
9
Click “Exit Calibration Mode” and send a walk command to verify smooth motion

Tips for good calibration

  • Calibrate one leg completely before moving to the next
  • Use +/− buttons for fine control — avoid jumping to large values
  • If offsets exceed ±25 ticks, physically reposition the servo horn instead of relying on software offset
  • Loose servo horns throw off calibration — make sure the horn is seated firmly on the spline before adjusting
  • Servos respond immediately as you adjust, so you get real-time visual feedback
  • Save your offsets — values persist in EEPROM but always note them from Serial Monitor as backup
  • Re-enter calibration mode any time to fine-tune if walking looks uneven