Skip to the content
4 layers95 × 58 mmEsp32Tap, the printed circuit board in 3D

Controlling my procor-9.3x treadmill

Size
95 × 58 mm
Copper layers
4
Thickness
1.59 mm
Parts
94
Nets
77
Pads
304
Tracks, vias
1,258, 265
Pours
10
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
28 Jan 2026
Updated
7 Sep 2026

Overview

Esp32Tap is an open-source printed circuit board by scottmsilver, from the scottmsilver/treddy repository on GitHub. It is a 4-layer board of 95 × 58 mm with 94 parts on 77 nets, routed with 1,258 tracks and 265 vias.

It is built around the ESP32-S3-WROOM-1-N8, SN74LVC1G126DBVR-TP and TPS54202DDCR, with the SN74LVC2G08DCTR, TPS3700DDCR and TPS70950DBVR-TP among its other parts. Its parts include 32 resistors, 21 capacitors, 8 diodes, 7 ICs and 3 connectors. It belongs with the ESP32 boards of this library.

Main components

12

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

94
QtyValueFootprintReferences
1610kResistor_SMD:R_0603_1608MetricR7, R8, R10, R13, R18, R20, R21, R23, R24, R25, R26, R27, R28, R29, R30, R31
7100nFCapacitor_SMD:C_0603_1608MetricC4, C5, C9, C11, C17, C20, C21
3100kResistor_SMD:R_0603_1608MetricR1, R3, R22
322uF/25V X7R 1210Capacitor_SMD:C_1210_3225MetricC1, C6, C7
3M2.5MountingHole:MountingHole_2.7mm_M2.5MH1, MH2, MH3
3PESD3V3L1BA-NDiode_SMD:D_SOD-323D5, D6, D7
210uF/25V X7R 1206Capacitor_SMD:C_1206_3216MetricC2, C3
21nF/50V C0G 0603Capacitor_SMD:C_0603_1608MetricC18, C19
222RResistor_SMD:R_0603_1608MetricR15, R16
2441440003RJ45_SMD:RJ45-SMD_441440003J1, J2
25.1kResistor_SMD:R_0603_1608MetricR4, R5
2DNPCapacitor_SMD:C_0603_1608MetricC13, C14
2SKRPACE010Button_Switch_SMD:SW_SPST_SKRPACE010SW1, SW2
1+5V_RLYTestPoint:TestPoint_Pad_1.5x1.5mmTP6
1100RResistor_SMD:R_0603_1608MetricR6
110uF/16V 0805Capacitor_SMD:C_0805_2012MetricC8
110uH SWPA4030S100MTInductor_SMD:L_Sunlord_SWPA4030SL1
1150kResistor_SMD:R_0603_1608MetricR17
11812L075/24DRFuse:Fuse_1812_4532MetricF1
11kResistor_SMD:R_0603_1608MetricR12
11uFCapacitor_SMD:C_0603_1608MetricC10
11uF/25V X7R 0603Capacitor_SMD:C_0603_1608MetricC15
122kResistor_SMD:R_0603_1608MetricR2
1255kResistor_SMD:R_0603_1608MetricR19
12N7002Package_TO_SOT_SMD:SOT-23Q2
1330RResistor_SMD:R_0603_1608MetricR11
13V3TestPoint:TestPoint_Pad_1.5x1.5mmTP3
14.7kResistor_SMD:R_0603_1608MetricR32
14.7uF/25V X7R 0805Capacitor_SMD:C_0805_2012MetricC16
147kResistor_SMD:R_0603_1608MetricR14
1560RResistor_SMD:R_0603_1608MetricR9
156pF C0G 0603Capacitor_SMD:C_0603_1608MetricC12
1BC817-40,215Package_TO_SOT_SMD:SOT-23Q1
1ESP32-S3-WROOM-1-N8RF_Module:ESP32-S3-WROOM-1U1
1G6K-2F-Y-TR DC5Relay_SMD:Relay_DPDT_Omron_G6K-2F-YK1
1GNDTestPoint:TestPoint_Pad_1.5x1.5mmTP4
1K1_NC_FBTestPoint:TestPoint_Pad_1.5x1.5mmTP12
1K1_NO_FBTestPoint:TestPoint_Pad_1.5x1.5mmTP13
1RED-0603LED_SMD:LED_0603_1608MetricLED2
1RELAY_GATETestPoint:TestPoint_Pad_1.5x1.5mmTP8
1RELAY_SWTestPoint:TestPoint_Pad_1.5x1.5mmTP9
1RXD0TestPoint:TestPoint_Pad_1.5x1.5mmTP2
1SMAJ6.0CADiode_SMD:D_SMAD4
1SMBJ10ADiode_SMD:D_SMBD3
1SN74LVC1G126DBVRPackage_TO_SOT_SMD:SOT-23-5U7
1SN74LVC2G08DCTRPackage_SO:SSOP-8_2.95x2.8mm_P0.65mmU6
1SS34Diode_SMD:D_SMAD1
1TPS3700DDCRPackage_TO_SOT_SMD:SOT-23-6U4
1TPS54202DDCRPackage_TO_SOT_SMD:SOT-23-6U2
1TPS70950DBVRPackage_TO_SOT_SMD:SOT-23-5U5
1TREAD_OKTestPoint:TestPoint_Pad_1.5x1.5mmTP7
1TXD0TestPoint:TestPoint_Pad_1.5x1.5mmTP1
1TX_DRVTestPoint:TestPoint_Pad_1.5x1.5mmTP11
1TX_GATETestPoint:TestPoint_Pad_1.5x1.5mmTP10
1USB-C_HRO_TYPE-C-31-M-12Connector_USB:USB_C_Receptacle_HRO_TYPE-C-31-M-12J3
1USBLC6-2SC6Package_TO_SOT_SMD:SOT-23-6U3
1VINTestPoint:TestPoint_Pad_1.5x1.5mmTP5
1XL-1608UGC-04LED_SMD:LED_0603_1608MetricLED1

