Skip to the content
PCBKitNew board
2 layers65 × 45 mmPiZeroHat, the printed circuit board in 3D

Controlling my procor-9.3x treadmill

Size
65 × 45 mm
Copper layers
2
Thickness
1.6 mm
Parts
9
Nets
44
Pads
83
Tracks, vias
65, 22
Pours
1
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
28 Jan 2026
Updated
7 Sep 2026

Overview

PiZeroHat is an open-source printed circuit board by scottmsilver, from the scottmsilver/treddy repository on GitHub. It is a 2-layer board of 65 × 45 mm with 9 parts on 44 nets, routed with 65 tracks and 22 vias.

Its parts include 3 resistors, 2 capacitors, 2 connectors and 1 IC.

README

README.md

Treddy

A 2005 treadmill that listens when you talk to it.

A Raspberry Pi sits between the console and motor controller of a Precor 9.31 treadmill, intercepting the serial bus. It runs an AI coach (Gemini), voice control, a tablet UI, and a Bluetooth daemon that makes Zwift think it's a modern smart treadmill.

The Ridgeline HUD: the workout's route switchbacks up a real mountain photo, with floating glass instruments

The Ridgeline HUD — your workout drawn as a trail up a real mountain. The route's switchbacks tighten with the grade, the strip on the right shows what's coming and when, and every panel is adaptive glass floating on the photo.


Voice + AI Coach

Detail: the interval route climbing the ridgeline, with grade/speed chips at each transition
  • "Set speed to 5" or "give me a 20-minute hill workout" — Gemini controls the belt directly
  • Voice works mid-run via Gemini Live (real-time, no wake word)
  • Says "this is the hardest interval" or "you're faster than last time" because it can query your run history

Apps

Lobby screen on Android tablet
  • Android (Kotlin + Compose): runs on a tablet mounted on the treadmill console
  • Workout library, run history, live elevation profile, calorie tracking

Bluetooth

  • Rust daemon makes the treadmill show up in Zwift, Peloton, QZ Fitness, and Apple Watch as a standard FTMS device
  • Fitness apps can read speed/incline and write speed/incline commands back

Heart Rate

  • Connects to any Bluetooth heart rate strap
  • HR shows in the UI and feeds into calorie calculations

Architecture

text
┌───────────────────────────────────────────────────────┐
│  Android (Kotlin + Compose)                           │
├───────────────────────────────────────────────────────┤
│  REST / WebSocket / Gemini Live (voice)               │
├───────────────────────────────────────────────────────┤
│  server.py (FastAPI)                                  │
│  Sessions, programs, AI chat, workout query DB        │
├──────────────────┬──────────────┬─────────────────────┤
│  treadmill_io    │  ftms-daemon │  hrm-daemon         │
│  C++20, GPIO     │  Rust, BLE   │  Rust, BLE          │
│  serial, safety  │  FTMS        │  heart rate         │
└──────────────────┴──────────────┴─────────────────────┘
                         │
                    Precor 9.31
                  RS-485 serial bus
  • C++ binary — reads/writes the serial bus, enforces safety (3-hour timeout, physical buttons always override software)
  • Python server — FastAPI. All the logic: Gemini AI, workouts, sessions, run history
  • FTMS daemon — Rust. Bluetooth for fitness apps
  • HRM daemon — Rust. Connects to heart rate straps
  • Android — display layer. All decisions happen server-side.

Details: CLAUDE.md


The Hardware Story

The serial protocol turned out to be plain ASCII text. We just had the polarity wrong and spent days decoding "binary" that was actually [key:value] pairs with every bit flipped.

Full reverse engineering writeup →

Custom hardware: the breadboard tap was productized into a custom Pi Zero 2 W hat — dual RJ45 (From Console / To Motor), a Pololu D24V10F5 buck so the treadmill's +8V rail powers the Pi, full 2×20 header. KiCad sources, gerbers, and wiring guides are in hardware/PiZeroHat/ (adapted from the vasya-zh/PiZeroHat pogo-pin base).


Quick Start

You need: a Raspberry Pi (any aarch64 model — Zero 2 W or 4), the treadmill serial tap (the custom hat in hardware/PiZeroHat/, or a breadboard tap wired per HARDWARE.md), Docker on your dev machine (for the cross toolchain), and a Gemini API key.

