Making a LED powered METAR map for your wall

While waiting for my airplane kit to arrive I got inspired to make a small crafty project after seeing someone post about it on reddit and showing it to my girlfriend who said we can make one together.

We did a bit more research and because I’ve made some projects with Raspberry Pi before, we decided to go that route. Here’s a picture of the finished project:


Supplies needed

Here’s a list of the things you will need:

Plotting your chart area

Unless you want to make your own frame, the dimensions of your project will be limited by what size shadow box frame you can easily purchase. The simplest size is 16 x 20 inch frames, so I used that as a guide of the area to size out.
This worked out great for the Puget Sound Area to cover the airports from Bellingham in the north to Olympia in the South and Hoquiam and Quillayute on the coast using my old expired sectional chart from my private pilot training.

Plotting out the area and using some wooden meeples to highlight the airports

To light up the airports with the flight category, we’re using the data reported from so we checked the airports we want to highlight via the API to ensure they are reporting data.

After we were satisfied with the area, we created a 16 x 20 inch transparent sheet by cutting up some sheet protectors and taping them together and then overlaying them onto the area and marking down the airports so we could transfer the locations onto the back of foam board for the LEDs to go into.

Transparent sheet with airport locations

Software and Wiring

Since the project is pretty simple, we used a Raspberry Pi Zero W, which has WIFI built in and can run the code to download the weather data using the above mentioned web API to pull the weather for all the airports in one go.

For the code, I’ve started by looking at some of the other projects people have done and the NeoPixel documentation for python.

We wrote an updated and optimized script and published it on Github, along with the instructions to set it up.

We ended up with a total of 22 lit up LEDs, so we wired it directly to the Raspberry as shown here. Before attaching the wires to the Raspberry headers, I soldered the header strip onto the Raspberry so it creates a good connection.

