Files
ChronoDisplay/README.md
T

211 lines
11 KiB
Markdown

# ChronoDisplay
An ESP32-based display panel for the **FX Archery Chronograph (v1)** that provides a real-time, always-on ePaper display of shot data via Bluetooth Low Energy (BLE). Compatible with airguns and archery applications.
## Overview
ChronoDisplay connects wirelessly to the [FX Archery Chronograph](https://fx-archery.com) via BLE, receives speed readings in real time, and displays comprehensive shot statistics on a 7.5" monochrome ePaper screen. It runs entirely on an ESP32 — no PC or phone required.
### Key Features
- **Live BLE Connection** — Automatically scans for, connects to, and maintains a link with the FX Chronograph
- **Real-Time E-Paper Display** — Always-on, sunlight-readable display showing:
- Latest shot velocity (FPS) and energy (FPE)
- Running shot count, average / min / max FPS
- Spread and standard deviation
- Profile info (gun name, power level, projectile type/caliber/weight)
- Last 32 shot history
- Real-time clock (EST timezone)
- Connection status indicator
- **Built-in Web Server** — Configure everything from any browser on your WiFi network
- Gun profiles (Bow/Airsoft, CO2 Pistol, Air Pistol, Air Gun UK, FAC)
- Projectile profiles (pellets & slugs with caliber and weight)
- Export all readings as CSV
- Reset readings, format storage, toggle test mode
- Accessible at `http://esp32.local` (mDNS) or the device's IP
- **Persistent Storage** — Gun and projectile profiles saved to LittleFS filesystem
- **Test Mode** — Generate simulated readings for display debugging
## Hardware
| Component | Specification |
|---|---|
| Microcontroller | ESP32 |
| Display | 7.5" Monochrome ePaper (UC8179 chipset, Screen Combo board ID: 502) |
| BLE Library | [NimBLEDevice](https://github.com/h2zero/NimBLE-Arduino) |
| Display Library | [TFT_eSPI](https://github.com/Bodmer/TFT_eSPI) |
| Filesystem | LittleFS |
### Pin / Board Configuration
The board type is defined in `driver.h`:
```cpp
#define BOARD_SCREEN_COMBO 502
#define USE_XIAO_EPAPER_DRIVER_BOARD
```
Ensure your `User_Setup_Select.h` (from TFT_eSPI) is configured for the **XIAO ePaper driver board** with a 7.5" UC8179 display.
## Architecture
```
┌──────────────┐ BLE ┌──────────────────┐ WiFi ┌──────────────┐
│ FX Chrono │ ◄──────────► │ ESP32 │ ◄──────────► │ Browser │
│ (v1) │ (speed │ │ (web UI) │ │
│ │ data) │ ┌──────────────┐│ │ 192.168.x.x │
│ │ │ │ ChronoBLE ││ │ esp32.local │
│ │ │ ├──────────────┤│ │ │
│ │ │ │ Display │ │ │ │
│ │ │ ├──────────────┤│ │ │
│ │ │ │ WebServer │ │ │ │
│ │ │ ├──────────────┤│ │ │
│ │ │ │ FileMgr │ │ │ │
│ │ │ └──────────────┘│ │ │
└──────────────┘ └──────────────────┘ └──────────────┘
```
### Core Modules
| Module | File(s) | Purpose |
|---|---|---|
| **Main** | `ChronoDisplay.ino` | Arduino setup/loop, orchestrates all subsystems |
| **BLE Client** | `ChronoBLE.h/.cpp` | NimBLE connection to FX Chronograph, reads speed notifications |
| **Display** | `Display.h/.cpp` | E-Paper rendering of all data fields |
| **Web Server** | `ChronoWebServer.h/.cpp` | HTTP server with embedded HTML/JS UI |
| **File Manager** | `FileManager.h/.cpp` | Persistent profile storage on LittleFS |
| **Reading Manager** | `ChronoReadingManager.h/.cpp` | Singleton that tracks all readings, profiles, and stats |
| **Profiles** | `GunProfile.h/.cpp`, `ProjectileProfile.h/.cpp`, `ChronoProfile.h/.cpp` | Gun and projectile profile data models |
| **Reading** | `ChronoReading.h/.cpp` | Individual shot reading (FPS + FPE + profile) |
## BLE Details
### FX Chronograph BLE Characteristics
The device uses a custom GATT service with the following UUIDs:
| Description | UUID |
|---|---|
| Device Info Service | `0000180A-0000-1000-8000-00805F9B34FB` |
| Chronograph Service | `00001623-88EC-688C-644B-3FA706C0BB75` |
| **Speed Characteristic** (notify) | `00001624-88EC-688C-644B-3FA706C0BB75` |
| Profile Setting Low | `00001626-88EC-688C-644B-3FA706C0BB75` |
| Battery Level | `00001627-88EC-688C-644B-3FA706C0BB75` |
| Profile Setting High | `00001628-88EC-688C-644B-3FA706C0BB75` |
Speed data is received as a 2-byte big-endian value and converted to FPS by multiplying by `0.0475111859`.
### Connection Flow
1. Start BLE scan for devices advertising the Device Info Service UUID
2. When target found, connect using cached or new BLE client
3. Subscribe to the speed characteristic for notifications
4. Write low/high speed profile bytes to configure range
5. On disconnect, return to scan state and repeat
## Web Interface
Connect to the device's WiFi network (or existing network — SSID and password are set in `ChronoWebServer.cpp`), then open:
- **mDNS**: `http://esp32.local`
- **Direct IP**: `http://<ESP32-IP>`
### Available Pages & Endpoints
| Route | Method | Purpose |
|---|---|---|
| `/` | GET | Main dashboard — select gun & projectile profiles, control panel |
| `/gunprofile` | GET | Form to add a new gun profile |
| `/gunprofile/add` | POST | Create a gun profile (name + type) |
| `/gunprofile/set` | POST | Activate a gun profile |
| `/gunprofile/remove` | POST | Delete a gun profile |
| `/projectileprofile` | GET | Form to add a projectile profile |
| `/projectileprofile/add` | POST | Create a projectile profile (name, type, caliber, weight) |
| `/projectileprofile/set` | POST | Activate a projectile profile |
| `/projectileprofile/remove` | POST | Delete a projectile profile |
| `/export` | GET | Download all readings as `data.csv` |
| `/reset` | GET | Clear all readings (shot count, stats) |
| `/format` | GET | Format LittleFS — erase all stored profiles |
| `/testmode` | GET | Toggle test mode (simulated readings every 5s) |
| `/ota` | GET | OTA firmware update page |
| `/ota` | POST | Upload and apply firmware update (.bin file) |
### Gun Profile Types
| Type | Description |
|---|---|
| 0 | Bow / Airsoft |
| 1 | CO2 Pistol |
| 2 | Air Pistol |
| 3 | Air Gun UK |
| 4 | FAC (French) |
### Display Layout
```
┌──────────────────────────────────────────────────────────────────────────────────────────┐
│ 14:56 EST ┌─────────────────────────────────┐ │
│ [Time] │ Profile: │ │
│ │ "My Rifle" [1] │ │
│ Latest Shot │ .22 Pellet │ │
│ ┌────────────────────┐ │ Cal: 6.35 │ │
│ │ │ │ Pellet 0.58g │ │
│ │ 905 fps │ └─────────────────────────────────┘ │
│ └────────────────────┘ (Right Panel) │
│ │ │ │
│ ┌─────────┐┌─────────┐┌─────────┐ ┌──────────────────────────────────────────┐ │ │
│ │Avg: 902│ │Count: 12│ │Spread: 5│ │Last Shots: │ │ │
│ └─────────┘└─────────┘└─────────┘ │ 12) 905 / 18.2 11) 904 / 18.2 ... │ │ │
│ ┌─────────┐┌─────────┐┌─────────┐ └──────────────────────────────────────────┘ │ │
│ │Low: 897│ │High: 907│ │SD: 3.2 │ │ │
│ └─────────┘└─────────┘└─────────┘ │ │
│ │ │
│ FPE: 18.2 │ │
└──────────────────────────────────────────────────────────────────────────────────────────┘
```
## Development
### Prerequisites
- [Arduino IDE](https://www.arduino.cc/en/software) or [PlatformIO](https://platformio.org/)
- ESP32 board support package
- [TFT_eSPI](https://github.com/Bodmer/TFT_eSPI) library — configure `User_Setup_Select.h` for your display
- [NimBLE-Arduino](https://github.com/h2zero/NimBLE-Arduino) library
### TFT_eSPI Configuration
In your TFT_eSPI `User_Setup_Select.h`, uncomment the XIAO ePaper 7.5" setup. The board constant used is `BOARD_SCREEN_COMBO 502` with `USE_XIAO_EPAPER_DRIVER_BOARD`.
### WiFi Configuration
Edit the SSID and password in `ChronoWebServer.cpp`:
```cpp
const char *ssid = "your-network";
const char *password = "your-password";
```
### Build & Upload
1. Configure libraries and board in Arduino IDE / PlatformIO
2. Set board to your ESP32 variant
3. Flash via USB
## Project Status
Initial development. The project compiles and runs with the following functionality:
- ✅ BLE connection to FX Chronograph v1
- ✅ Live ePaper display of shot data
- ✅ Web-based gun & projectile profile management
- ✅ CSV export of readings
- ✅ Persistent profile storage
- ✅ Test mode for display debugging
- ✅ OTA firmware updates (via web UI at /ota)
- ✅ Time synchronization via NTP
## License
[Add your license here]