

FullSheetCurlingTimer
An exploration of ESP32, Bluetooth GATT, and ESP-NOW to create a full-sheet curling timer for practice.
- Size
- 81 × 54.5 mm
- Copper layers
- 2
- Thickness
- 1.6 mm
- Parts
- 25
- Nets
- 16
- Pads
- 92
- Tracks, vias
- 98, 0
- Pours
- 1
- Routed
- Yes
- KiCad
- KiCad 9.0 (file 20241229)
- Created
- 16 Dec 2025
- Updated
- 28 Jan 2026
Overview
FullSheetCurlingTimer is an open-source printed circuit board by theznerd, from the theznerd/FullSheetCurlingTimer repository on GitHub. It is a 2-layer board of 81 × 54.5 mm with 25 parts on 16 nets, routed with 98 tracks and 0 vias.
It is built around the LM393N and BC337. Its parts include 8 resistors, 2 capacitors, 2 transistors, 1 IC and 1 switch. It belongs with the radio and wireless boards of this library.
Main components
2README
README.md🥌🥌🥌 Full Sheet Curling Timer 🥌🥌🥌
The purpose of this repository is to explore an inexpensive, ESP32-based, laser trip timer for full sheet timing (4 lasers, 2 at each back line and 2 at each hog line). Access to the times recorded by the timer is provided via a simple web interface that connects to an ESP32 using the Web Bluetooth API. One ESP32 acts as a BLE Peripheral that hosts a custom GATT service for the timer, and all four ESP32 devices will act as event detectors (laser trip detection) which communicate the event data via ESP-NOW protocol to be picked up by the BLE peripheral.

