3D printed case (STL + assembly): MakerWorld · Firmware: Releases
Firmware for an ESP32-C3 board (either an ESP32-C3 Super Mini or a Seeed Studio XIAO ESP32-C3) 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.
Pick your board with the matching PlatformIO env: supermini or xiao (pin mapping is selected automatically via build-time defines — see include/config.h).
- Wi‑Fi setup (if needed) — captive portal on AP
PlaneRadar-Setup - Radar — live aircraft from adsb.fi on a sonar-style grid
After Wi‑Fi is saved, the device reconnects automatically; the radar runs in the main loop with periodic ADS-B updates (~5 s).
| 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 |
During setup you can also hold BOOT at power-on to force a credential reset (same as the long press).
- Connect to
PlaneRadar-Setup - Open
http://plane-radar.local(preferred) orhttp://192.168.4.1— both are shown on the yellow setup screen; captive portal may open automatically - Set home Wi‑Fi, then save
mDNS hostname is configured in config.h as kPortalHostname (plane-radar → plane-radar.local on the setup AP). Some phones resolve .local slowly; use the IP if needed.
Custom fields (stored in NVS):
| 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) |
After a reset, the device reboots and shows the setup screen immediately (no “Connecting” loop on stale credentials).
- 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
Layout and colors: include/ui/radar_theme.h.
| 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).
- 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.
- 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) inconfig.h - Ground aircraft hidden by default (
kAdsbShowGroundAircraft)
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).
include/
config.h
hardware/
lgfx_config.hpp
display.h
display_font.h
ui/
radar_theme.h
radar_range.h
radar_display.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)
src/
main.cpp
hardware/
ui/
services/
| 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 |
Power the display from 3V3, not 5V. The XIAO's onboard BOOT button (GPIO 9) is used for range cycling / Wi‑Fi reset — no external button needed.
| Display | XIAO pin | GPIO |
|---|---|---|
| VIN | 3V3 | — |
| GND | GND | — |
| SCL (SCLK) | D8 | 8 |
| SDA (MOSI) | D10 | 10 |
| RES | D3 | 5 |
| DC | D1 | 3 |
| CS | D0 | 2 |
| BLK (backlight) | D2 | 4 |
BLK is driven by a GPIO (PWM), so brightness control works. If the screen is dark at full brightness, set cfg.invert = true in the Light_PWM block of include/hardware/lgfx_config.hpp.
pio run -t upload -e supermini # ESP32-C3 Super Mini
pio run -t upload -e xiao # Seeed XIAO ESP32-C3
pio device monitor- PlatformIO envs:
superminiandxiao(choose with-e) - Serial: 115200 baud
- USB CDC on boot enabled in
platformio.inifor both boards
Single .bin for esptool-js and similar tools (ESP32-C3, 4 MB, flash at 0x0):
chmod +x scripts/merge-firmware.sh # once
./scripts/merge-firmware.shWrites release/plane-radar-merged.bin. Skip rebuild if firmware is already built:
./scripts/merge-firmware.sh --no-buildOr via PlatformIO only (output: .pio/build/supermini/firmware-merged.bin):
pio run -e supermini
pio run -t merge -e superminiPut the board in download mode (hold BOOT, tap RESET), then flash with Chrome/Edge over USB.
| Workflow | When | Output |
|---|---|---|
| Build | Push / PR to main |
Artifacts plane-radar-supermini and plane-radar-xiao (merged + split .bin files, ~90 days) |
| Release | 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:
git tag v1.0.0
git push origin v1.0.0The 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).