Files
espnav-display/README.md
T
2026-06-18 15:18:12 +02:00

302 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Marine Navigation Display
> Waterproof marine e-ink navigation display based on the **Waveshare ESP32-S3-Zero**
> and a 4.2" monochrome e-paper screen, acting as a BLE client to the **Marine Gateway**.
---
## Hardware Bill of Materials
| Component | Model |
|---|---|
| Microcontroller | Waveshare ESP32-S3-Zero |
| Display | Waveshare 4.2" E-Ink GDEY042T81 (400×300 px) |
| Touch buttons | 3× capacitive pads on Touch pins 1, 2, 3 |
| Status LED | Built-in WS2812B NeoPixel (GPIO 21) |
| Power | 3.3 V regulated (e.g. waterproof LiPo + TP4056) |
---
## Wiring
### E-Ink Display (SPI — HSPI bus)
| ESP32-S3 GPIO | E-Ink Pin | Signal |
|---|---|---|
| 10 | CLK | SPI Clock |
| 11 | DIN | SPI MOSI |
| 9 | CS | Chip Select |
| 8 | DC | Data / Command |
| 7 | RST | Reset |
| 6 | BUSY | Busy (active LOW) |
| 3V3 | VCC | Power |
| GND | GND | Ground |
> If you rewire these pins, update the `Pins::EPD_*` constants in `include/Config.h`.
### Touch Buttons
Connect a metallic rod or pad to each touch GPIO. No pull-up or external components
are required — the ESP32-S3 native touch peripheral handles everything.
| Button | GPIO | Action |
|---|---|---|
| NEXT | Touch 1 | Next page (short press) |
| PREV | Touch 2 | Previous page (short press) |
| ACTION | Touch 3 | Force full e-ink refresh |
| NEXT + PREV | — | Hold 3 s → toggle WiFi AP mode |
---
## Project Structure
```
marine-display/
├── platformio.ini # Build system configuration
├── partitions/
│ └── custom_ota.csv # Custom flash partition table (OTA + LittleFS)
├── scripts/
│ └── gen_littlefs.py # Pre-build script (PlatformIO extra_script)
├── data/ # LittleFS root — upload with: pio run -t uploadfs
│ └── version.txt # Auto-generated at build time
├── include/
│ ├── Config.h # All constants, UUIDs, data structures
│ ├── ConfigManager.h # Persistent configuration API
│ ├── BleManager.h # BLE central client API
│ ├── DisplayManager.h # E-Ink display driver API
│ ├── WifiManager.h # WiFi AP + web server API
│ ├── TouchManager.h # Capacitive touch API
│ └── StatusLed.h # NeoPixel status LED API
└── src/
├── main.cpp # Application entry point
├── ConfigManager.cpp
├── BleManager.cpp
├── DisplayManager.cpp
├── WifiManager.cpp
├── TouchManager.cpp
└── StatusLed.cpp
```
---
## Partition Layout
| Name | Type | Size | Purpose |
|---|---|---|---|
| nvs | data/nvs | 20 KB | NimBLE bonds, Preferences |
| otadata | data/ota | 8 KB | OTA slot selector |
| app0 | app/ota_0 | 1.5 MB | Running firmware |
| app1 | app/ota_1 | 1.5 MB | OTA target partition |
| littlefs | data/spiffs | 1 MB | Config JSON + web assets |
| coredump | data/coredump | 64 KB | Crash dump |
---
## Software Architecture
```
main.cpp
├── ConfigManager LittleFS + ArduinoJson
│ └── /config.json (pages, tiles, AP credentials)
├── BleManager NimBLE-Arduino (central role)
│ ├── Scan → connect → pair → subscribe (5 characteristics)
│ ├── Notify callbacks → parse JSON → update BoatState (mutex-protected)
│ └── sendAutopilotCmd / sendAdminCmd
├── DisplayManager GxEPD2_BW
│ ├── Full refresh — page change, boot, timer (5 min)
│ └── Partial refresh — value area only, per-tile change detection
├── WifiManager ESPAsyncWebServer
│ ├── GET / → embedded HTML config page
│ ├── GET /api/config → config JSON
│ ├── POST /api/config → apply new config
│ ├── GET /api/state → live BoatState JSON
│ ├── POST /api/ble/cmd → forward BLE command
│ ├── POST /api/ble/passkey → provide BLE pairing PIN
│ └── POST /update → OTA firmware upload
├── TouchManager ESP32-S3 native touchRead()
│ └── Short press / combo detection (NEXT+PREV → AP mode)
└── StatusLed Adafruit NeoPixel
└── Colour + blink pattern encodes BLE/WiFi status
```
### Mode switching
The ESP32-S3 radio is shared between BLE and WiFi. The display operates in one
mode at a time:
```
Boot
├── NEXT+PREV held? → WiFi AP mode
└── Normal boot → BLE mode
BLE mode: BLE scanning → connect → live data display
WiFi AP mode: AP started → web server → config / OTA
Toggle at runtime: hold NEXT+PREV for 3 seconds.
```
---
## Display Layout
```
┌────────────────────┬────────────────────┐
│ ████ TILE 0 ████ │ ████ TILE 1 ████ │
│ │ │
│ 5.2 │ 47.2° │
│ kn │ │
├────────────────────┼────────────────────┤
│ ████ TILE 2 ████ │ ████ TILE 3 ████ │
│ │ │
│ 10.1 │ 85 % │
│ kn │ │
└────────────────────┴────────────────────┘
400 px wide × 300 px tall
Each tile: 200 × 150 px
Label bar: 22 px (inverted — white text on black)
Value area: 128 px tall — large 24pt font, centred
```
### Refresh strategy
| Event | Refresh type | Duration |
|---|---|---|
| Data value changed | Partial (value area only) | ~200 ms |
| Page change | Full | ~1500 ms |
| Manual (ACTION button) | Full | ~1500 ms |
| Timer (every 5 min) | Full | ~1500 ms |
---
## BLE Protocol
The display connects to the **Marine Gateway** (`MarineGateway`) as a BLE
central client. Full protocol documentation is in `BLE_Client_Documentation.md`.
### Pairing
1. The Marine Gateway displays a 6-digit PIN on its dashboard.
2. Submit the PIN via the web UI at `http://192.168.4.1/`**BLE Pairing PIN**,
or via the Serial console (planned).
3. The bond is saved; subsequent reconnections are automatic.
### Subscribed characteristics
| Service | Characteristic | Update rate |
|---|---|---|
| Navigation | NavData | 1 Hz |
| Wind | WindData | 1 Hz |
| Autopilot | AutopilotData | 1 Hz |
| Sail Performance | PerformanceData | 1 Hz |
| Admin | AdminData | 1 Hz |
---
## Building and Flashing
### Requirements
- [PlatformIO Core](https://docs.platformio.org/en/latest/core/installation/) ≥ 6.x
- USB-C cable to the ESP32-S3-Zero (native USB CDC)
### First flash
```bash
# Clone / open the project
cd marine-display
# Build and flash firmware
pio run -t upload
# Upload the LittleFS filesystem (web UI assets + default config placeholder)
pio run -t uploadfs
```
### OTA update (subsequent flashes)
1. Ensure the device is in **WiFi AP mode** (hold NEXT+PREV 3 s or at boot).
2. Connect your computer to the `MarineDisplay` WiFi network.
3. Open `http://192.168.4.1/` in a browser.
4. Scroll to **Firmware Update**, select the `.bin` file, click **Flash Firmware**.
The firmware binary is at `.pio/build/esp32s3_marine_display/firmware.bin` after a build.
Alternatively, configure OTA upload in `platformio.ini`:
```ini
upload_protocol = espota
upload_port = 192.168.4.1
```
Then use `pio run -t upload` over WiFi.
---
## Configuration Web UI
Connect to `MarineDisplay` WiFi (default password: `marine123`) and open
`http://192.168.4.1/` in a browser.
### Tile configuration
Each display page has 4 tiles arranged in a 2×2 grid. For each tile, select:
- **Data Field** — which BLE data to display (SOG, TWA, VMG, Depth, etc.)
- **Label override** — custom short label (max 15 chars); leave blank for auto
Up to **8 pages** can be configured. Navigate with NEXT/PREV buttons.
### Gateway control
From the web UI you can:
- Switch the **Marine Gateway** to STA mode (connect it to your boat WiFi)
- Restart the Marine Gateway remotely
- Submit a BLE pairing PIN
---
## Customisation
### Adding a new data field
1. Add an entry to the `DataField` enum in `include/Config.h`.
2. Add the field to `fieldName()` and `fieldUnit()` inline functions.
3. Add the field extraction in `DisplayManager::_fieldToString()`.
4. Add parsing in the appropriate `BleManager::_parseXxx()` method and struct.
### Changing the display model
Replace `GxEPD2_420_GDEY042T81` in `include/DisplayManager.h` with the correct
GxEPD2 model class for your panel. Update `DISPLAY_WIDTH` / `DISPLAY_HEIGHT` in
`platformio.ini` accordingly.
### Changing pin assignments
All pin constants live in `include/Config.h` under the `Pins::` namespace, or
can be overridden via `build_flags` in `platformio.ini`.
---
## Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
| Display shows only splash | BLE not connected | Wait for scan; check gateway is advertising |
| Values show `---` | NMEA data stale (>10 s) | Check gateway serial input |
| Ghosting on display | Partial refresh accumulation | Press ACTION button for full refresh |
| Can't see web UI | Not in AP mode | Hold NEXT+PREV 3 s |
| OTA fails | Wrong .bin file | Use `firmware.bin` from `.pio/build/` |
| Touch not responding | Threshold too high/low | Adjust `Touch::THRESHOLD` in `Config.h` |
| BLE bond stale | Old bond data | Clear NVS: `pio run -t erase` then re-flash |
---
## Licence
MIT — see `LICENSE` file.