Skip to content

README.md

Machine-translated by Robotheca from the original in Chinese (opens in a new tab). License: GPL-3.0-only (opens in a new tab).

Hexapod Robot

Hexapod robot based on Raspberry Pi Pico (RP2040). 18-channel digital servos (2× PCA9685), BNO055 IMU auto-leveling, supports ELRS CRSF / PS2 controller / USB three input methods.

Features

  • Control loop (default 100 Hz, runtime adjustable 50–200 Hz) + real-time IK solving; four gaits (triangle 6/8, ripple, wave) + biomimetic continuous variable speed
  • Balance mode (direct body posture control) + IMU attitude compensation auto-leveling (optional)
  • Dual-drive CRSF / PS2 pre-compiled, !MODE runtime switch without soldering or plugging; both drives share the same channel and parameter set (stick/button mappings in firmware are converted to the same channel numbers), remote page displays protocol raw values in real time at 5 Hz (CRSF 16 channels 172–1811 / PS2 four sticks 0–255 + 16 buttons)
  • Betaflight-style “Modes” page: which channel and which switch positions are assigned to unlock/balance/gait/stand-up posture (mode matrix), and which key combinations trigger one-shot actions (channels CH5–CH16), all runtime parameters saved by !CFGW; each line can be set to “single-click trigger” (flip on one flick) or “hold to activate,” the same config works for both transmitters and gamepads — factory unlock uses level semantics (switch flicked away locks), ticking “single-click trigger” turns it back into flip-on-flick
  • Kinematics geometry (leg segment lengths/stand height/servo zero position/install angle/body-to-foot offset) are runtime parameters, adjustable on the web “Geometry” page and applied at power-up
  • Battery protection (over-voltage/under-voltage/auto-cut servo power on deep discharge), hardware watchdog, I²C bus auto-recovery
  • Non-volatile storage: calibration parameters (18× horn_offset + PWM period) stored in flash, power-down safe; event log ring buffer (BOOT/battery/calibration), commands !SAVE / !LOG / !LOGC
  • Runtime parameters: 92 items (gait travel/thresholds/switches/direction flips/IMU feel/channel mapping/mode matrix & key combos/geometry/control period/peripheral ownership & baud rates/pin assignments) adjustable via web or serial console, commands !CFG / !CFGR / !CFGW; changes take effect immediately (geometry exceptions: take effect after reboot), !CFGW saves to flash
  • Onboard reserved interfaces controllable at runtime: DC motor ×2 (speed only, no direction pin) / buzzer / dual LED / external UART0 (GP0/GP1) / external I²C or ADC (GP26/27) / PCA9685 free 14-channel PWM; controlled via serial commands or the web “Peripherals” page (wiring not yet populated, see STATUS.md)
  • Betaflight-style “Ports” page: one line per pin group to select function — shared pins (UART0 / input UART1 / motor GP2-3 / foot-end detect GP16-21 / external header GP26-27) change function via dropdown and write parameters; GP23/24/29 are not brought out on the board (Pico module internal pins tied to SMPS mode / VBUS detect / VSYS detect), page still lets you set input/output and use !GPO for level, but treat as debug only; fixed pins are read-only. Status column reports the pin’s real-time measured level (!PORTS polling), useful when parameters and hardware don’t match
  • TCP/IP remote access: serial console built-in TCP bridge (multi-client broadcast + reverse command injection), headless operation supported; pair with tools/tcp_monitor.py for remote control
  • PCB design, Gerbers, full BOM, and mechanical STEP files all open-source (see hardware/)

Quick Start

cd pico/build && make -j$(nproc)

Drag the compiled output hexapod_pico.uf2 into Pico’s USB drive to flash it; on Linux, no button is required: picotool load -f -x build/hexapod_pico.uf2 (running firmware will be soft-reset into BOOTSEL mode). Debug console: python3 tools/serial_console.py (auto-connects and reconnects on disconnection). Web configuration panel (one page, two ways to open):

