OpenRUNN is an ESP32-C3 treadmill running sensor. It reads pulses from a TCRT5000 optical sensor and exposes speed and distance through the Bluetooth Low Energy Running Speed and Cadence (RSC) service.
Follow the project on Instagram.
Connect the ESP32-C3 to the TCRT5000 module as follows:
- GND to
GND - 3.3 V to
VCC - GPIO 4 to
DO - Leave
AOdisconnected
The circuit is powered through the ESP32-C3 USB connector. The board supplies 3.3 V to the TCRT5000 module, so no separate power supply is required.
- Power the TCRT5000 from 3.3 V, not 5 V, so its digital output remains safe for the ESP32-C3 GPIO.
- The ESP32-C3 and sensor must share the same GND connection.
- Disconnect USB power while changing the wiring.
- Adjust the sensor module's potentiometer until
DOchanges state reliably once per belt marker. The module's digital indicator LED can be used while tuning the threshold. - Position the sensor close enough to the marker for reliable detection, while leaving enough clearance to prevent contact with the moving belt.
The enclosure parts can be 3D printed or modified online:
- Onshape CAD Project: OpenRUNN CAD on Onshape
Main enclosure housing the ESP32-C3 and TCRT5000 sensor.
- STL: assets/stl/top_case.stl
- STEP: assets/stl/top_case.step
Mounting rail for securing the case to the treadmill frame.
- Python 3
- A USB connection to an ESP32-C3 DevKitM-1
- macOS, Linux, or Windows
The first build downloads the ESP32 platform, Arduino framework, and other PlatformIO packages automatically.
From the project root, create and activate a virtual environment.
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install -r requirements.txtpy -3 -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txtThe virtual environment must be activated before using the pio commands below. To leave it, run:
deactivateMeasure the distance represented by one valid sensor pulse, in meters, and update main.cpp:
const float beltLengthMeters = 3.19f; // Distance per valid sensor pulseAfter changing this value, build and upload the firmware again.
The ESP32 creates an open Wi-Fi access point named OpenRUNN. Connect a phone or computer to that network, then open:
http://192.168.4.1
The dashboard displays session distance, pace, and elapsed time. The ESP32 exposes only current sensor telemetry through GET /api/status; Start, Pause, Resume, Stop, and session accumulation are handled locally by JavaScript in the browser.
Session values are not stored on the ESP32. Reloading or closing the dashboard page resets the current browser session.
The editable web sources are located in assets/web/. During every PlatformIO build, scripts/embed_web_assets.py minifies the HTML, CSS, and JavaScript, compresses them with gzip, and embeds them in the firmware. Generated files remain inside .pio/ and must not be edited or committed.
Run the dashboard locally with a simulated metrics API:
python scripts/dev_web_server.pyOpen http://127.0.0.1:8765. The server continuously simulates the same /api/status telemetry provided by the ESP32, while the browser manages the session controls. The default simulated speed is 10 km/h; change it with:
python scripts/dev_web_server.py --speed-kph 12.5To test from another device on the same network, bind to all interfaces and open the computer's local IP address from that device:
python scripts/dev_web_server.py --host 0.0.0.0Compile the firmware for the ESP32-C3 DevKitM-1:
pio run --environment esp32-c3-devkitm-1The first build may take longer while PlatformIO downloads the required toolchains and frameworks.
Connect the board by USB and upload the firmware:
pio run --target upload --environment esp32-c3-devkitm-1If PlatformIO does not detect the board automatically, list available serial ports:
pio device listThen specify the port explicitly:
pio run --target upload --environment esp32-c3-devkitm-1 --upload-port /dev/cu.usbmodemXXXXReplace /dev/cu.usbmodemXXXX with the port reported on your system.
Open the serial monitor at the configured baud rate:
pio device monitor --environment esp32-c3-devkitm-1 --baud 115200To specify the port explicitly:
pio device monitor --environment esp32-c3-devkitm-1 --port /dev/cu.usbmodemXXXX --baud 115200The firmware prints startup, Bluetooth connection, disconnection, and RSC measurement messages to the monitor.
Clean the build directory:
pio run --target clean --environment esp32-c3-devkitm-1Build and upload in one command:
pio run --target upload --environment esp32-c3-devkitm-1.
|-- assets/
| |-- images/ # Project images and screenshots
| |-- stl/ # 3D printable STL and STEP files
| `-- web/ # Dashboard HTML, CSS, and JavaScript sources
|-- platformio.ini # PlatformIO project configuration
|-- requirements.txt # Python dependency for PlatformIO Core
|-- scripts/ # Web asset build scripts
`-- src/
|-- main.cpp # Application setup and main loop
|-- BLE_RSC.cpp/.h # Bluetooth Low Energy RSC service
|-- WebDashboard.cpp/.h # Wi-Fi access point and web dashboard
`-- TCRT5000.cpp/.h # Optical sensor and pulse measurement




