When I sit at my living room table I can see wonderful big airplanes in the final approach to Zurich (ZRH) airport or ascending to a far destination: Airbus A380 or Boeing B777 are ingenious proof of what we are capable to design and build. Quite often when I have visitors I start flightradar24 to get more information about the airplanes we see. But wouldn’t it be nice if this information would just be there, anytime I’m curious – without starting an app on my smart phone? Since I’m playing a lot with the ESP8266 it was an obvious choice to build such a device by myself. I actually had already built one a while back with the Flight-O-Matic but the setup was quite complicated and the project was dormant for a while. Until I recently discovered a service that provides exactly the information I needed and is free to use as well.
What you’ll need
In order to get this project running you’ll need the following list of hardware:
![]() | NodeMCU ESP8266 module or Wemos D1 Mini |
![]() | 0.96" SSD1306 OLED display |
![]() | A few connectors and USB Wire |
![]() | Or order a complete starter kit for USD $19.90 (incl. shipping) from my shop and support this blog |
Depending on the coverage of adsbexchange.com feeders in your area you might also buy the following items:
- Raspberry Pi (Model 3 recommended but also works with older versions and probably Zero)
- RTL-SDR dongle for receiving the ADS-B signal
- Micro SD card for Raspberry Pi (for Model 3 or with adapter, depending on your RasPi model)
The Service – ADSBExchange
At the core of this project is the excellent service provided by Dan Streufert and countless people feeding live transponder signals into it: http://adsbexchange.com. From what I understand it is built on top of the http://www.virtualradarserver.co.uk/ project and lets you query live position data based on location, distance to a point, altitude etc and returns a JSON object which you can process in your code. Please note: in order to keep this service free-to-use Dan depends on your support, either by donating money to cover the server hosting costs or by providing your local data to improve coverage.
Note, this step is optional: When I first checked the coverage of the Zurich airport wasn’t so great so I decided to reactivate my RTL-SDR DVB-T dongle (see posts here, here and here) and contribute live data to adsbexchange.com. If the coverage in your area is insufficient consider to setup such a feeder as well.
Once you have the hardware (see above, Raspberry Pi and RTL-SDR dongle) you can either do the setup manually or take a short cut by becoming a flightaware feeder and using their ready-to-feed sd-card image called PiAware: http://flightaware.com/adsb/piaware/install. Once you have done that you have to setup your PiAware instance to also feed to adsbexchange.com by running a script provided by Dan: http://www.adsbexchange.com/how-to-feed/
The Plane Spotter Hardware
Once you are sure you have a good coverage of your area of interest you can start to get to the actual plane spotter hardware. I recommend to either use the components provided by my IoT Starter Kit ($USD 19.90 incl. free shipping from China) or to get the setup I described in this post using the Wemos D1 Mini which requires soldering but yields a very compact setup. The wiring is described here.
The Code
In my recent ESP8266 projects I started switching to the PlatformIO IDE since it is a lot more convenient to use compared to the Arduino IDE: automatic library dependency management, better coding support in the editor and great Travis CI and even Continuous Delivery support. So please make sure that you have a running IDE before you get started with the code. Once you have that ready please checkout the code from my github repository.
Now the most important part is to configure the QUERY_STRING variable in the main.cpp file:
const String QUERY_STRING = “lat=47.424341887&lng=8.568778038&fDstL=0&fDstU=10&fAltL=0&fAltL=1500&fAltU=10000”;
For a detailed description please checkout the documentation of the virtual radar server. What my example does is to filter out all aircrafts which are not within 10km from a location south of the runway and above 1500 feet (I don’t care about landed airplanes) or above 10000 feet (I also don’t care about transit airplanes). There are many options to adapt this query to your needs, so please carefully read the afore mentioned documentation. Once you are ready with the query you can flash the firmware on your ESP8266 chip.
First Run & Adapting it
Since the ESP8266 is fetching the data from the internet you’ll have to connect the module to the internet. My code is using the excellent WifiManager library. If your ESP8266 cannot connect to a (known) access point it will start an AP by itself and allow you to connect through your Wifi settings to it. A captive portal window opens and lets you select the correct SSID and enter the password. It then stores the Wifi settings on flash and will use it in the future.
If everything works you can go on and change the way the data is displayed or extract more data from the adsbexchange json object. It would be great if you could share your results with me either here in the comments or on Twitter. I’ll be happy to share it with the community.
Summary
You can build a cute little plane spotting tool with just a few components for under $20 without much work. If the coverage of your area on adsbexchange is poor then you could become a data feeder for about $50.- more (Raspberry Pi + RTL-SDR Dongle). Playing with the real-time data is fun and can be a very rewarding weekend project!