1. Build the OS image for your Pi. The Pi runs a stock Debian-based Pi OS; you flash a reproducible image built for your hardware. See provisioning/ for the image builder (DietPi is the reference implementation — adapt the regulatory/board settings for yours). Flash it, boot, confirm SSH.

2. Deploy the software. Compiled code is cross-built off-Pi in one Docker toolchain — nothing is compiled on the Pi. The OS runtime prerequisites (python3, libpigpio1) are installed automatically by the deploy; you do not apt-install anything by hand.

bash
make deploy        # cross-build → rsync → restart all 4 services
make deploy-key    # one-time per device: push your ./.gemini_key (a secret;
                   #   never rsync'd by a normal deploy)
make image         # OR: bake a flashable .img with everything pre-installed

Local dev (no Pi needed):

bash
TREADMILL_MOCK=1 ./scripts/dev.sh    # server.py in mock mode

API reference, deploy details, tests: CLAUDE.md

License

MIT

Parts

9
QtyValueFootprintReferences
3100Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_HorizontalR1, R2, R3
2100nFCapacitor_THT:C_Disc_D5.0mm_W2.5mm_P5.00mmC3, C4
1D24V10F5Scott:D24V10F5U1
1From ConsoleConnector_RJ:RJ45_Amphenol_54602-x08_HorizontalJ1
1Raspberry Pi Zero v1.3Raspberry_Pi_Zero_v.1.3_Hat:RASPI_ZERO_FULLA1
1To MotorConnector_RJ:RJ45_Amphenol_54602-x08_HorizontalJ2

Questions

How big is the PiZeroHat PCB?

It measures 65 × 45 mm and has 2 copper layers, 1.6 mm thick.

What parts does the PiZeroHat use?

9 parts. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the PiZeroHat KiCad files?

From the scottmsilver/treddy repository on GitHub, at the commit this page was made from: the board is hardware/PiZeroHat/kicad/PiZeroHat.kicad_pcb and its schematic hardware/Esp32Tap/kicad/Esp32Tap.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the PiZeroHat design in my own project?

Its repository states no licence, so its author keeps all rights: ask scottmsilver before reusing the design.

More from scottmsilver/treddy

1
  • 4 layers95 × 58 mmEsp32Tap, the printed circuit board in 3D

    Esp32Tap

    scottmsilver/treddy

    Controlling my procor-9.3x treadmill

    94 parts2

Similar boards

  • 2 layers103 × 30.5 mmTS Back Endcap, the printed circuit board in 3D

    TS Back Endcap

    EEVengers/ThunderScope

    ThunderScope GitHub Repo

    9 parts1.3kMIT
  • 2 layers31.8 × 47.6 mmNGC 38 connector, the printed circuit board in 3D

    NGC 38 connector

    rusefi/rusefi

    rusefi - GPL internal combustion engine control unit

    9 parts1.2k
  • 2 layers24 × 27.3 mmExpansion Card Retrofit, the printed circuit board in 3D

    Expansion Card Retrofit

    FrameworkComputer/ExpansionCards

    Reference designs and documentation to create Expansion Cards for the Framework Laptop

    9 parts1.1kCC-BY-4.0
  • 2 layers15.6 × 17.3 mmSKR Mini TFT Thermistor Board, the printed circuit board in 3D

    SKR Mini TFT Thermistor Board

    VoronDesign/Voron-Hardware

    Cool Hardware designed by the Voron Design group

    9 parts1.1kGPL-3.0
  • 2 layers39.1 × 49.5 mmLearnoliver, the printed circuit board in 3D

    Learnoliver

    hackclub/OnBoard

    💡 Join 1,000 teenagers and make your first PCB with a $100 grant!

    9 parts915
  • 2 layers17.4 × 16.9 mmToolhead, the printed circuit board in 3D

    Toolhead

    tanaes/whopping_Voron_mods

    9 parts787GPL-3.0
  • 2 layers9.8 × 108 mmExpander, the printed circuit board in 3D

    Expander

    wntrblm/Castor_and_Pollux

    A Juno-inspired dual oscillator

    9 parts587
  • 2 layersKeyboard after, the printed circuit board in 3D

    Keyboard after

    adamws/kicad-kbplacer

    KiCad plugin for automatic keyboard's key placement and routing

    9 parts547GPL-3.0