Single-axis mouse joystick controller board for the Janelia Dudman lab joystick rig, built as a native pyControl peripheral. One board drives one joystick: an RP2040 runs a TMC5130A stepper driver with the joystick's encoder and limit switch, a magnetic-particle brake, a torque-sensor bridge and two analog outputs, and speaks a line protocol to pyControl over one UART. The rig has two joysticks and two of these boards.
Status, October 2026: v1.0 is the fabricated revision, tagged v1.0.
Four assembled boards have been built by JLCPCB from the package in
fab/mouse-joystick-pcb/ (committed
2026-09-21). All four passed bench bring-up and ran the rig's trial task end
to end through pyControl running
mouse-joystick-firm:
units A and B were installed in Rig 1 on 2026-10-09, and units C and D run
the verification rig at Peter's desk since 2026-10-12. Every measurement
made on a board is in the bring-up log, under the
board's serial.
The Board
The block below is written by make docs from the KiCad sources: renders, key
dimensions, and links to the schematic, BOM, STEP model and enclosure geometry.
Do not edit between the markers; run make docs instead.


More views, including both elevations, are in the generated documentation.
The documentation site, with the board turning and its design blocks clickable: https://peterpolidoro.github.io/mouse-joystick-pcb/.
| Property | Value |
|---|---|
| Outline | 100.0 × 80.0 mm, 5.0 mm corner radius |
| Thickness | 1.6 mm |
| Copper layers | 4 |
| Mounting holes | 4 × 3.2 mm |
| Connectors and controls | 13 |
| Bill of materials | 81 distinct parts, 360 placements |
Documents
| Document | File |
|---|---|
| Schematic, all sheets, PDF | mouse-joystick-pcb-schematic.pdf |
| Schematic sheets, SVG (20) | schematic/ |
| Schematic, instance overviews and details, PDF | Review booklet |
| Design blocks placed (15), one page each | blocks/README.md |
| Board view: the model and the top render with the design blocks numbered | board-view.md |
| Subsystem sheets (4), from their recipes | subsystems/README.md |
| MCU pin allocation, from the board source | gpio-allocation.md |
| Assembly view, top | assembly-top.svg |
| Assembly view, bottom | assembly-bottom.svg |
| Assembled board, STEP, for FreeCAD | mouse-joystick-pcb-assembled.step |
| Assembled board, glTF, for a viewer (the library's materials written in) | mouse-joystick-pcb.glb |
| Bill of materials | table · CSV |
| Outline and mounting holes, dimensioned drawing | SVG · PDF · PNG |
| Board dimensions and stackup | board-dimensions.md |
| Board geometry, machine readable | board-geometry.json |
| Mounting holes | mounting-holes.csv |
| Connector locations | connectors.csv |
Enclosure Reference
Millimetres from the centre of the board outline, X right and Y up, looking at the top of the board. Extents are the part's courtyard, which is what a panel cutout has to clear. Full tables in board-dimensions.md.

The outline and the mounting holes dimensioned, as KiCad draws them: SVG · PDF; the cross is the centre the tables measure from.
Mounting holes
| Ref | X (mm) | Y (mm) | Drill (mm) |
|---|---|---|---|
| H101 | -45.0 | 35.0 | 3.2 |
| H102 | 45.0 | 35.0 | 3.2 |
| H103 | 45.0 | -35.0 | 3.2 |
| H104 | -45.0 | -35.0 | 3.2 |
Connectors and controls
| Ref | Part | X (mm) | Y (mm) | Rot | Extent X (mm) | Extent Y (mm) |
|---|---|---|---|---|---|---|
| J201 | USB-C | -45.0 | -11.0 | 90.0 | -47.31 to -42.69 | -16.05 to -5.95 |
| J301 | RJ45-8P8C | -41.0 | 8.0 | 270.0 | -50.0 to -32.0 | -0.5 to 16.5 |
| J501 | TBH-1x02-5.08mm | -44.0 | 24.0 | 270.0 | -48.3 to -38.7 | 17.41 to 30.58 |
| J901 | Conn_Coaxial_HL-BNC-KHDA | 16.0 | -15.0 | 0.0 | 9.5 to 22.5 | -21.5 to -8.5 |
| J1101 | Conn_Coaxial_HL-BNC-KHDA | -8.0 | -15.0 | 180.0 | -14.5 to -1.5 | -21.5 to -8.5 |
| J1102 | TBH-1x04-3.5mm | -21.0 | 36.0 | 180.0 | -29.2 to -12.8 | 31.25 to 39.5 |
| J1103 | TBH-1x05-3.5mm | 1.0 | 36.0 | 180.0 | -8.95 to 10.95 | 31.25 to 39.5 |
| J1301 | FH12-50S-0.5SVA(54) | 0.0 | -36.0 | 180.0 | -14.75 to 14.75 | -38.8 to -33.2 |
| J1601 | TBH-1x02-3.5mm | 18.0 | 36.0 | 180.0 | 13.3 to 22.7 | 31.25 to 39.5 |
| J1801 | TBH-1x02-3.5mm | 37.0 | -12.0 | 180.0 | 32.3 to 41.7 | -16.75 to -8.5 |
| J2001 | TBH-1x05-3.5mm | 37.0 | 18.0 | 180.0 | 27.05 to 46.95 | 13.25 to 21.5 |
| SW601 | 436333045822 | -47.5 | -27.5 | 270.0 | -49.5 to -45.5 | -31.0 to -24.0 |
| SW602 | 436333045822 | -47.5 | -20.5 | 270.0 | -49.5 to -45.5 | -24.0 to -17.0 |
What Is On It
| Connector | Carries |
|---|---|
J301 RJ-45 |
pyControl behaviour port: the UART at 115200 8N1, and the port's 5 V, which powers the MCU when USB is absent |
J201 USB-C |
firmware load, a USB serial console, and the other MCU power source |
J501 2-pos 5.08 mm terminal |
36 V motor supply, behind a protected, firmware-switched high-side input |
J1102 4-pos 3.5 mm terminal |
stepper coils |
J1103 5-pos 3.5 mm terminal |
encoder: supply, return, A and B |
J1601 2-pos 3.5 mm terminal |
limit switch |
J1801 2-pos 3.5 mm terminal |
brake coil, driven by a 0 to 49 mA current sink |
J2001 5-pos 3.5 mm terminal |
torque-sensor bridge: excitation, signal pair, ground and shield |
J1101 BNC |
joystick angle, 0 to 3.3 V analog out |
J901 BNC |
torque, 0 to 3.3 V analog out |
J1301 50-pin FFC |
instrument port: 32 buffered digital taps for a logic analyzer |
SW601, SW602 |
side-actuated buttons for the RP2040: BOOTSEL and reset |
The board has two power domains. The MCU domain runs from USB or from the
pyControl port's 5 V and is always on, so the board answers ID and STATUS
with the motor supply off. Everything else, the driver, the brake sink, the
torque front end and the analog outputs, runs from the 36 V input through a
switched high-side input that firmware controls, so pyControl can power-cycle
every peripheral to a known state without anything being unplugged.
Power explains the chain.
The two joysticks use different motor and encoder cables so that the boards and the firmware can be identical; a board carries no left or right state. Harness pinouts gives both cables and how a wrong one shows up.
Documents
- Interface map: every connector pin, GPIO and instrument-port channel, with the board manifest
- UART protocol: the line protocol pyControl speaks to the board
- pyControl port pinout and pyControl interface: the RJ-45 and how the board uses it
- Harness pinouts: the left and right joystick cables
- Rig layout: how a board sits in the rig and what plugs into each connector
- Power: the 36 V chain, the two domains and the pyControl 5 V budget
- OneBox analog interface and encoder analog output: the angle and torque BNC outputs
- Bring-up log: every measurement, by board serial
- Fabrication package: the JLCPCB package the v1.0 boards were ordered from, with its reports
- Datasheets: the motor, encoder, brake and torque sensor the board was designed around
- Generated board documentation: schematic PDF and SVGs, renders, STEP and glTF, BOM, enclosure geometry and the dimensioned outline drawing, one page per placed design block and per subsystem sheet, and the MCU pin allocation
- The documentation site: the same pages with the board turning and its design blocks clickable
Opening And Fabricating
KiCad 10 opens kicad/mouse-joystick-pcb.kicad_pro. The schematic and board
carry their own copies of every symbol and footprint; KiCad reports the
project's shared libraries as missing once and carries on, and the only loss
is the 3D models in the viewer, which the assembled STEP model under
docs/generated/3d/ covers.
To order more boards, upload mouse-joystick-pcb-jlcpcb.zip,
jlcpcb-bom.csv and jlcpcb-mouse-joystick-pcb-all-pos.csv from
fab/mouse-joystick-pcb/ to JLCPCB; the package's README records what was
validated and which placement rotations were corrected. To fabricate
elsewhere, plot the layers and drill files from the board in KiCad.
Related Repositories
- mouse-joystick-firm: the firmware, the pyControl device class, a board simulator and the protocol test corpus.
- camera-gpio-interface-pcb: the rig's camera interface board.
- mouse-joysticks-mech: STEP and glTF of the two-joystick mechanical assembly.
- joystick-rig: the rig's pyControl tasks, hardware definition and operating notes.
Development
The board was drawn from a shared KiCad library and toolchain, which is
needed only to regenerate docs/generated/, the fabrication package or the
composed sheets. docs/development.md describes that
toolchain, the environment, the sibling repositories and the design and
layout record. Agent guidance is in AGENTS.md and .agents/.
License
Hardware design files and documentation are CC-BY-SA-4.0; code and automation are 3-clause BSD. See LICENSE.
Citation
CITATION.cff carries the citation metadata; GitHub renders it under "Cite this repository".
Files
| Name | Size |
|---|---|
| .agents/ | |
| .codex/ | |
| .github/ | |
| .guix/ | |
| fab/ | |
| kicad/ | |
| LICENSES/ | |
| .gitignore | 380 B |
| AGENTS.md (raw) | 425 B |
| CITATION.cff | 1 kB |
| CLAUDE.md (raw) | 364 B |
| LICENSE | 557 B |
| Makefile | 30 kB |
| mkdocs.yml | 4 kB |
| README.md (rendered above; raw) | 11 kB |