License
This project is licensed under the Business Source License 1.1 (BUSL). You may use it freely for noncommercial purposes. For commercial use, please contact nathan@z-nerd.com to obtain a commercial license.
Goals
- 💸 Low-cost hardware: inexpensive components (e.g., ESP32, laser modules) to keep single sheet cost under $150 (less when building for multiple sheets).
- ✅ Easy fabrication: 3D-printable enclosure and PCBs for hobbyist skill level assembly (or schematics for breadboard assembly).
- ⏱️ Accurate timing: millisecond-level accuracy for splits.
- ⚙️ Easy Setup and Use: non-technical friendly setup and operation with guidance for setup and calibration provided in the web UI.
- 👀 Full sheet support: support dual split timing (back line to hog line, and hog line to hog line) and bi-directional throws without moving hardware.
- 👨👩👧👦 Multi-viewer support: allow multiple phones/tablets to connect and view timing data simultaneously.
- 🌐 Native App: simple native app accessible from any modern platform with Bluetooth support - no cloud services, no complicated Wi-Fi setup for devices.
Architecture (Multi-viewer)
Roles and data flow
-
Main Timer and Laser Sensor - ESP32 = BLE Peripheral (GATT Server)
- Advertises a custom "Timer Service" so clients can discover it.
- Has an assigned sheet ID (via dip switches) for identification.
- Has an assigned placement ID (via dip switches) for sheet position.
- Receives laser trip events from self and secondary timer devices (ESP-NOW).
- Hosts characteristics for state + events.
- Pushes timing updates using notifications.
-
Secondary Timer Devices - ESP32s = ESP-NOW Sender
- Has an assigned sheet ID (via dip switches) for identification.
- Has an assigned placement ID (via dip switches) for sheet position.
- Communicates laser trip events via ESP-NOW protocol.
-
Viewer (browser/web UI) = BLE Central (GATT Client)
- Scans for timer devices (filtered by name/service UUID).
- Connects to one timer device at a time.
- Provides diagnostics and setup UI.
- Reads current timer state upon connection.
- Subscribes to notifications to receive live updates.
This pattern supports multiple viewers concurrently: each viewer connects and enables notifications independently.
BLE Advertising For Viewer Discovery
To make it easy to pick the right timer when multiple devices are nearby, each device should include clear identity in advertising:
- Device name: e.g.,
CurlTimer Sheet 3 - Advertised Service UUID:
Timer Service(custom UUID) - Optional service/manufacturer data: e.g.,
sheetId,deviceId,firmwareVersion
GATT Service Model (proposed)
GATT is used for structured data exchange between the timer device and viewer. GATT is well-suited for this use case due to its efficient notification mechanism for real-time updates. Implementation details are discussed in the firmware design decisions document.
Device-to-Device ESP-NOW Communication Model
ESP-NOW is the proposed protocol for communication between the laser sensors and the main timer device. ESP-NOW was considered over BLE Advertising due to better reliability and lower latency. Implementation details are discussed in the firmware design decisions document.
Notes for future consideration
- WebKit has no support (actively opposes) for the Web Bluetooth API, and all iOS browsers are forced to use WebKit (with the exception of EU member states). Therefore, iOS support is not feasible with the current Web Bluetooth API limitations. Need to switch to a native app, which will bring added complexity. Looking at Avalonia for cross-platform native app development.
- It is possible to infer the direction of travel from the sequence of laser trip events, so that a stone passing the opposing back line does not cause a new timing event. However, this may be error-prone if stones are being thrown closely together in timing in opposite directions. Explicit direction setting from the viewer may be more reliable but requires user interaction which may be inconvenient or undesirable during practice.
- It may be useful to calculate the rock speed at each trip point and include that in the event data sent to viewers.
- Timing accuracy note: ESP-NOW retries/bursts improve delivery reliability but can add variable arrival latency. To keep recorded split times accurate, trip events should include a sender-side capture timestamp (taken at the instant the beam transition is detected), and the main timer should map that to its own clock using a lightweight beacon-based offset estimate.
Wish List
- Apple WatchOS App for on-ice timing
- Garmin Connect IQ App for on-ice timing
Parts
25| Qty | Value | Footprint | References |
|---|---|---|---|
| 4 | MountingHole_2.2mm_M2 | MountingHole:MountingHole_2.2mm_M2 | M2, M2, M2, M2 |
| 3 | 100kΩ | Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_Horizontal | R1, R2, R7 |
| 2 | 0.1µF | Capacitor_THT:C_Disc_D7.0mm_W2.5mm_P5.00mm | C1, C2 |
| 2 | 10kΩ | Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_Horizontal | R3, R5 |
| 2 | PinHeader_1x19_P2.54mm_Vertical | Connector_PinHeader_2.54mm:PinHeader_1x19_P2.54mm_Vertical | , |
| 1 | 1MΩ | Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_Horizontal | R4 |
| 1 | 1kΩ | Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_Horizontal | R6 |
| 1 | 47kΩ | Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_Horizontal | R8 |
| 1 | BC337 | FSCT:TO92254P480H870-3 | Q2 |
| 1 | LM393N | FSCT:DIP254P762X508-8 | U1 |
| 1 | LOGO | FSCT:CurlingStone | G*** |
| 1 | LOGO | FSCT:znerdlogo | G*** |
| 1 | Laser | LED_THT:LED_D5.0mm_Horizontal_O1.27mm_Z3.0mm_Clear | LD1 |
| 1 | PT334 | LED_THT:LED_D5.0mm_Horizontal_O1.27mm_Z3.0mm_Clear | Q1 |
| 1 | Piezo | FSCT:CUI_CMI-1295IC-0585T | LS1 |
| 1 | SW_DIP_x05 | Button_Switch_THT:SW_DIP_SPSTx05_Slide_9.78x14.88mm_W7.62mm_P2.54mm | SW2 |
| 1 | SolderWire-0.5sqmm_1x03_P4.6mm_D0.9mm_OD2.1mm | Connector_Wire:SolderWire-0.5sqmm_1x03_P4.6mm_D0.9mm_OD2.1mm | TP4056 w/ Step Up |
Questions
How big is the FullSheetCurlingTimer PCB?
It measures 81 × 54.5 mm and has 2 copper layers, 1.6 mm thick.
What parts does the FullSheetCurlingTimer use?
25 parts, built around the LM393N and BC337. 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 FullSheetCurlingTimer KiCad files?
From the theznerd/FullSheetCurlingTimer repository on GitHub, at the commit this page was made from: the board is PCB/MainBoard/MainBoard.kicad_pcb and its schematic PCB/MainBoard/MainBoard.kicad_sch. PCBKit opens the board in the browser, with nothing to install.
Can I use the FullSheetCurlingTimer design in my own project?
Its repository states no licence, so its author keeps all rights: ask theznerd before reusing the design.
Similar boards
- 2 layers101.5 × 63 mm

- 2 layers180 × 130 mm

Cell test bench
0hasant/Liion_Cell_Simulator
Single-cell characterization bench for 18650 and 21700 Li-ion cells (DMEGC INR45E, generic 3.5 Ah 18650). Part of the Solaris final-year project.
133 parts - 2 layers60 × 80 mm

- 2 layers36 × 26 mm

- 2 layers120 × 95 mm

Rain Sense
Iva0108/Rain-Sense
PCB design as well as case design for a rain sensor. KiCad and FreeCad.
55 parts - 2 layers48 × 72 mm

- 2 layers50 × 25 mm

Mbus master
roarfred/AmsToMqttBridge
Minimalistic system to read AMS/HAN data from electrical meter
50 parts223 - 2 layers118 × 103.5 mm
