Files
hexapod-robot/2026-current/remote/README.md
T
mangavalkandClaude Opus 5.5 91dac16fca Draft: shared protocol, remote firmware, project docs
Not yet verified on hardware.

- shared/HexapodProtocol: CmdPacket (now 20 bytes, adds remote_roll /
  remote_pitch), FLAG_* bits and radio settings as the single protocol
  definition; static payload size = sizeof(CmdPacket) on both radios.
- robot: use the shared protocol; vx = forward (harness w/x <-> q/e);
  InputMapper adds remote tilt on top of the right stick when
  FLAG_REMOTE_GYRO is set, and robot.ino no longer zeroes stick
  roll/pitch when it's off.
- remote (Teensy 4.1): Sticks (calibration, EEPROM), RemoteIMU,
  RemoteState (interlocks, link-loss disarm, smoothing), PacketBuilder,
  RadioLink, NextionUI, SerialConsole.
- CLAUDE.md, README.md, remote/README.md, remote/NEXTION.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 18:14:00 +02:00

5.1 KiB
Raw Blame History

Hexapod remote firmware (Teensy 4.1)

Handheld transmitter for the hexapod. It reads two 3-axis twist-grip joysticks and an MPU6050, takes operator commands from a Nextion touchscreen, and sends a CmdPacket (defined in ../shared/HexapodProtocol/HexapodProtocol.h) to the robot over nRF24L01 at 100 Hz.

Building

From the repo root: pio run -e remote, flash with pio run -e remote -t upload, monitor with pio device monitor -e remote.

Wiring (placeholders; edit Config.h to match)

Part Signal Teensy 4.1 pin
nRF24L01 MOSI / MISO / SCK 11 / 12 / 13 (SPI0)
nRF24L01 CE / CSN 9 / 10
nRF24L01 VCC 3.3 V, with a 10–100 µF cap right at the module
MPU6050 SDA / SCL 18 / 19 (Wire)
Nextion TX → RX2, RX ← TX2 7 / 8 (Serial2), 5 V supply
Left stick X / Y / twist A0 / A1 / A2
Right stick X / Y / twist A3 / A6 / A7

Stick pots are wired 3.3 V – wiper – GND. Never feed 5 V into a Teensy 4.x analog pin.

Control scheme

Input Packet field Meaning on the robot
Left stick forward/back vx walk forward/back
Left stick left/right vy strafe (mode A); heading target direction (mode B)
Left stick twist yaw_rate turn rate (mode A only; ignored in mode B)
Right stick, ROTATE (default) rx/ry/rz body roll / pitch / yaw
Right stick, MOVE (FLAG_RSTICK_XLATE) rx/ry/rz body X / Y / Z (height, via twist) offset
Handset tilt remote_roll/pitch extra body roll/pitch while REMOTE GYRO is on

Touchscreen: ARM / DISARM, SIT/STAND, TRIPOD/WAVE, DIRECT/HEADING, R: ROTATE/MOVE, REMOTE GYRO, ROBOT GYRO, speed slider, LEVEL (re-zero the handset tilt), CAL / CANCEL CAL. NEXTION.md has the HMI build guide.

Safety interlocks (in RemoteState)

  • Arming is refused unless every stick axis is centered, and never allowed during calibration.
  • Disarming always clears the stand request. The robot arms into SIT, so re-arming never stands it up by itself.
  • Link loss: if no ack arrives for LINK_LOST_MS (300 ms, matching the robot's failsafe), the remote disarms itself. When the link comes back the robot stays down until you re-arm deliberately.
  • Sit/stand requests are only accepted while armed. FLAG_WALK is only sent while standing is requested.
  • While disarmed or calibrating, all motion fields are sent as zero.

Smoothing

  • Speed scale ramps toward the slider at SPEED_SCALE_RATE_PER_SEC. The robot uses speed scale directly on the walking twist, so a slider jump would otherwise be a velocity step.
  • Remote tilt fades in/out over ~0.5 s when REMOTE GYRO is toggled, and the handset re-zeroes its "level" at the moment you enable it.
  • FLAG_WALK lingers 250 ms after the left stick centers, so hovering at the deadzone edge doesn't make the robot chatter between STAND and WALKING.
  • Body pose smoothing is left to the robot's BodyPose rate limiters.

Stick calibration

  1. Power on with both sticks released and the remote held still. Each axis's resting center is captured automatically.
  2. For full calibration, disarm, then tap CAL (or press c on the serial console). Move every axis of both sticks to both limits, release them, and tap SAVE CAL (c). The result is saved to EEPROM.
  3. If any axis moved less than CAL_MIN_HALF_SPAN either side of center, the save is refused and you stay in calibration mode. CANCEL CAL (x) aborts.
  4. p prints the calibration in a form you can paste into Config.h defaults. R wipes EEPROM back to the Config.h defaults.

Serial console (USB, 115200, single keystrokes)

Every touchscreen control is available here, so you can bench-test with no display attached.

Key Action Key Action
a toggle arm k disarm
s toggle sit/stand g tripod ↔ wave
m direct ↔ heading-hold t right stick rotate ↔ translate
r remote gyro on/off b robot gyro on/off
+ / - speed ±25 z zero handset level
c start / save calibration x cancel calibration
p print status (raw + mapped sticks, IMU, link, state, cal) d toggle 10 Hz packet dump
R reset stick cal to Config defaults

Bench-check checklist

  1. Stick directions: with p, confirm each logical axis reads positive for right / forward / counterclockwise twist. Flip it in STICK_INVERT[] if not.
  2. IMU mounting: with p, dip the right edge down to get +roll, and tip the far edge down to get +pitch. If not, fix IMU_AXIS_FROM_CHIP / IMU_AXIS_SIGN.
  3. Nextion baud: bauds=115200 must be in Program.s, or the display shows nothing useful.
  4. Radio: with the robot powered, tLink / p should show ~100%. If it reads NO LINK, check that both boards were built from the same HexapodProtocol.h. The static payload size is part of the handshake.
  5. End to end with the robot on a stand: use d to dump packets and confirm each field changes the way the table above says.