Raspberry Pi LED wiring (image courtesy of adafruit -

Here’s a picture of the wiring while I was testing out the code. I was using a breadboard while doing this since it made it easier to disconnect the wires during testing.

LED wiring in action

To finalize the order of the LEDs you will need to arrange them on the board and make changes to the airport list accordingly.

Another important note is to test the LEDs for all the colors in case there is a bad one, in our case the 5th LED couldn’t show RED light, so we skipped over that one.
The easiest way to test this once you’ve installed the software is to just manually control the colors of the LEDs by opening the python3 console:

sudo python3

Then entering the following to light up 30 LEDs at once (if you are using more, just replace the number below):

import board
import neopixel
pixels = neopixel.NeoPixel(board.D18, 30)

This will light up all LEDs in red, if you see a bad one, mark it with some tape so you don’t use it for an airport.
Repeat the step for green:






Once you’re done you can turn off the lights by typing


and then pressing CTRL+Z to exit the python console.

Board Assembly

Once we figured out the software portion and what airports to light up it was time to drill some holes in the foam board for the LEDs to go into using the template made earlier.

Foam board holes drilled

After we had the holes made we tested it by temporarily affixing the sectional chart onto the board and sticking some of the LEDs into the holes and turning on the project, but we found that the LEDs created a lot of light and the LEDs were sticking out a bit, so we decided to double up the foam board, which made the light more defined and allowed the sectional chart to sit flush on the board, so we glued together the two foam boards.

We did a second quick test and pinned the sectional chart onto the board for the first complete light up test:

First light up test

After that it was time put everything together. we made the final cuts to the chart to fit perfectly onto the board and align with the lights and then glued it to the board using a glue stick.

Then it was time to glue the LEDs onto the board, as you can see from the picture below, some of the LEDs are not lit, one of them because the red light didn’t work and some others because the gap between two airports was too much and it was easier to just skip the light than to cut the lights and having to solder in some wires. at the end we just cut off the remaining LEDs we didn’t need (disconnect the Raspberry power when you do this).

Lit LEDs back of board

Once that was all done and good it was time to assemble it all into the frame – we drilled a hole into the bottom of the frame for the power cable to go through.

Raspberry assembly in frame

And here is the final picture of the completed project:


I hope this was helpful for you.

Some of the above links to Amazon may earn me a small commission to keep the site running.

51 thoughts on “Making a LED powered METAR map for your wall

  1. Erick

    This looks great! Question, what are my options for dimmer lights? Something that glows less. Are they certain specifics I would need to meet? Can you recommend something? Cheers!

    1. Dave

      Change the color to less intence

      COLOR_VFR= (67,0,0) # Green
      COLOR_MVFR= (0,0,67) # Blue
      COLOR_IFR= (0,67,0) # Red
      COLOR_LIFR= (0,34,34) # Magenta
      COLOR_CLEAR= (0,0,0)

      Thats 25% bright
      you could go (2,0,0) etc for really dim


  2. Bob Berlyn

    Looks like a great project and I would like to build. I am an analog electronics guy and pilot but not a programmer. I have discovered that PYTHON is a language but thats really all I know. Does the pi run PYTHON using the operating system (Rasberian) or do I have to get PYTHON software or just load the scrips you wrote into the pi and go.


    1. Philip Rueker Post author

      You just need to load the scripts into the Raspberry file system, “install python” by running the scripts that I’ve documented here and and modify the airports file to have the name of the airports that are relevant to you.

  3. Ulrich Pommer

    Hey Philip,
    First of all, this is a great project. I’m from Germany and would like to take German airports. Is that possible? Do I have to change only the names in the file (airports)? Sorry for my bad english:-(

    greetings Uli

    1. Philip Rueker Post author

      Yes the web service I’m using does also support many international airports, you just need to use the 4 digit ICAO codes like EDDF for Frankfurt and EDDM for Munich.

  4. Rick Sayles

    I saw a MetarMap at SUNnFUN last year and then seeing your project you inspired me to give it a go.

    Thanks for your excellent documentation. Made it work for a non-programmer. It all works now, but it doesn’t update, until you rerun the program, and the pi doesn’t automatically run the program. I have it now where the pi is connected to monitor so I can run the program. I assume you have automated both of those operations?


    1. Philip Rueker Post author


      Yes you can automate this using crontab.
      As I mention on the Github, here’s how you do it:

      If you’d like to have the script refresh in regular intervals, use crontab and set the appropriate interval. For an example you can refer to the crontab file in the GitHub repo (make sure you grant the file execute permissions beforehand). To edit your crontab type: crontab -e, after you are done with the edits, exit out by pressing ctrl+x and confirm the write operation
      The sample crontab will run the script every 5 minutes (the */5) between the hours of 7 to 21, which includes the 21 hour, so it means it will run until 21:55
      Then at 22:05 it will run the script, which will turn all the lights off

  5. Sameer

    This is great! I’m working on this project now as well. I ran into a snag with the level shifter. Everything works great on the breadboard, but when I connect jumper wires to the level shifter directly the LEDs go rainbow colors instead of red or green etc. I just purchased some veroboard to solder the level shifter and create connections without jumper wires.

    How many LEDs are you able to light up directly off the 5v pin without risking the pi? Thx!

    1. Philip Rueker Post author

      I’m running 22 active LEDs directly off the Pi 5v without issues.

  6. Chris

    Using your command sequence for checking all the LED’s:
    import board
    import neopixel
    pixels = neopixel.NeoPixel(board.D18, 30)
    I am presented with Attribute Error ‘neopixel’ has no attribute ‘Neopixel’
    Any solutions for this? I am not a code literate.

    1. Philip Rueker Post author

      Make sure that prior to this you have successfully installed the neopixel library by running the following command as listed in the github instructions:
      sudo pip3 install rpi_ws281x adafruit-circuitpython-neopixel
      After that command, you open python3 by entering:
      sudo python3
      and then enter the commands and it should work:
      Testing pixels screenshot

    1. Bob

      I changed the corntab file by just adding

      */5 7-21 * * * /home/pi/
      05 22 * * * /home/pi/

      I guess I am not understanding root permission. I did run sudo chmod +x corntab

      Thanks for the project just wish I knew more about pi but working on it.

      1. Philip Rueker Post author

        Ah, you need to grant the files that are being executed inside the crontab execute permissions, so you should run the chmod command for the and the file.

        After you have done that you can check that you’ve done it correctly by running "ls -al" and you should see “x” for the files 3 times, similar to this:

        Also just to be clear, you have to edit your system crontab by typing "crontab -e", not by copying my sample file into the folder.

  7. Bob

    looks like it is working, I was doing “sudo nano crontab -e”. Thanks for your help and thanks for the program. I had a thought and it is way above my knowledge with pi. I was thinking could you add a screen somewhere on a chart with 5/10 day forecast or scrolling local weather. Again thanks now I need to start on my frame.

  8. Ron Heberlein

    Thanks for the instructions! I was able to get running manually, but I can’t get it to start on power-up.
    Here’s what the statrup.log shows:

    Thu 07 May 2020 06:46:43 AM PDT
    /home/pi/ 2: /home/pi/ echo
    : not found
    /home/pi/ 4: /home/pi/
    : not found
    /usr/bin/python3: can’t open file ‘/home/pi/
    ‘: [Errno 2] No such file or directory

    And here is my ls -al:
    pi@raspberrypi:~ $ ls -al
    total 132
    drwxr-xr-x 17 pi pi 4096 May 7 06:46 .
    drwxr-xr-x 3 root root 4096 Feb 13 07:55 ..
    -rw-r–r– 1 pi pi 244 May 6 06:50 airports
    -rw——- 1 pi pi 905 May 7 06:46 .bash_history
    -rw-r–r– 1 pi pi 220 Feb 13 07:55 .bash_logout
    -rw-r–r– 1 pi pi 3523 Feb 13 07:55 .bashrc
    drwxr-xr-x 7 pi pi 4096 May 5 22:11 .cache
    drwx—— 11 pi pi 4096 May 6 07:20 .config
    drwxr-xr-x 2 pi pi 4096 Feb 13 08:17 Desktop
    drwxr-xr-x 2 pi pi 4096 Feb 13 08:17 Documents
    drwxr-xr-x 2 pi pi 4096 May 6 20:42 Downloads
    drwx—— 3 pi pi 4096 Feb 13 08:17 .gnupg
    -rwxr-xr-x 1 pi pi 53 Apr 19 14:48
    drwxr-xr-x 3 pi pi 4096 Feb 13 08:03 .local
    drwxr-xr-x 2 pi pi 4096 Feb 13 08:03 MagPi
    drwxr-xr-x 3 pi pi 4096 May 7 06:46 METARMAP
    -rwxr-xr-x 1 pi pi 2568 May 5 22:51
    drwxr-xr-x 2 pi pi 4096 Feb 13 08:17 Music
    drwxr-xr-x 2 pi pi 4096 Feb 13 08:17 Pictures
    -rw-r–r– 1 pi pi 108 Apr 19 14:48
    drwx—— 3 pi pi 4096 May 5 21:41 .pki
    -rw-r–r– 1 pi pi 807 Feb 13 07:55 .profile
    drwxr-xr-x 2 pi pi 4096 Feb 13 08:17 Public
    -rwxr-xr-x 1 pi pi 48 Apr 19 14:48
    -rw-r–r– 1 pi pi 74 May 7 06:44 .selected_editor
    -rw-r–r– 1 root root 264 May 7 06:46 startup.log
    -rwxr-xr-x 1 pi pi 107 Apr 19 14:48
    -rwxr-xr-x 1 pi pi 129 May 6 20:48 startup.sh_test
    drwxr-xr-x 2 pi pi 4096 Feb 13 08:17 Templates
    drwxr-xr-x 2 pi pi 4096 Feb 13 08:17 Videos
    -rw——- 1 pi pi 56 May 7 06:46 .Xauthority
    -rw——- 1 pi pi 2425 May 7 06:47 .xsession-errors
    -rw——- 1 pi pi 2425 May 7 06:35 .xsession-errors.old

    Any thoughts as to what is going on?
    Thanks! Ron

    1. Philip Rueker Post author

      I just updated the instructions on the github and removed the step about setting up rc.local since it seems to cause strange issues with startup.
      I found it easier to just rely on the crontab instead to automatically run the script regularly, so I suggest you just forget the rc.local startup and instead use the crontab.

      1. Ron Heberlein

        That did it. It took a minute to start after a restart, but it came on automatically!
        50 lights setup, now I have to get the sectionals. Thanks for the help!

  9. Steve Peck

    there is no file in github now… and can you please update the instructions about what you’re saying about cron?

    1. Philip Rueker Post author

      Correct, I removed the file, since for the crontab I just used (which basically does the same).
      The instructions about crontab have been on the Github all this time:

      To have the script start up automatically and refresh in regular intervals, use crontab and set the appropriate interval. For an example you can refer to the crontab file in the GitHub repo (make sure you grant the file execute permissions beforehand to the and file). To edit your crontab type: crontab -e, after you are done with the edits, exit out by pressing ctrl+x and confirm the write operation
      The sample crontab will run the script every 5 minutes (the */5) between the hours of 7 to 21, which includes the 21 hour, so it means it will run until 21:55
      Then at 22:05 it will run the script, which will turn all the lights off

  10. Ron Heberlein


    Have you tried to incorporate blinking lights into the program?
    I’d like to be able to have a light blink if the wind speed (or gust) exceeds a certain value. I’ve been searching on the internet for this and haven’t seen anything that seemed like it would plug into your code. That being said I’m not a programmer…

    1. Philip Rueker Post author

      I felt inspired by your question and since I am a programmer, I expanded the script to support blinking for windy conditions.

      I just uploaded the updated version of the script that now supports animation for wind conditions, if you go to the github, please use the updated, and with the latest version I just uploaded (it makes sure that any currently running scripts will be closed when the next one runs).

      I also added some information to the Readme instructions about the new parameters that I’ve added to the script that you can adjust as needed.

      1. Ron Heberlein

        How awesome!!!
        I found one error in your code. On line 22 and 23, both variables were named “COLOR_IFR_FADE”. I updated line 22 to remove the “_FADE” and everything worked perfectly!

  11. Jordan

    Hi Philip,

    Thanks so much for the tutorial, build a huge map to go in my work area and everyone loves it. Ive seen now the commercial Maps have the ability to flash white when there is lightning reported in the area? Is there any way we could add a line in the script to run this kind of like how you ran the wind one? That would be super cool!

    1. Philip Rueker Post author

      Sure, I just added this functionality in the script, it will flash to white to represent lightning in the vicinity as reported by that airports METAR.
      You can get the latest version with the updated changes from the github.

  12. Kit

    Hi Philip.

    I have an issue where only the first led lights up. I have a strand of 50, the ones you suggested. I can issue “pixels = neopixel.NeoPixel(board.D18, 30)” or use 20, or 10, or 50, I still only get the first led to light up after issuing “pixels.fill()”. Do you think I have a bad strand of leds?

    1. Philip Rueker Post author

      I think there’s two possibilities.
      1) Yes maybe the strand is bad
      2) Did you make sure that you connect the correct ends to the Raspberry? On the LEDs you will find a small arrow on one side like this, this is the side that you have to connect the wires to the Raspberry. direction on LEDs.

      1. Kit

        I did connect the pi to the input end of the led strand. After some testing, the strand is defective. Will give it a try again when the new strand arrives! Thanks for the help.

  13. Chuck

    I just finished making one of these, i love it! thanks for putting together this guide, and the upkeep with the code!

  14. Ron Heberlein

    I wanted to see if anyone else was having issues with the map not refreshing?
    For about the past week, I have to turn the Pi off and then back on to get the map to refresh with the latest weather data. It then will refresh for a while (maybe a few hours), and then gets stuck again.

    Is there a way to plug in a monitor and see how the program is running (other than manually starting the program)?

    1. Philip Rueker Post author

      Maybe your WIFI connection is weak and it fails at some point randomly? I’m not quite sure how the raspberry PI handles that.

      In any case, you could write to a logfile every time the script gets executed.
      If you just want to see if the script get’s started at all you could add something like this to the start of the script:
      echo $(date) - running metar script >> myfile.txt
      This will write the current date/time into a new text file called myfile.txt

      And if you want to just print the entire output of every time the script gets executed automatically, you can modify your crontab to something like this and it will print the entire output that would usually be seen on the console:
      * 7-21 * * * /home/pi/ > /home/pi/outputlog.log 2>&1
      This will print everything that happens in the script into a new file called outputlog.log

  15. Randy

    Great post. I frequently visit Aero Maintenance at Pearson airport and have always liked the METAR chart they have in their office. I was looking for different addressable LED products to make my own METAR chart and, bam!, full build instructions and parts list!

    My plan is to combine this with a previous (insanely over-designed) project of mine: Basically, I’m thinking about building the METAR chart, then cutting out a part of the sectional for the PiTFT screen so it can also display METAR details.

  16. Tony

    Philip, fantastic project. I noticed there is a guy in the US (Metarmaps) selling these so i was curious to see if the code/project existed and found you. A couple of hours work and it was up and running. The VNC charts in Canada are paper only and huge so I discovered the US charts are free and downloadable so I am going to have a poster shop print up the size I want ( 2′ x 3′) and then complete the LED install. Bought you more than a coffee 🙂 Thanks for the project.

    Tony Varga

  17. Scott

    You may not know this for sure but I’m about to start a very large map and I’m up to 81 LEDs so far. Can this project use more than 50? Do you happen to know the limit?

    1. Philip Rueker Post author

      Yes you can, but you will have to wire an external power supply to the LEDs as the internal power coming from the Raspberry Pi won’t be enough to power that many LEDs.

      1. Scott

        Just got my 5050 LEDs and the code works great. The fading confused me a bit because I was expecting a fade but found that it just blinks with a set brightness. I’m using 107 5050 LEDs and the current draw is 0.81A.

  18. Anthony Varga

    Philip, to conserve the lifetime of the LEDs (they are long but really only about 5 years on 24/17) I purchased a micro PIR sensor that I am going to flush mount into my map to trigger the lights on when motion is detected. I am planning to put a 60 minute countdown in Python that when triggered, would start counting and when t=0 the lights would go off. I am not an adept Python programmer but will figure it out but just wondering if you have any thoughts about placement of the timer in the code ?

    1. Philip Rueker Post author

      So the script will just turn on the light and will keep them lit when the script finishes by default.
      So you could just add a sleep timer and then deinit the LEDs which turns them off at the end. So you can just add this to the bottom of the script and it will wait for 3600 seconds and then pixels.deinit() will turn off the LEDs until the next time the script starts and turns them back on.


  19. Anthony Varga

    I think the problem with that is that during the sleep, the metars will not update every five minutes like they do now ?

    1. Philip Rueker Post author

      Yes in that case, what you’ll need to do is make use of a temporary file where you store the time when you started the timer after motion was triggered.
      You can insert the code just after the initialization of the LEDs.
      Here’s a sample that should work, there are 2 new imports in line 9 and 10 and you need to replace the sensor piece of code in line 59 with your reading of your actual motion sensor to return True when motion is detected:

  20. Anthony Varga

    Really appreciate the code insert. I will play this weekend and report back.


Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.