Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
260 changes: 84 additions & 176 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,209 +1,117 @@
# Plane Radar
# ESP32 Plane Radar & Aviator Chronometer (2.1" Round Display Edition)

<img width="800" height="450" alt="plane-radar" src="https://github.com/user-attachments/assets/716d0992-dab8-47ba-8f1a-2aec7f607419" />
<p align="center">
<img width="380" alt="ESP32 Plane Radar Desktop Console" src="images/plane_radar_console.png" />
</p>

**3D printed case (STL + assembly):** [MakerWorld](https://makerworld.com/en/models/2872376-esp32-plane-radar-live-ads-b-on-a-round-display#profileId-3207083) · **Firmware:** [Releases](https://github.com/MatixYo/ESP32-Plane-Radar/releases)
Live **ADS-B Flight Radar** & **Aviator Chronometer** desktop console running on an **ESP32-C3 Super Mini**, featuring a **2.1″ 360×360 round SPI TFT display (GC9B72)**, an **EC11 rotary encoder**, and a custom **3D-printable 18° tilted desk console enclosure**.

Firmware for an **ESP32-C3 Super Mini** and a **1.28″ round GC9A01** display (240×240). Shows a circular **ADS-B radar** around your configured location, with **WiFiManager** for first-time setup.
---

## What it does
## Key Features

1. **Wi‑Fi setup** (if needed) — captive portal on AP **`PlaneRadar-Setup`**
2. **Radar** — live aircraft from [adsb.fi](https://opendata.adsb.fi/) on a sonar-style grid
- **2.1″ Round 360×360 GC9B72 SPI Display**: High-resolution, vibrant circular display driven by [LovyanGFX](https://github.com/lovyan03/LovyanGFX) for buttery-smooth 40 MHz SPI DMA rendering.
- **Live ADS-B Flight Tracking**: Real-time aircraft tracking from [adsb.fi](https://opendata.adsb.fi/) plotted on a circular aviation sonar grid with altitude, speed vector, callsign, and aircraft type.
- **EC11 Rotary Encoder Navigation**:
- **Rotate**: Smoothly adjust radar zoom range (5, 10, 15, 25 km) or browse individual aircraft targets.
- **Click**: Cycle between **Radar Mode**, **Aircraft Details Screen**, and **Aviator Chronometer Clock Mode**.
- **Aviator Chronometer Mode**: Authentic aviation clock face with date window, digital time, second hand, and automatic NTP internet time synchronization (CET/CEST supported).
- **Wi‑Fi Setup & Configuration Portal**: Built-in captive portal (`PlaneRadar-Setup` AP / `http://plane-radar.local`) to configure Wi-Fi, radar center coordinates, units (km / miles), and runway overlays.
- **3D Printable Desktop Enclosure**: Fully parametric OpenSCAD model (`cad/plane_radar_case.scad`) and ready-to-print STL files (`cad/plane_radar_case-front.stl`, `cad/plane_radar_case-back.stl`) optimized for face-down FDM printing without supports.

After Wi‑Fi is saved, the device reconnects automatically; the radar runs in the main loop with periodic ADS-B updates (~5 s).
---

## Controls (BOOT, GPIO 9, active LOW)
## Hardware & Wiring

| Action | Effect |
|--------|--------|
| **Short tap** | Cycle range preset (5 → 10 → 15 → 25 km); saved to flash |
| **Hold 3 s** | Clear Wi‑Fi, location, and units; reboot into setup portal |
### Components

During setup you can also hold BOOT at power-on to force a credential reset (same as the long press).
| Component | Description |
|-----------|-------------|
| **Microcontroller** | ESP32-C3 Super Mini |
| **Display** | 2.1″ Round 360×360 TFT LCD (GC9B72 driver, 10-pin SPI) |
| **Controls** | EC11 Rotary Encoder with push button (e.g. KY-040 module) |
| **Enclosure** | 3D-printed case (OpenSCAD / STL included in `cad/`) |

## Wi‑Fi setup portal
### Pinout Mapping (ESP32-C3 Super Mini)

**First-time setup** (no saved Wi‑Fi):
#### Display (GC9B72 2.1" Round 10-Pin SPI)
| Display Pin | ESP32-C3 GPIO | Notes |
|-------------|---------------|-------|
| **VCC / VDD** | **3V3** | 3.3V Power |
| **GND** | **GND** | Ground |
| **SCL (SCLK)** | **GPIO 4** | SPI Clock |
| **SDA (MOSI)** | **GPIO 3** | SPI Data |
| **RST (RES)** | **GPIO 0** | Display Reset |
| **DC** | **GPIO 10** | Data / Command |
| **CS** | **GPIO 1** | Chip Select |
| **BL (LEDA)** | **3V3** (or NC) | Backlight Power |

1. Connect to **`PlaneRadar-Setup`**
2. Open **`http://plane-radar.local`** (preferred) or **`http://192.168.4.1`** — both are shown on the yellow setup screen; captive portal may open automatically
3. Set home Wi‑Fi, then save
#### Rotary Encoder (EC11)
| Encoder Pin | ESP32-C3 GPIO | Notes |
|-------------|---------------|-------|
| **CLK (A)** | **GPIO 5** | Quadrature Channel A |
| **DT (B)** | **GPIO 6** | Quadrature Channel B |
| **SW (Button)**| **GPIO 7** | Push Button (Active LOW) |
| **GND** | **GPIO 8** | Virtual GND (driven LOW by firmware) |
| **+ (VCC)** | **GPIO 2** | Virtual 3.3V VCC (driven HIGH by firmware) |

**Reconfigure anytime** (after the device is on your network):
#### System Controls
| Control | ESP32-C3 GPIO | Action |
|---------|---------------|--------|
| **BOOT Button** | **GPIO 9** | Hold 3 s to reset Wi-Fi credentials & launch setup portal |

1. Open **`http://plane-radar.local`** or **`http://<device-ip>`** (e.g. from your router or serial log at boot)
2. Change Wi‑Fi, location, units, or runway overlay; save
---

The same portal runs on the setup AP and on the device’s LAN IP while connected to Wi‑Fi. mDNS hostname is `plane-radar` → **plane-radar.local** (`kPortalHostname` in `config.h`). Some clients resolve `.local` slowly; use the IP if needed.
## Controls & Operating Modes

**Custom fields** (stored in NVS):
| Control | Action | Effect |
|---------|--------|--------|
| **Rotary Knob** | **Turn** | Adjust radar range (5 ↔ 10 ↔ 15 ↔ 25 km) or browse aircraft |
| **Rotary Knob** | **Click** | Switch display mode: **Radar** $\rightarrow$ **Aircraft Details** $\rightarrow$ **Chronometer** |
| **BOOT (GPIO 9)** | **Hold 3 s** | Reset Wi-Fi configuration and reboot into captive setup portal |

| Field | Purpose |
|-------|---------|
| **Latitude / Longitude** | Radar center and ADS-B query position (defaults in `config.h` until set) |
| **Display distances in miles** | Ring scale label in **mi** instead of **km** (e.g. `6mi` vs `10km`) |
| **Show airport runways** | Major-airport runway overlay on the radar (off to hide) |
---

After a reset, the device reboots and shows the setup screen immediately (no “Connecting” loop on stale credentials).
## Wi‑Fi Setup Portal

## Radar display
1. On first boot (or after holding BOOT for 3 s), connect your phone or PC to the Wi-Fi network **`PlaneRadar-Setup`**.
2. A captive portal should automatically open. If not, browse to **`http://plane-radar.local`** or **`http://192.168.4.1`**.
3. Select your home Wi-Fi network, enter the password, and configure:
- **Latitude / Longitude**: Your home radar center coordinates.
- **Units**: Distances in kilometers (`km`) or miles (`mi`).
- **Runways Overlay**: Toggle major airport runway strips on/off.
4. Save and restart. The radar will automatically connect and begin tracking flights.

### Grid
---

- Dark blue background, subdued green rings and crosshairs
- White **N / S / E / W** at the bezel; range label on the **east** spoke (ring 3 = ¾ of outer radius)
- White center dot
## 3D Printed Console Case

Layout and colors: `include/ui/radar_theme.h`.
The repository includes a custom parametric console enclosure in the `cad/` directory:

### Range presets
- **`cad/plane_radar_case.scad`**: Parametric OpenSCAD source file.
- Supports `part = "front"`, `part = "back"`, and `part = "test_bezel"`.
- **`cad/plane_radar_case-front.stl`**: Main console body with 18° front tilt, internal 2.0mm display collar, locating pin studs, snap-fit tabs, and sliding rails for ESP32-C3. Designed to print face-down on a textured PEI plate without supports.
- **`cad/plane_radar_case-back.stl`**: Recessed rear cover plate with ventilation louvers, USB-C cutout, and countersunk M2.5/M3 screw holes.

| Ring 3 label | Outer radius (aircraft scale) |
|------------|-------------------------------|
| 5 km / 3 mi | ~6.7 km |
| 10 km / 6 mi | ~13.3 km (default) |
| 15 km / 9 mi | ~20 km |
| 25 km / 16 mi | ~33.3 km |
---

Preset and miles/km choice persist across reboot (`planeradar` NVS namespace).
## Building and Flashing

### Runways

- Major airports from OurAirports (`large_airport`); all open runway strips in range (helipads excluded)
- Teal runway lines with one ICAO label per airport (e.g. `KJFK`); toggle in the Wi‑Fi setup portal
- Update the embedded list: `python3 scripts/build_large_airports.py`

### Aircraft

- **Inside the outer ring** — red heading triangle, magenta speed vector (clipped at the ring), callsign / type / altitude tags
- **Outside the ring** (still within ADS-B fetch) — small **red dot on the screen rim** at the correct bearing (direction cue; not distance-accurate past the ring)
- **Tags** — placed toward the **center**: west (left) → tag on the **right** of the symbol; east (right) → tag on the **left**

As range decreases (or aircraft approach), targets move inward; beyond-ring dots become full symbols when they cross the outer ring.

### ADS-B

- Source: `https://opendata.adsb.fi/api/v3/`
- Fetch radius: `ui::radar::fetchRadiusKm()` — scales with the active preset to roughly the screen edge (so rim dots have data)
- Poll interval: `kAdsbFetchIntervalMs` (5 s) in `config.h`
- Ground aircraft hidden by default (`kAdsbShowGroundAircraft`)

## Configuration

Edit **`include/config.h`** for hardware and behavior:

| Area | Keys / notes |
|------|----------------|
| Portal | `kPortalApName`, `kPortalIp`, `kPortalHostname` / `kPortalHostUrl` (mDNS; needs `-DWM_MDNS` in `platformio.ini`) |
| Wi‑Fi timing | connect attempts, reconnect grace, portal timeout (`0` = no timeout) |
| BOOT | `kBootPin`, `kBootResetHoldMs`, `kBootTapMinMs` |
| Display SPI | pins, `kDisplayInvert`, `kDisplayRgbOrder`, `kDisplaySpiWriteHz` |
| Default location | `kDefaultRadarLat`, `kDefaultRadarLon` (until portal overrides) |
| ADS-B | `kAdsbFetchIntervalMs`, `kAdsbShowGroundAircraft` |

Range presets: `include/ui/radar_range.h` (`kRangePresets`).

## Project layout

```
include/
config.h
hardware/
lgfx_config.hpp
display.h
display_font.h
data/
large_airports.h
ui/
radar_theme.h
radar_range.h
radar_display.h
runway_overlay.h
status_screens.h
services/
wifi_setup.h
radar_location.h
adsb_client.h
data/
ui_font.vlw — embedded smooth UI font (Noto Sans Bold)
scripts/
build_large_airports.py
src/
main.cpp
data/
large_airports_data.cpp
hardware/
ui/
services/
```

## Wiring (GC9A01 ↔ ESP32-C3 Super Mini)

| Display | ESP32-C3 |
|---------|----------|
| VCC | 3V3 |
| GND | GND |
| RST | GPIO **0** |
| CS | GPIO **1** |
| DC | GPIO **10** |
| SDA (MOSI) | GPIO **3** |
| SCL (SCLK) | GPIO **4** |
| BOOT (user) | GPIO **9** |

## Build
### PlatformIO

```bash
pio run -t upload
pio device monitor
```

- PlatformIO env: **`supermini`**
- Serial: **115200** baud
- USB CDC on boot enabled in `platformio.ini` for the Super Mini
# Build and upload firmware to ESP32-C3 Super Mini
pio run -e supermini -t upload

### Web-flashable release image

Single `.bin` for [esptool-js](https://espressif.github.io/esptool-js/) and similar tools (ESP32-C3, 4 MB, flash at **0x0**):

```bash
chmod +x scripts/merge-firmware.sh # once
./scripts/merge-firmware.sh
```

Writes `release/plane-radar-merged.bin`. Skip rebuild if firmware is already built:

```bash
./scripts/merge-firmware.sh --no-build
```

Or via PlatformIO only (output: `.pio/build/supermini/firmware-merged.bin`):

```bash
pio run -e supermini
pio run -t merge -e supermini
```

Put the board in download mode (hold **BOOT**, tap **RESET**), then flash with Chrome/Edge over USB.

### CI and releases (GitHub Actions)

| Workflow | When | Output |
|----------|------|--------|
| [Build](.github/workflows/build.yml) | Push / PR to `main` | Artifact `plane-radar-supermini` (merged + split `.bin` files, ~90 days) |
| [Release](.github/workflows/release.yml) | Git tag `v*` (e.g. `v1.0.0`) | GitHub Release asset `plane-radar-v1.0.0.bin` + `.sha256` |

To ship a version users can download:

```bash
git tag v1.0.0
git push origin v1.0.0
# Open serial monitor (115200 baud)
pio device monitor
```

The release workflow builds firmware in CI and attaches the merged image to the release. Download from **Releases** on GitHub, then flash at **0x0** (ESP32-C3, 4 MB).
---

## Dependencies
## Credits & Acknowledgments

- [LovyanGFX](https://github.com/lovyan03/LovyanGFX)
- [WiFiManager](https://github.com/tzapu/WiFiManager)
- [ArduinoJson](https://github.com/bblanchon/ArduinoJson)
- Based on the original [ESP32-Plane-Radar](https://github.com/MatixYo/ESP32-Plane-Radar) by [MatixYo](https://github.com/MatixYo).
- Flight data provided by [adsb.fi](https://opendata.adsb.fi/).
- Graphics engine powered by [LovyanGFX](https://github.com/lovyan03/LovyanGFX).
- Airport database sourced from [OurAirports](https://ourairports.com/).
Binary file added cad/2.1 inch display - dimensions.avif
Binary file not shown.
Binary file added cad/plane_radar_case-back.stl
Binary file not shown.
Binary file added cad/plane_radar_case-front.stl
Binary file not shown.
Loading