Great project! Have all components and already suceeded ploting data from sdr but esp+oled always feel magical 😉
One question, you have mentioned wemos d1 mini, what driver are you using? my existing doesnt work with it although it uses ch340g (it works with witty)?
Great project, I made a small copy under Arduino IDE as I have problems starting up with platform IO. now adding the displayfunctions… I also ordered a magnetometer, my final idea is to point the device in the direction of a plane that I can see and that the display shows me the info on that plane. Do you think that is feasible?
Hi Hans. I guess the magnetometer would be a very cool addition to the orginal project and should be very much feasible. Maybe even add a GPS module into the mix and you won’t have to hard code the current coordinates. You mentioned that you had some issues with platformio. I heard that from several people but never really in details. Can you tell me a bit about the problems you ran into? I might write a clearing article about it then…
– Daniel
Hi, cool project! I ordered one of your ‘Weather Station Kits’ so I could build it. Today I got a package but it only contained the MCU, not the display nor the jumpers. Could you email me? Cheers!
Hi Costa
As mentioned in the email to you the following sometimes happens: my supplier splits the order into two or more deliveries to ship parts of it faster. If you chose to pay for additional tracking you can follow each of the separate parcels and track them up to your door steps. Please let me know (here) when everything arrived…
Kind regards,
Daniel
Hi,
I’m new to all this I tried your weather app, so I moved on to this, for the life of me I cant get it to work, when uploaded to the Wemos I just have a blanks display, do you have a version of code that runs for the arduino-1.6.9 version
Regards
Hi Paul
My first suspect would be that you have the pins set wrong. Two suggestions to make sure this is true: do you get results from fetching the data from adsbexchange.com in the serial console? If yes, this means that everything is fine and just the display is not working. In that case I suggest that you first get the display working in the Arduino IDE with the OLED library example (File > Examples > ESP8266 OLED display driver for SSD1306 > SSD1306UiDemo) or from here: https://github.com/squix78/esp8266-oled-ssd1306/tree/master/examples/SSD1306SimpleDemo
Make sure that you have the correct pins attached:
// D3 -> SDA
// D5 -> SCL
SSD1306 display(0x3c, D3, D5);
And there is also a chance that your display or the output pins that you planed to use are broken. Try to use other pins and don’t forget to adapt the code! Please let me know if it helped!
Hi Daniel,
congratulations for your great project(s)!
I have added a few lines to your code in order to display a message when there are no planes in range. I have added them to the “drawHeaderOverlay” function…
else if (!adsbClient.isAircraftVisible()) {
display->setTextAlignment(TEXT_ALIGN_LEFT);
display->setFont(ArialMT_Plain_16);
display->drawString(10, 10, “No planes”);
}
Is it the right place to add this? Is “drawHeaderOverlay” the right place to interact with other I/O, for example adding a few leds or a neopixels in order to tell me when there are visible planes in range?
Thanks and best regards!
Hi Fernando
Yes, the drawHeaderOverlay function is the right place to display the “No planes” message. Good idea, by the way. You could even add some information like “No airplane seen in the last 5 minutes”…
I wouldn’t add interaction with other hardware into the drawOverlay functions. It would work but it is really bad style, since the drawOverlay function is for drawing to the display. A better place would probably be to add it to the main loop. And if you are worried about smooth animations you probably should make sure that you have enough cycles left in order to do the hardware interaction with this block of the main loop:
int remainingTimeBudget = ui.update();
if (remainingTimeBudget > 0) { ..}
I hope that helps!
If you want to add GPS support I have very good experiences with this cheap gps module: http://www.banggood.com/1-5Hz-VK2828U7G5LF-TTL-Ublox-GPS-Module-With-Antenna-p-965540.html?p=6R31122484684201508S
It has everything on board, and works directly from 3.3V. Has a good reception, acquires gps signals in ~30 seconds cold. When placed close to a window I could get stable reception even indoors.
I used a GPS like that on another project (hackaday.io/project/5180-real-simple-and-cheap-gps-navigation). I might try to combine both systems to show the planepositions on my map…
I also added an offset to the heading arrow in order to have it pointing the direction the screen and i am facing:
#define LOCALHEADING 170 // this is what you measure holding a compass the direction you are facing at
Then i subtract it in the drawHeading call:
drawHeading(display, 78, 52, adsbClient.getHeading()-LOCALHEADING);
In my case it is 170 degrees as this is the orientation of my terrace (170 degrees = almost oriented to the South). This is how I will be looking both at the screen and at the planes.
As the arrow is drawn with trigonometric functions we just subtract the offset without caring about it being negative, right?
Cheers!