Overview
The autonomous drone needed something better than a laptop balanced on a truck tailgate. This is a self-contained ground station built into a Pelican 1550: a Beelink mini PC running Ubuntu, QGroundControl, and the WFB-NG video downlink, plus a custom control panel that makes the whole thing feel like equipment instead of my desk at home.
The control panel PCB
The panel is driven by a custom ESP32-S3 board that bridges physical controls (joystick, throttle, toggle switches, four 6-position rotary switches, a key switch) to the PC as a USB composite device: an HID gamepad that QGroundControl reads natively, plus a CDC serial channel for telemetry.
The board was routed entirely headless, verified at every step with kicad-cli:
schematic ERC driven from 33 violations to 0, then autorouted to 0 DRC
violations. The routing survived one rework. A pad-by-pad check against
Espressif’s pinout showed the generic 2×20 header footprint put the DevKitC-1’s
two pin rows 2.54 mm apart instead of 22.86 mm, so the module could not have
seated. A custom footprint fixed the geometry, an SPI remap moved the display bus
off the octal-PSRAM pins, and the board grew to 160 × 110 mm to fit the real
module. The final route is 514 trace segments and 12 vias, with all 29 MCU pads
checked against the datasheet.

Two ILI9341 displays run LVGL-based MFD/PFD screens, prototyped in an SDL2 desktop simulator that switches to real hardware with one line.
The firmware (PlatformIO, Arduino-ESP32, LVGL 9.5) compiles to 678 KB with 42%
of RAM in use. Its first compile caught a bug that reading the source would not
have: the DevKitC-1 board definition hard-sets ARDUINO_USB_MODE=1, the hardware
CDC peripheral, which cannot present a HID device. Defining it as 0 only
collided with the default; it had to be removed with build_unflags, or the
gamepad would never have enumerated for QGroundControl.
The panel inserts
Both halves of the case get a flat insert: the lid carries the displays, the base carries the keyboard and flight controls. Each one is roughly 480 × 365 mm, far larger than my 256 mm print bed, so both come out of a build123d script that reads Pelican’s STEP model of the case, sections the interior at the panel plane, and splits the result into four quarters joined by half-lap seams with 0.2 mm of clearance.
Working from the STEP model fixed the worst problem with the first base panel, a single fabricated board with four identical 24.8 mm corner radii. The case corners are splines, not arcs: a best-fit circle misses them by 6.9 mm. Sectioning the real geometry gives an outline that follows the wall with 0.3 mm of clearance all the way around.

The model also turned up mounting points I did not have to add. The lid has five molded screw bosses (four corners, one on the centerline) with 3.2 mm pilot holes, and the base has 15 small ledges around its walls, 24.5 mm below the rim. Neither insert needs the case drilled or anything glued to it.
The lid stack is a 4 mm printed panel, 22.3 mm standoffs, and a 9 mm Baltic birch frame that screws to the bosses. The standoff length is not a free choice: it is whatever puts the back of the frame on the boss faces. The main display has no mounting holes of its own, so it is clamped instead. The panel window is smaller than the display body, and the frame presses it forward from behind.
The base insert gets leaned on, so it is designed for stiffness. Deflection scales with span cubed: a 100 mm strip of 5 mm PLA across a 240 mm span sags about 5.5 mm under a 5 kg hand, and going to 7 mm only buys a factor of 2.7. Shortening the span is the better lever. The 7 mm panel sits flat on a 9 mm birch sub-frame that rests on all 15 ledges, held by 38 screws on a grid, so the largest gap between fasteners is 91 mm. Nothing is fixed to the case; the whole assembly lifts straight out.

The keyboard and trackpad seat from below into pockets behind a 2 mm lip, so their surfaces sit just under the panel face and their cables never cross the top side. The trackpad is shallow enough that the sub-frame itself holds it up; the keyboard passes through the frame and is held by straps underneath.
The power system
A 12 V, 40 Ah LiFePO4 bus with a per-branch fuse schedule, pass-through AC charging, and thermostatic cooling. Budgeted at ~38 W typical draw for 13+ hours of runtime, with a labeled 23-wire harness cut list.
Status
PCB v1 is fabricated and hand-assembled: 25 parts, 187 pads, all through-hole. Next is staged bring-up (supply rails, then an I2C scan for the two MCP23017 expanders, then the displays) before the full firmware goes on. Remaining after that: porting the LVGL screens from the simulator, the PC-side telemetry bridge, touch input, and the battery fit-check (the 170 mm pack vs. 149 mm of case depth is an open argument with physics).
Panel inserts: the lid quarters have been test-printed and fit the lid. The base insert redesign and both birch frames are designed, with cut files ready to order.