Project log

Arcade Remote

Updated October 4, 2026
Arcade Remote icon

The Arcade Remote turns real arcade hardware into a WiFi controller for robots: a microswitch joystick, five snap-in arcade buttons, and an ESP32-C6, all in a 3D-printed cabinet that fits in your hands. It drives every RookiDroid hexapod, and any other robot that speaks the same UDP protocol.

Arcade Remote from above: a blue ball-top joystick on the left, a cluster of red, yellow, white and blue buttons on the right, and a black special button, on a black panel over a red cabinet
Top panel · joystick, direction cluster, special button
Back of the red Arcade Remote cabinet with its magnetic cover removed, showing the 9 V battery in its bay
Back · magnetic battery bay with a 9 V battery
9microswitches
5 msinput scan
20 Hzheartbeat to the robot
5speed levels

Overview

An arcade stick for a six-legged robot

Each RookiDroid hexapod (Nougat, Mochi and Macaroon) hosts its own WiFi access point and listens for UDP commands. The Arcade Remote joins that access point directly, with no router in between, and sends the robot one command at a time, built from whatever the joystick and buttons are doing. Switching robots means changing a single line in the sketch.

  • Real arcade feel: a microswitch joystick and five snap-in arcade buttons. No analog sticks and no deadzone.
  • All-digital inputs: nine switches on INPUT_PULLUP GPIOs, scanned every 5 ms. A command has to hold for 30 ms before it is sent, which filters switch bounce and half-pressed combos.
  • Stops when you let go: a new command goes out as soon as it settles, and the current one repeats every 50 ms, so releasing the controls stops the robot right away.
  • Adjustable speed: five levels from 20 % to 100 % of the robot's gait speed, remembered across power cycles.
  • Battery powered: a single 9 V battery in a bay closed by a magnetic cover, no screws.

Hardware

ESP32-C6 · arcade parts · one print project

Underside of the Arcade Remote top panel, with the joystick and five buttons wired to the small controller board
Under the panel: one wire per button, plus the joystick harness
Controller board×1ESP32-C6 SuperMini on a carrier board with a Mini360 buck converter (9 V to 5 V), a power switch, a battery terminal, a 5-pin joystick header and a 2×7 button header. Available here, or wire the switches straight to a bare SuperMini.
Arcade joystick×1Microswitch stick with a ball top and a 5-pin harness. Fit the 8-way gate if you want diagonals.
Arcade push buttons×530 mm snap-in buttons with microswitches: four for the direction cluster and one for the special (modifier) button.
Power9 VA 9 V battery and a snap connector screwed into the terminal block, with four 6 × 2 mm magnets to hold the battery cover.
CabinetPLABody, top cover, bottom plate and battery cover, all in one Bambu Studio project, plus the Fusion 360 source. The cover is multi-material, so the logo and outlines print in a second color.
InputSignalGPIOHeader
Joystick up / down / left / rightJS_UP JS_DOWN JS_LEFT JS_RIGHTGP3 GP2 GP0 GP15-pin joystick
Buttons up / down / left / rightBT_UP BT_DOWN BT_LEFT BT_RIGHTGP14 GP15 GP18 GP192×7 button
Special buttonBT_SPECIALGP202×7 button
Status LEDPIN_RGBGP8WS2812 on the SuperMini

Every input is a plain switch to ground: the firmware enables the internal pull-ups, so one terminal goes to the signal pin and the other to any GND pin.

Controls

One command at a time · nothing pressed means stand by

Joystick

Walks in eight directions, and takes priority over the direction buttons.

Up / Down
Walk forward / backward
Left / Right
Sidestep left / right
Diagonals
Walk at 45° and 135° either side

Direction buttons

Used when the joystick is centered.

Up
Walk forward
Down
Walk backward
Left
Turn left in place
Right
Turn right in place

Special + button

Holding special turns the cluster into body motion.

+ Up
Body pitch
+ Left
Body roll
+ Right
Body yaw
+ Down
Body twist
TurboHold the up button while pushing the joystick up to run forward fast, or the down button while pulling it down to run backward fast.
SpeedHold special and flick the joystick up or down to step between 20, 40, 60, 80 and 100 %. The level is saved in flash and sent with every packet, so the robot always follows the remote.
Forgiving combosBecause a command must hold for 30 ms, special + up doesn't have to be pressed perfectly together: the robot gets the finished combo, not whichever switch closed first.
Blinking blueConnecting to the robot
Blinking redWiFi lost, retrying
GreenConnected, standing by
CyanWalking or turning
YellowTurbo
MagentaBody motion
White flashSpeed level changed
BrightnessDim at 20 %, brightest at 100 %

How It Works

Switches to UDP in four steps

ScanAll nine switches read every 5 ms
MapThe switch states become exactly one command
SettleSent once it has held for 30 ms, then every 50 ms
RobotUDP to 192.168.4.1:1234 on the robot's own AP
byte 0magic0xA5
byte 1cmd0–18
bytes 2–5seq_numuint32, counts every packet
byte 6speed20–100 %

Each packet is 7 bytes, little-endian and unpadded, and matches UdpControlPacket in the hexapod firmware. The speed byte needs hexapod firmware with motion-speed support; older firmware only accepts the 6-byte packet, so update the robot too. The remote connects in the background and keeps retrying, so the robot and the remote can be powered up in either order.

ESP32-C6ArduinoWiFiUDPAdafruit NeoPixelBambu StudioFusion 360

Build One

Print · wire · flash

Print

Open arcade.3mf in Bambu Studio: PLA, 0.2 mm layers, 0.4 mm nozzle. No AMS? Print the cover in a single color.

Assemble

Snap the buttons into the cover, bolt the joystick down with M4 hardware, mount the board on M2 standoffs, then close the cabinet with M3 screws.

Flash

Upload software/arcade/arcade.ino with Arduino IDE 2.x, the esp32 board package 3.x, and the Adafruit NeoPixel library.

Point it at your robot

Edit the top of the sketch. Every hexapod hosts its AP at 192.168.4.1 on port 1234, so usually only the SSID changes:

const char *ssid = "hexapod_nougat";
const char *password = "hexapod_1234";
const IPAddress udpAddress(192, 168, 4, 1);
const int udpPort = 1234;

Robots it drives

RobotssidGuide
Nougathexapod_nougatBuild
MochihexapodBuild
Macaroonhexapod_macaroonBuild

Select ESP32C6 Dev Module as the board. If the port never shows up, hold BOOT, tap RESET, release BOOT, and upload again. The step-by-step version with photos is the Build the Arcade Remote guide.

MIT license · feedback welcome Issues · Build guide · Hexapod