Direct connection — board plugged into your own computer, zero install: open in Chrome/Edge/Opera https://gitcfyang.github.io/hexapod_robot/ (opens in a new tab) → click “Connect” → browser pops up a serial-port selector; choose Pico. The page talks directly to the USB serial port (Web Serial), no local server, nothing to download. Parameters/ports/calibration/logs all travel this same path; after pushing changes to main, Pages auto-deploys (takes ~10 min; first time go to Settings → Pages and set Source to GitHub Actions once). Alternative: double-click the local index.html — same page, same features, no waiting for a deploy and no internet required, just grab the file yourself (Chrome treats file:// as a secure context, serial port still works). Safari is unsupported; Firefox needs 151+. If the browser refuses to pop the serial selector, switch to the “Local Server” method below. ⚠️ Firmware flashing is not available in direct connection — drag the UF2 file into Pico’s USB drive as usual.

Local server — board plugged into another machine, or you need to flash firmware: python3 tools/webconfig/run.py start → open browser to 127.0.0.1:8080 (same script also provides stop/restart/status/logs; restart = stop old process then start new; it only serves the HTTP endpoint, does not touch the serial bridge. On Linux the wrapper tools/webconfig/run.sh start runs it; you can also run python3 tools/webconfig/server.py directly without the script. Cross-platform is run.py (works on Windows/WSL too), but the serial bridge serial_console.py itself is Linux-only; Windows is best used only as the browser side, forwarding the port via VSCode to connect. When opened you first see the start page: only shows whether the hardware is online and what firmware the robot is running, plus one-click firmware flashing; after the device is detected, click “Connect” to enter the debug page — status: real-time voltage/I2C/IMU/servo angles · parameters grouped by function (gait/posture/geometry/RC/mode/power/balance/control/peripherals/ports): sliders write to flash · geometry: leg length/stand height/servo neutral/tilt angle/offset (takes effect after reboot) · RC: input-source switch + real-time channel display · mode: unlock/gait/pose mode matrix + combo keys + single-click triggers + real-time status badge · control: servo power switch + walk/turn/gait/lift buttons + PWM period sliders for the two PCA9685s · peripherals: motor/LED/buzzer/external UART/external I2C+ADC/idle PWM control board · ports: function selector for each pin pair (multiplex pins change purpose, GP23/24/29 switch input/output and set level, fixed pins are read-only), plus live pin level readout · calibration: center each servo mechanically (select cell → slider to neutral → set center), then servo sweep/save/bus scan + voltage calibration (enter multimeter reading → voltage-divider ratio) + IMU calibration (shows calibration level / reset to re-calibrate) · logs: serial log + command input; unplugging USB, bridge disconnecting, or clicking “Disconnect” returns to the start page; details in STATUS.md). Before connecting you can tick “Allow RC control during debugging” — unchecked (default) means the RC only reports channel values during debugging while the robot obeys web commands only; the robot will hand control back to the RC after 6 s of lost heartbeat (web page crash won’t lock it up). Remote access: the console automatically opens a TCP bridge (127.0.0.1:7100); open another terminal python3 tools/tcp_monitor.py to send/receive commands remotely (multiple sessions possible). Letting someone else use the web UI: if the board is in their hands, just have them open the Pages direct-connect page (you don’t need to do anything). If the board is plugged into your machine and you want others to see it, use the local-server setup — the server listens on 127.0.0.1 by default (localhost only); to let other computers connect, start the server with the listen address — same LAN run.py start --host 0.0.0.0, any device opens http://<这台机器的IP>:8080; across networks without exposing a public endpoint, use Tailscale (already running on the host) run.py start --host <tailnet IP>, then devices on the same network open http://100.x.y.z:8080; traffic never goes through routers whose two NICs are both down. ⚠️ This service has no authentication: anyone who can reach the web page can unlock, drive all 18 servos, and flash firmware. Therefore, if you expose a “any browser can open” public tunnel, either keep it closed or add auth first (TODO, see STATUS). (The direct-connection path avoids this issue: although the page may be on the public web, only the person who physically plugs the board into their own computer and manually selects the serial port in the browser popup can operate it — commands never pass through any server.) Keep the serial bridge (7100) listening only on localhost; do not open it to the network.