More from scottmsilver/treddy

1
  • 2 layers65 × 45 mmPiZeroHat, the printed circuit board in 3D

    PiZeroHat

    scottmsilver/treddy

    Controlling my procor-9.3x treadmill

    9 parts2

Similar boards

  • 4 layers72 × 70 mm0000000001, the printed circuit board in 3D

    0000000001

    harris-newsteder/0000000001

    98 parts2
  • 4 layers21.7 × 89.8 mmEuroPlatvorm, the printed circuit board in 3D

    EuroPlatvorm

    nanassound/eurorack-nanassound

    Eurorack modules of Nanas Sound

    34 parts27
  • 4 layers141.6 × 135.2 mmController core reva, the printed circuit board in 3D

    Controller core reva

    itorralbo/open-saeco-controller

    Controladora open-source para sustituir la electrónica de la Saeco Incanto HD8911, placa objetivo 421941308981/01. Proyecto independiente, sin afiliación a Philips/Saeco.

    226 partsMIT
  • 4 layers110 × 90 mmFilMachine Mainboard, the printed circuit board in 3D

    FilMachine Mainboard

    yesnoj/FilMachine_Reworked

    FilMachine is an automated film processing machine designed for photographic film development. It handles the entire process: chemical baths, water rinses, temperature regulation, and motor-driven film agitation — all…

    205 parts
  • 6 layers300 × 220 mmAIPE Buck 1kW, the printed circuit board in 3D

    AIPE Buck 1kW

    FulongLi/AIPE-PCB-Agent

    AIPE-PCB-Agent is the PCB design automation of the AIPE power-electronics ecosystem. Python generators turn a requirement file set (specification, insulation table, components, interfaces, floorplan and routing inputs)…

    240 parts
  • 4 layers90 × 66 mmChassisBoard, the printed circuit board in 3D

    ChassisBoard

    SolarEnergyRacers/solar_car_control_system_v6

    solarenergyracers.ch - control system (AC, DC, MC), Documents

    71 parts
  • 4 layers100 × 90 mmNexus pear reva, the printed circuit board in 3D

    Nexus pear reva

    aminewe898/nexus-pear-reva

    NEXUS PEAR Rev A hardware design, schematics, PCB, manufacturing review exports and engineering documentation

    117 partsMIT
  • 4 layers560.1 × 158.8 mmKeyboard, the printed circuit board in 3D

    Keyboard

    DEV-ajthedj/Keyboard

    A custom RGB keyboard that features three 1D capacitive touch sliders, two joysticks, an OLED screen, a fingerprint sensor, and plenty of macro keys!

    439 parts

Questions

How big is the Esp32Tap PCB?

It measures 95 × 58 mm and has 4 copper layers, 1.59 mm thick.

What parts does the Esp32Tap use?

94 parts, built around the ESP32-S3-WROOM-1-N8, SN74LVC1G126DBVR-TP, TPS54202DDCR and SN74LVC2G08DCTR. 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 Esp32Tap KiCad files?

From the scottmsilver/treddy repository on GitHub, at the commit this page was made from: the board is hardware/Esp32Tap/kicad/Esp32Tap.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 Esp32Tap design in my own project?

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