# mouse-joystick-pcb

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/](fab/mouse-joystick-pcb/README.md) (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](https://github.com/peterpolidoro/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](docs/bringup-log.md), 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.

<!-- BEGIN GENERATED BOARD DOCUMENTATION -->
<!-- Generated by orb-weaver-kicad-docs. Edits between these markers are lost. -->

![Top, straight down](docs/generated/3d/top.png)

![Isometric from the front left](docs/generated/3d/iso-front-left.png)

More views, including both elevations, are in [the generated documentation](docs/generated/README.md).

The documentation site, with the board turning and its design blocks clickable: [https://peterpolidoro.github.io/mouse-joystick-pcb/](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](docs/generated/schematic/mouse-joystick-pcb-schematic.pdf) |
| Schematic sheets, SVG (20) | [schematic/](docs/generated/schematic/) |
| Schematic, instance overviews and details, PDF | [Review booklet](docs/generated/schematic/mouse-joystick-pcb-schematic-review.pdf) |
| Design blocks placed (15), one page each | [blocks/README.md](docs/generated/blocks/README.md) |
| Board view: the model and the top render with the design blocks numbered | [board-view.md](docs/generated/board-view.md) |
| Subsystem sheets (4), from their recipes | [subsystems/README.md](docs/generated/subsystems/README.md) |
| MCU pin allocation, from the board source | [gpio-allocation.md](docs/generated/gpio-allocation.md) |
| Assembly view, top | [assembly-top.svg](docs/generated/layout/assembly-top.svg) |
| Assembly view, bottom | [assembly-bottom.svg](docs/generated/layout/assembly-bottom.svg) |
| Assembled board, STEP, for FreeCAD | [mouse-joystick-pcb-assembled.step](docs/generated/3d/mouse-joystick-pcb-assembled.step) |
| Assembled board, glTF, for a viewer (the library's materials written in) | [mouse-joystick-pcb.glb](docs/generated/3d/mouse-joystick-pcb.glb) |
| Bill of materials | [table](docs/generated/bom/mouse-joystick-pcb-bom.md) · [CSV](docs/generated/bom/mouse-joystick-pcb-bom.csv) |
| Outline and mounting holes, dimensioned drawing | [SVG](docs/generated/mechanical/board-dimensions.svg) · [PDF](docs/generated/mechanical/board-dimensions.pdf) · [PNG](docs/generated/mechanical/board-dimensions.png) |
| Board dimensions and stackup | [board-dimensions.md](docs/generated/mechanical/board-dimensions.md) |
| Board geometry, machine readable | [board-geometry.json](docs/generated/mechanical/board-geometry.json) |
| Mounting holes | [mounting-holes.csv](docs/generated/mechanical/mounting-holes.csv) |
| Connector locations | [connectors.csv](docs/generated/mechanical/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](docs/generated/mechanical/board-dimensions.md).

![Outline and mounting holes, dimensioned](docs/generated/mechanical/board-dimensions.png)

The outline and the mounting holes dimensioned, as KiCad draws them: [SVG](docs/generated/mechanical/board-dimensions.svg) · [PDF](docs/generated/mechanical/board-dimensions.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 |

<!-- END GENERATED BOARD DOCUMENTATION -->

## 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](docs/power.md) 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](docs/harness-pinouts.md) gives both cables and how a wrong
one shows up.

## Documents

- [Interface map](docs/interface-map.md): every connector pin, GPIO and instrument-port channel, with the board manifest
- [UART protocol](docs/uart-protocol.md): the line protocol pyControl speaks to the board
- [pyControl port pinout](docs/pycontrol-port-pinout.md) and [pyControl interface](docs/pycontrol-interface.md): the RJ-45 and how the board uses it
- [Harness pinouts](docs/harness-pinouts.md): the left and right joystick cables
- [Rig layout](docs/rig-layout.md): how a board sits in the rig and what plugs into each connector
- [Power](docs/power.md): the 36 V chain, the two domains and the pyControl 5 V budget
- [OneBox analog interface](docs/onebox-analog-interface.md) and [encoder analog output](docs/encoder-analog-output.md): the angle and torque BNC outputs
- [Bring-up log](docs/bringup-log.md): every measurement, by board serial
- [Fabrication package](fab/mouse-joystick-pcb/README.md): the JLCPCB package the v1.0 boards were ordered from, with its reports
- [Datasheets](docs/datasheets/): the motor, encoder, brake and torque sensor the board was designed around
- [Generated board documentation](docs/generated/README.md): 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](https://peterpolidoro.github.io/mouse-joystick-pcb/): 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](https://github.com/peterpolidoro/mouse-joystick-firm): the firmware, the pyControl device class, a board simulator and the protocol test corpus.
- [camera-gpio-interface-pcb](https://github.com/peterpolidoro/camera-gpio-interface-pcb): the rig's camera interface board.
- [mouse-joysticks-mech](https://github.com/peterpolidoro/mouse-joysticks-mech): STEP and glTF of the two-joystick mechanical assembly.
- [joystick-rig](https://github.com/sourishmukh/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](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](LICENSE).

## Citation

[CITATION.cff](CITATION.cff) carries the citation metadata; GitHub renders it
under "Cite this repository".
