A Raspberry Pi flight tracker that displays live ADS-B flight data on a Waveshare 2.4" LCD. It reads from the locally running FlightRadar24 "Build Your Own" receiver software and enriches the data with free external APIs — no FR24 subscription or API key required.
- Live ADS-B data — reads directly from the local dump1090/fr24feed JSON endpoint on your Pi
- Closest aircraft tracking — automatically finds and displays the nearest aircraft within a configurable radius
- Rich flight info — airline name, aircraft model, registration, callsign, origin, destination, altitude, vertical speed, ground speed, and heading
- Aircraft photos — fetched from Planespotters.net by ICAO hex code
- Smart enrichment — aircraft metadata and route data from adsbdb.com (no API key needed)
- Offline name lookup — airport and airline names from OpenFlights data, downloaded once and refreshed weekly
- In-memory cache — minimises API calls; aircraft metadata cached 24 h, routes 6 h, photos 24 h
- Graceful degradation — if any enrichment API is unavailable, raw ADS-B codes are shown rather than crashing
- Auto-install — requirements installed automatically from
requirements.txton every run - Auto-venv — re-executes itself under the local
.venvPython if launched with the system Python
┌─────────────────────────────────────────────────────────┐
│ Raspberry Pi │
│ │
│ RTL-SDR dongle -> fr24feed/dump1090 │
│ │ │
│ ADS-B JSON (HTTP URL or local file path) │
│ │ │
│ fr24-display.py │
│ │ │
│ ┌─────────────────┼─────────────────┐ │
│ ▼ ▼ ▼ │
│ adsbdb.com airport-data.com OurAirports │
│ (reg/type/route) (photos/info) (airports) │
│ │ │ │ │
│ └─────────────────┴─────────────────┘ │
│ │ │
│ Waveshare 2.4" LCD │
└─────────────────────────────────────────────────────────┘
| Source | Data provided | Cache TTL |
|---|---|---|
| Local ADS-B (HTTP or file) | Position, altitude, speed, heading, callsign | Real-time (polled every REFRESH_RATE seconds) |
| adsbdb.com | Registration, aircraft type, operator, origin & destination airports | 24 h (aircraft), 6 h (route) |
| airport-data.com | Aircraft photographs; model name fallback for unknown type codes | 24 h |
| OurAirports | Full airport names (actively maintained community dataset) | Downloaded to data/, refreshed weekly |
| Built-in table | ICAO type code → model name (e.g. B738 → Boeing 737-800) |
Static |
┌──────────────────────────────────────────┐ ← 0 px
│ │
│ Aircraft photo (full width) │ 77 px
│ │
├──────────────────────────────────────────┤
│ British Airways BA0117 │ +25 px (font 20 / 18)
│ Boeing 737-800 G-EUPT │ +18 px (font 16)
├──────────────────────────────────────────┤
│ London Heathrow Airport │ +22 px (font 18, red)
│ New York JFK Airport │ +22 px (font 18, green)
├──────────────────────────────────────────┤
│ 35,000 ft ^ 200 fpm │ +22 px (font 18)
│ 450 kts Track 270° │ +22 px (font 18)
├──────────────────────────────────────────┤
│ 12.5 miles away, bearing 270° │ +23 px (font 18, amber)
└──────────────────────────────────────────┘ ← 240 px
Vertical speed indicator: ^ climbing, v descending, ~ level (within ±50 fpm).
- Raspberry Pi (any model with 40-pin GPIO header — tested on Pi 3/4/Zero 2 W)
- RTL-SDR USB dongle (e.g. RTL2832U) with 1090 MHz antenna
- Waveshare 2.4" LCD HAT (ST7789 driver, 240 × 320 px)
- MicroSD card (8 GB+) running Raspberry Pi OS Lite or Desktop
- Internet connection for first-run data download and API enrichment
The display uses the SPI0 bus. Connect it to your Raspberry Pi's 40-pin GPIO header as follows:
Waveshare 2.4" LCD Raspberry Pi 40-pin header
───────────────── ──────────────────────────
VCC ────────────────────── Pin 1 (3.3 V)
GND ────────────────────── Pin 6 (GND)
DIN ────────────────────── Pin 19 (GPIO 10 / SPI0 MOSI)
CLK ────────────────────── Pin 23 (GPIO 11 / SPI0 SCLK)
CS ────────────────────── Pin 24 (GPIO 8 / SPI0 CE0)
DC ────────────────────── Pin 22 (GPIO 25)
RST ────────────────────── Pin 13 (GPIO 27)
BL ────────────────────── Pin 12 (GPIO 18 / PWM0)
Raspberry Pi GPIO header reference (odd pins on left, even on right):
3V3 [ 1] [ 2] 5V
GPIO2 [ 3] [ 4] 5V
GPIO3 [ 5] [ 6] GND ◄── GND
GPIO4 [ 7] [ 8] GPIO14
GND [ 9] [10] GPIO15
GPIO17 [11] [12] GPIO18 ◄── BL
GPIO27 [13] [14] GND
GPIO22 [15] [16] GPIO23
3V3 [17] [18] GPIO24
GPIO10 [19] [20] GND
GPIO9 [21] [22] GPIO25 ◄── DC
GPIO11 [23] [24] GPIO8
GND [25] [26] GPIO7
GPIO0 [27] [28] GPIO1
GPIO5 [29] [30] GND
GPIO6 [31] [32] GPIO12
GPIO13 [33] [34] GND
GPIO19 [35] [36] GPIO16
GPIO26 [37] [38] GPIO20
GND [39] [40] GPIO21
◄── Pin 1 (3V3) ── VCC
◄── Pin 19 (MOSI) ── DIN
◄── Pin 23 (SCLK) ── CLK
◄── Pin 24 (CE0) ── CS
◄── Pin 13 (GPIO27) ── RST
Note: If your display module has a HAT form factor it will plug directly onto the GPIO header — no individual wiring needed. Check your specific Waveshare product page to confirm.
Follow the FlightRadar24 Build Your Own guide to install and configure fr24feed and dump1090 on your Pi. Once complete, verify the local feed is working.
If your setup exposes a web interface (the default for fr24feed/dump1090):
curl http://localhost:8080/data/aircraft.json | python3 -m json.tool | head -30If you are running dump1090-mutability or dump1090-fa, the JSON is written directly to a file instead:
# dump1090-mutability
cat /run/dump1090-mutability/aircraft.json | python3 -m json.tool | head -30
# dump1090-fa (FlightAware)
cat /run/dump1090-fa/aircraft.json | python3 -m json.tool | head -30Either way, you should see a JSON response with an aircraft array.
sudo raspi-config
# Interface Options → SPI → Enable
sudo rebootVerify SPI is enabled after reboot:
ls /dev/spidev0.*
# Should show: /dev/spidev0.0 /dev/spidev0.1sudo apt update
sudo apt install -y python3-pip python3-venv python3-dev libopenblas-dev libjpeg-devcd /home/pi
git clone https://github.com/timhanley/fr24-display.git
cd fr24-displaypython3 -m venv .venvPython packages are installed automatically on first run, but you can also pre-install them:
.venv/bin/pip install -r requirements.txtCopy the example file and edit it:
cp .env.example .env
nano .env# Your receiver location (from Google Maps — right-click → copy coordinates)
LAT=your_latitude_here
LON=your_longitude_here
# Search radius in kilometres
RADIUS_KM=50
# Local ADS-B data source — either an HTTP URL or a file path:
# HTTP (fr24feed / dump1090 with web interface):
ADSB_URL=http://localhost:8080/data/aircraft.json
# File path (dump1090-mutability):
# ADSB_URL=/run/dump1090-mutability/aircraft.json
# File path (dump1090-fa / FlightAware):
# ADSB_URL=/run/dump1090-fa/aircraft.json
# Seconds between display updates (minimum 15 recommended)
REFRESH_RATE=30chmod +x fr24-display.py
./fr24-display.pyOn first run the script will:
- Install any missing Python packages
- Download
airports.csvfrom OurAirports (~7 MB) - Start polling your local ADS-B feed
Create a service file:
sudo nano /etc/systemd/system/fr24-display.service[Unit]
Description=FR24 Flight Display
After=network-online.target fr24feed.service
Wants=network-online.target
StartLimitIntervalSec=0
[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/fr24-display
ExecStart=/home/pi/fr24-display/.venv/bin/python /home/pi/fr24-display/fr24-display.py
Restart=on-failure
RestartSec=10
MemoryMax=1G
OOMPolicy=stop
[Install]
WantedBy=multi-user.target
User=pi— Replacepiwith your actual username if you set a different one during Raspberry Pi OS setup (newer images no longer default topi). Likewise update the twoWorkingDirectory/ExecStartpaths to match.
StartLimitIntervalSec=0— Disables systemd's crash-loop protection (default: give up after 5 restarts in 10s). Without this, a burst of early failures (e.g. an SPI init race right after boot) can leave the unit permanentlyfailedwith no further restart attempts — the exact symptomRestart=on-failurealone is meant to prevent.
MemoryMax/OOMPolicy=stop— Caps the service's memory and lets systemd's cgroup-aware OOM handling stop and restart it cleanly if memory ever runs away, instead of the kernel's global OOM killer picking a victim process on this shared, memory-constrained Pi (it could just as easily killdump1090orfr24feedinstead).
After=fr24feed.service— This dependency only applies if you are using the FR24 Build Your Own software. If you are running standalonedump1090instead, replace it withdump1090.service(or remove it entirely — the script will simply retry on the next poll cycle if the feed isn't ready yet).
Enable and start the service:
sudo systemctl daemon-reload
sudo systemctl enable fr24-display.service
sudo systemctl start fr24-display.serviceCheck status and logs:
sudo systemctl status fr24-display.service
sudo journalctl -u fr24-display.service -f| Symptom | Likely cause | Fix |
|---|---|---|
No aircraft nearby on screen |
ADS-B feed not reachable or radius too small | Check curl $ADSB_URL returns data; increase RADIUS_KM |
ADS-B fetch failed in logs |
dump1090/fr24feed not running | sudo systemctl status fr24feed |
| Display stays blank / white | SPI not enabled or wiring error | Re-check raspi-config SPI setting and wiring table above |
Display init failed |
GPIO/SPI permissions | Run as pi user or add user to gpio and spi groups: sudo usermod -aG gpio,spi pi |
| Airport names showing as IATA codes | OurAirports download failed at startup | Check internet connection; file saves to data/ and retries weekly |
| Wrong origin or destination shown | adsbdb stores historical callsign→route associations; callsigns are reused across seasons | No fix — upstream data limitation; primary flight data is still correct |
| Photos not showing | airport-data.com API unreachable | Expected occasionally; noimage.png is shown as fallback |
pip install slow on every start |
Normal on first run only | Once packages are installed in .venv subsequent installs are instant |
fr24-display/
├── fr24-display.py Main script
├── requirements.txt Python dependencies
├── .env Configuration (not committed)
├── .gitignore
├── README.md
├── Font/
│ └── helvetica.ttf Display font
├── images/
│ ├── noimage.png Fallback when no photo available
│ └── error.png Shown when no aircraft detected
├── lib/
│ ├── LCD_2inch4.py Waveshare display driver
│ ├── lcdconfig.py SPI/GPIO base class
│ └── __init__.py
└── data/ Auto-created on first run
└── airports.csv OurAirports data (refreshed weekly)
- OurAirports — airport data
- adsbdb.com by @mrjackwills — free aircraft and route lookup API
- airport-data.com — aircraft photo and info API
- FlightRadar24 — Build Your Own ADS-B receiver software
- Waveshare — LCD display and driver library