Hardware Overview

  • MCU: Pico (RP2040) · Servos: 18× dual-axis digital servos, 2× PCA9685 · IMU: BNO055 (I²C 0x29)
  • Battery: 2S 18650, GP28 ADC2 voltage divider 47/377 (330k+47k), automatic low-voltage/over-voltage/discharge protection (dual AO4407A) (batt_check parameter defaults to 0; will be enabled after new board testing and voltage divider calibration; divider ratio can be recalibrated on the web calibration page using multimeter readings)
  • 6× micro-switches at foot ends · passive buzzer · dual LEDs · 2× DC motors (speed control)
  • Unused pins: external UART0 (GP0/GP1) · external I²C or ADC (GP26/27) · 14 free PWM channels on PCA9685 (channel numbers do not overlap with servo channels; can output alongside servos)
  • Complete GPIO layout and battery protection behavior: see STATUS.md Hardware section

Frame

The frame of this project uses 18× dual-axis servos (STEP model available in hardware/mechanical/). A low-cost alternative is the 3D-printed solution from MakeYourPet/hexapod (opens in a new tab) (MIT, MG996R single-axis servos): to port this firmware, only the leg segment lengths, servo neutral positions, and mounting angles (geometric parameters) need to be adjusted (via the "Geometry" page in the web interface or !CFG, effective after reboot; see STATUS.md for details). No changes to the IK or gait algorithms are required (both use 3-joint legs).

Control

ModeCH1CH2CH3CH4CH5~CH8
NormalLeft/Right TranslationForward/BackwardBody HeightIn-Place RotationUnlock / Gait / Stand Pose / Balance Mode
BalanceRollPitchBody HeightYawSame as Above

CH1~CH8 in the table are default mappings, all of which can be changed on the web page ("Remote" page for stick channels, "Mode" page for switches): stick channels are filled with 0~19 (!CFG ch_fwd <0-19>), and switches are in the mode matrix of "channel + low/mid/high gear". This setup is shared by both remote controllers and gamepads — the sticks and buttons of the gamepad are first converted to the same set of channel numbers, then go through the same mapping. Changes take effect immediately and are saved by !CFGW even after power-off.

Each row can also be checked for "Single-Click Trigger": unchecked = only effective when staying within the activation range (unlocking is factory-set this way), checked = action once when entering the range (unlock/balance flip, gait/stand pose selection once). One-time actions for the gamepad (gait/stand pose switching, leg lifting, emergency stop) are in the "Combination Keys" table on the "Mode" page, while remote controller buttons correspond to channels CH5~CH16. Factory default direction inversion is all 0; if a direction feels reversed, flip the "Direction Inversion" on the "Remote" page (e.g., !CFG inv_str 1), do not change the channel number.

The input source is determined by the parameter input_mode (!MODE crsf|ps2 or web button switch, saved by !CFGW even after power-off), while INPUT_CONTROL_MODE is only the factory default. For the complete PS2 key mapping, see STATUS.md.

Structure

hexapod_robot/
├── pico/        # RP2040 firmware (HAL structure: Inc/Src)
├── tools/       # Serial console serial_console.py (+ TCP bridge) · IK simulation ik_gait_debug.py
│              # webconfig/ web configuration tool · tcp_monitor.py remote client · no-hardware testing
├── hardware/    # PCB design/mechanical/BOM (see hardware/README.md)
├── README.md
└── STATUS.md    # Firmware details: GPIO/parameters/gait/debug/circuit protection

Status

⚠️ The project is still under active development, and features and interfaces may change at any time.

License

Firmware: GNU GPLv3 (see LICENSE). Hardware documentation licensing is specified separately (see hardware/README.md).

Files by @gitcfyang, at commit 496f54f, read from GitHub in your browser. Hardware license: GPL-3.0-only; software license: GPL-3.0-only. Robotheca doesn't review code: read it before running it.