Raspberry Pi NOAA Weather Satellite Receiver




I'm a ham, a tinker, a maker. I like interesting things. I'm a technophile, a wood turner, and a ...

A new pile of parts means a new project is in the works.

I’m building a Raspberry Pi based NOAA weather satellite receiver. I’ve got some experience with receiving signals from NOAA satellites, but will be a little different, as all of the work is going to be done automatically on a Raspberry Pi. This will allow me to place the receiver right at the antenna, which is mounted in my attic. With a very short piece of coax, reducing feed-line loss.

I’ll be using the following list of parts:

  • Raspberry Pi 3 Model B
  • MicroUSB Power Supply
  • Generic Raspberry Pi 3 Case
  • 32 GB Micro SD Card
  • NooElec SDR Dongle
  • QFH Antenna

This project will require some basic Linux skills. If you are not comfortable navigating around the Linux command line, you may need to get some help if you want to follow along.

This instructable is going to focus on getting the Raspberry Pi working to receive images. Details around building a proper antenna can be found from other sources. I even made a video about it: https://youtu.be/KU75FSA6o2M

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: Prepare the Raspberry Pi

The first step is getting the Raspberry Pi up and running. I’m using Raspbian (Jessie 2016-11-25).

There are plenty of tutorials on getting Raspbian set up and booting on the Raspberry Pi. You should have no difficulty in finding one: https://www.raspberrypi.org/documentation/installation/installing-images/README.md

Once you have the Raspbian image copied to your micro SD card, boot the Raspberry Pi. You'll need to get it on the network and enable SSH. You can certainly use either a wired Ethernet connection, or wireless. I'm using wireless, as I don't have a wired connection in my attic.

Enable SSH using the Raspberry Pi Configuration utility in the Preferences menu. You may want to set it to boot to CLI while you are in there. Since this is going to be a headless setup, there is no need to waste resources on a GUI.

Next we want to make sure the Raspberry Pi is fully up-to-date. Issue the following commands:

sudo apt-get update
sudo apt-get upgrade
sudo reboot

Step 2: Install the Necessary Software

The first thing we need is the USB drivers for the RTL dongle:

sudo apt-get install libusb-1.0

Since we need to build the latest version of rtl-sdr to actually make use of the RTL dongle, we'll need to install cmake:

sudo apt-get install cmake

We need to make sure the Raspberry Pi doesn't load any SDR kernel modules that will interfere with the rtl-sdr sofware.

Using your favorite text editor, create a new file named /etc/modprobe.d/no-rtl.conf and put the following text in the file. You need to run that text editor as sudo (i.e. 'sudo vi' or 'sudo nano' etc) to write to the modprobe.d directory:

blacklist dvb_usb_rtl28xxu
blacklist rtl2832
blacklist rtl2830

Install the most recent build of rtl-sdr:

cd ~
git clone https://github.com/keenerd/rtl-sdr.git
cd rtl-sdr/
mkdir build
cd build
sudo make install
sudo ldconfig
cd ~
sudo cp ./rtl-sdr/rtl-sdr.rules /etc/udev/rules.d/
sudo reboot

We'll need the sox audio toolkit in order to manipulate the received audio stream:

sudo apt-get install sox

We need a way to schedule the captures to happen as the satellites pass overhead. Install the at scheduler:

sudo apt-get install at

We need a way to know when the satellites will pass overhead. We'll use an application called predict:

sudo apt-get install predict

Finally, we'll need wxtoimg to convert the captured audio stream to an actual image:

cd ~
wget http://www.wxtoimg.com/beta/wxtoimg-armhf-2.11.2-beta.deb
sudo dpkg -i wxtoimg-armhf-2.11.2-beta.deb

Step 3: Testing Things Out

Once all the software is installed, make sure your USB dongle is connected and run the following command:

sudo rtl_test

You should see the following output:

Found 1 device(s):
  0:  Realtek, RTL2838UHIDIR, SN: 00000001

Using device 0: Generic RTL2832U OEM
Found Rafael Micro R820T tuner
Supported gain values (29): 0.0 0.9 1.4 2.7 3.7 7.7 8.7 12.5 14.4 15.7 16.6 19.7 20.7 22.9 25.4 28.0 29.7 32.8 33.8 36.4 37.2 38.6 40.2 42.1 43.4 43.9 44.5 48.0 49.6 
Sampling at 2048000 S/s.

Info: This tool will continuously read from the device, and report if
samples get lost. If you observe no further output, everything is fine.

Reading samples in async mode...

If you receive any error messages, you'll need to troubleshoot them before continuing. If your RTL Dongle isn't working at this point, it won't do any good to continue.

You need to run predict one time to set your ground station location. To do that you'll need your latitude and longitude. You can get your latitude and longitude from google maps by searching for your address, the right clicking on the pointer and selecting "What's Here". One thing to note is that Google displays North as positive and East as positive numbers. Predict uses North as positive but WEST as positive. Make sure to adjust accordingly, or your predictions will be no good.

Run predict from the command line, and select option 'G'. Enter your ground station information and exit the program.:

                           --== PREDICT  v2.2.3 ==--         
                     Released by John A. Magliacane, KD2BD   
                                    May 2006                 

                            --==[ Main Menu ]==--

 [P]: Predict Satellite Passes          [I]: Program Information
 [V]: Predict Visible Passes            [G]: Edit Ground Station Information
 [S]: Solar Illumination Predictions    [D]: Display Satellite Orbital Data
 [L]: Lunar Predictions                 [U]: Update Sat Elements From File
 [O]: Solar Predictions                 [E]: Manually Edit Orbital Elements
 [T]: Single Satellite Tracking Mode    [B]: Edit Transponder Database
 [M]: Multi-Satellite Tracking Mode     [Q]: Exit PREDICT

                 *  Ground Station Location Editing Utility  *

                        Station Callsign  : W1AW
                        Station Latitude  : 41.7169 [DegN]
                        Station Longitude : 72.7271 [DegW]
                        Station Altitude  : 25 [m]

            Enter the callsign or identifier of your ground station

You need to run wxtoimg once to accept the terms and conditions.


You need to tell wxtoimg where your base station is at, so it can properly generate an overlay map. You do so by creating a file in your home directory named ~/.wxtoimgrc. In this file, North is positive, as with predict, however EAST is positive, which is the opposite of what predict uses. Make sure to adjust your values appropriately.

Using your favorite text editor, create a new file named ~/.wxtoimgrc and put the following text in the file, substituting your values:

Latitude: 41.7169
Longitude: -72.7271
Altitude: 25

Step 4: The Scripts

Now that you've got a working RTL dongle on your Raspberry Pi, it's time to actually make it receive some weather maps. Make sure your antenna is connected and located as best as possible. I've got mine mounted in my attic and it works fairly well from there. If you can mount it outside, that would be even better. Get it as high as possible.

We are going to need to create a few scripts to automate everything. This is where that Linux familiarity is going to come in.

First we'll create a couple directories to hold our files:

cd ~
mkdir weather
cd weather
mkdir predict
cd predict

Next we'll make the two scripts that kick off the scheduling. The first is 'schedule_all.sh'. This script will be called nightly at midnight. It downloads satellite pass information from celestrak and creates a TLE file for predict to use. Then it removes all AT jobs from the system, so no passes get double scheduled. Finally, it calls the second script 'schedule_satellite.sh' for each satellite we are interested in.

Using your favorite text editor, create a new file in ~/weather/predict named schedule_all.sh and put the following code in the file:


# Update Satellite Information

wget -qr https://www.celestrak.com/NORAD/elements/weather.txt -O /home/pi/weather/predict/weather.txt
grep "NOAA 15" /home/pi/weather/predict/weather.txt -A 2 > /home/pi/weather/predict/weather.tle
grep "NOAA 18" /home/pi/weather/predict/weather.txt -A 2 >> /home/pi/weather/predict/weather.tle
grep "NOAA 19" /home/pi/weather/predict/weather.txt -A 2 >> /home/pi/weather/predict/weather.tle
grep "METEOR-M 2" /home/pi/weather/predict/weather.txt -A 2 >> /home/pi/weather/predict/weather.tle

#Remove all AT jobs

for i in `atq | awk '{print $1}'`;do atrm $i;done

#Schedule Satellite Passes:

/home/pi/weather/predict/schedule_satellite.sh "NOAA 19" 137.1000
/home/pi/weather/predict/schedule_satellite.sh "NOAA 18" 137.9125
/home/pi/weather/predict/schedule_satellite.sh "NOAA 15" 137.6200

The second script, 'schedule_satellite.sh', recurses through each pass of the given satellite for the current day. It determines if the maximum elevation is 20 degrees or greater. If it is, then it calculates the length of the pass, and schedules the recording and processing of the pass. If the maximum elevation is less than 20 degrees, the pass is ignored, as it generally won't produce a decent image.

Using your favorite text editor, create a new file in ~/weather/predict named schedule_satellite.sh and put the following code in the file:

PREDICTION_START=`/usr/bin/predict -t /home/pi/weather/predict/weather.tle -p "${1}" | head -1`
PREDICTION_END=`/usr/bin/predict -t /home/pi/weather/predict/weather.tle -p "${1}" | tail -1`

var2=`echo $PREDICTION_END | cut -d " " -f 1`

MAXELEV=`/usr/bin/predict -t /home/pi/weather/predict/weather.tle -p "${1}" | awk -v max=0 '{if($5>max){max=$5}}END{print max}'`

while [ `date --date="TZ=\"UTC\" @${var2}" +%D` == `date +%D` ]; do

START_TIME=`echo $PREDICTION_START | cut -d " " -f 3-4`
var1=`echo $PREDICTION_START | cut -d " " -f 1`

var3=`echo $START_TIME | cut -d " " -f 2 | cut -d ":" -f 3`

TIMER=`expr $var2 - $var1 + $var3`

OUTDATE=`date --date="TZ=\"UTC\" $START_TIME" +%Y%m%d-%H%M%S`

if [ $MAXELEV -gt 19 ]
    echo ${1//" "}${OUTDATE} $MAXELEV

    echo "/home/pi/weather/predict/receive_and_process_satellite.sh \"${1}\" $2 /home/pi/weather/${1//" "}${OUTDATE} /home/pi/weather/predict/weather.tle $var1 $TIMER" | at `date --date="TZ=\"UTC\" $START_TIME" +"%H:%M %D"`


nextpredict=`expr $var2 + 60`

PREDICTION_START=`/usr/bin/predict -t /home/pi/weather/predict/weather.tle -p "${1}" $nextpredict | head -1`
PREDICTION_END=`/usr/bin/predict -t /home/pi/weather/predict/weather.tle -p "${1}"  $nextpredict | tail -1`

MAXELEV=`/usr/bin/predict -t /home/pi/weather/predict/weather.tle -p "${1}" $nextpredict | awk -v max=0 '{if($5>max){max=$5}}END{print max}'`

var2=`echo $PREDICTION_END | cut -d " " -f 1`


When the time comes for a give pass to be recorded and processed, at kicks off the final script 'receive_and_process_satellite.sh'. When this script is called, it uses rtl_fm to receive the audio from the satellite pass, and sends that audio to sox for processing. Sox saves the audio to a file. Once the pass is complete, wxmap is called to generate an overlay map for the image. Finally, wxtoimg is called to generate the actual image and place the overlay map on it.

Using your favorite text editor, create a new file in ~/weather/predict named receive_and_process_satellite.sh and put the following code in the file:


# $1 = Satellite Name
# $2 = Frequency
# $3 = FileName base
# $4 = TLE File
# $5 = EPOC start time
# $6 = Time to capture

sudo timeout $6 rtl_fm -f ${2}M -s 60k -g 45 -p 55 -E wav -E deemp -F 9 - | sox -t wav - $3.wav rate 11025

PassStart=`expr $5 + 90`

if [ -e $3.wav ]
    /usr/local/bin/wxmap -T "${1}" -H $4 -p 0 -l 0 -o $PassStart ${3}-map.png

    /usr/local/bin/wxtoimg -m ${3}-map.png -e ZA $3.wav $3.png

Once all three scripts have been created, we need to make the executable, by issuing the following commands:

chmod +x schedule_all.sh
chmod +x schedule_satellite.sh
chmod +x receive_and_process_satellite.sh

Now, the last step in automating the reception is to schedule the first script to run just after midnight. Run the following command:

crontab -e

It will open a text editor of your choice to edit the cron file. Simply add the following line to the bottom of this file and save:

1 0 * * * /home/pi/weather/predict/schedule_all.sh

Now, at 00:01 the schedule will start. (if you don't want to wait, simply run the following command once to kick the process off:)


Step 5: Check Things Out

To see upcoming satellite passes that are scheduled to be processed, run the following command:


Check the ~/weather directory for your results. Each pass will generate three files:

NOAA1820170105-181147-map.png  <-- Map overlay file
NOAA1820170105-181147.png      <-- The final image file
NOAA1820170105-181147.wav      <-- The raw audio file

The format of the file name is the satellite name, followed by the date (YYYYMMDD) and time (HHMMSS) of the start of the pass. There are several filters that wxtoimg can use when generating the image file. I've had different luck with different satellites and passes on each filter. Feel free to play around with wxtoimg on the original map and audio files and see what you come up with.

One thing to note, the receiver can only receive one satellite at a time. If two satellites are passing overhead at the same time, the first one to start recording will "win" and be recorded. The second recording will error out and stop.

Step 6: Some of My Results

Epilog Contest 8

Participated in the
Epilog Contest 8

32 People Made This Project!


  • Made with Math Contest

    Made with Math Contest
  • Multi-Discipline Contest

    Multi-Discipline Contest
  • Robotics Contest

    Robotics Contest

203 Discussions


9 days ago

Good morning! I recently completed this project with a NOAA wx antenna procured through ebay (https://www.ebay.com/itm/137-MHz-LOOP-ANTENNA-NOAA/173670169433?hash=item286f8c7b59:g:YxAAAOSwaSVcAs25). I was receiving partial / poor images when I had it mounted in my attic, so I moved it out onto the driveway overnight for the night passes, and still receive partial images. Is there a setting for the script I should check, or is it my suburban location or the antenna that is causing the poor quality?


7 weeks ago

I get this error in schedule_satellite.sh file:

/home/pi/weather/predict/schedule_satellite.sh: line 10: [: ==: unary operator expected
date: invalid date ‘TZ="UTC" @’

How can I fix this?

2 replies

Reply 27 days ago

Hi Alex, that is because it is being run by the first script. Try this to test it.
/home/pi/weather/predict/schedule_satellite.sh "NOAA 19" 137.1000

You will see you don't get the error since you are now passing the proper parameters to it.


Reply 4 weeks ago

Hi, I recently had a similar error. I think this may mean that the script cannot locate your weather.tle file and cannot find the date information properly required in line 10? I suggest you check the path to this file carefully whenever it appears. Also make sure the predict program is running properly.


Question 8 weeks ago on Step 2

The wget wxtoimg line failed with a file not found. There is a copy of wxtoimg 2.11 beta on the https://wxtoimgrestored.xyz website but it is not a deb package nd I have no idea how to build it or what to do with it. When I extract the tar file there is a 'usr' and 'etc' directories each of which have multiple sub direcories. Any suggestions?


Question 2 months ago

Ok so i have installed everything and got all the scrpts to run what i think is correctly. I had a few passes happen but no files came up in the weather folder. if i read the output of the prossessing script it says

timeout: invalid time interval ‘rtl_fm’
Try 'timeout --help' for more information.
sox FAIL formats: can't open input `-': WAVE: RIFF header not found
cp: cannot stat '/home/pi/weather/*.png': No such file or directory
rm: cannot remove '/home/pi/weather/08-05-2019_21-12/*-map.png': No such file or directory
rm: cannot remove '/home/pi/weather/*.png': No such file or directory
rm: cannot remove '/home/pi/weather/*.wav': No such file or directory

idk what is wrong. the extra is b/c i modded like what is in the comments
pls help i want this to work
i made sure the names of the scripts were right.
i resynced my pi time

Edit i did the rtlsdr v3 edit and it now records the sound files and images pop up BUT
the images are blank and i dont think there is any sound in the files. they are like 44 bytes.


3 months ago

Has anyone succes with a RTL-SDR v3 dongle? Had this instructable running a year ago with a NooElec dongle without an issue but now with the RTL-SDR v3 it seems to be not working.
Have the dongle connected to a USB2.0 powere hub with a 2.5Amp powersupply.
When I run the rtl_fm command line manually:
sudo rtl_fm -f 100.3e6 -s 60k -g 45 -p 55 -E wav -E deemp -F 9 - | sox -t wav - test.wav rate 11025
Found 1 device(s):
0: Realtek, RTL2838UHIDIR, SN: 00000001
Using device 0: Generic RTL2832U OEM
Found Rafael Micro R820T tuner
Tuner gain set to 44.50 dB.
Tuner error set to 55 ppm.
Tuned to 100780000 Hz.
Oversampling input by: 32x.
Oversampling output by: 1x.
Buffer size: 4.27ms
Sampling at 1920000 S/s.
Output at 60000 Hz.
^CSignal caught, exiting!
User cancel, exiting...
sox FAIL formats: can't open input `-': WAVE: RIFF header not found

it looks like rtl_fm is running without issues, but when I cancel with CTRL-c I see the sox error message

Have it running on the last downloadable Stretch with Desktop version from April 2019 before they switch to Buster.


1 reply

Reply 2 months ago

heres what I use.
"sudo timeout $6 rtl_fm -f ${2}M -s 60k -p 59 -g 49 -E wav -E deemp -F 9 - | sox -t raw -e signed -b 16 -r 12480 - $3.wav"

looks like the rtlsdr puts out a different signal then some other sdrs


Question 4 months ago

Hi I live in australia and having trouble with Lat and long in predict. my Lat is -31.482170 S
and Long 118.281929 E Can someone pls tell me how to get this into predict

1 answer

Answer 3 months ago

When in Predict both latitude & Longitude are positive North and West values, so latitude I would presume to be 31.482170 and longitude 118.281929, but on your base station on ./wxtoimgrc is Latitude -31.482170 and Longitude 118.281929 for the map overlay. Predict is confusing to why only positive N latitude & W longitude.


4 months ago

I want to say thank you for these instructions, works great and very easy to do
I did make some changes to a couple of the files which allow me to create a satellite pass list for that day and to also put image files into their own folder for that date and time for better organization. I will be including what n6vmoa did in the near future, as that looks very interesting to just open a web page to view the current images.

I am posting it here for others that may want to use it.
In receive_and_process_satellite.sh I added the following:

# $1 = Satellite Name
# $2 = Frequency
# $3 = FileName base
# $4 = TLE File
# $5 = EPOC start time
# $6 = Time to capture

# reads and creates folder with current date / time (i.e 05-30-2019_07-48 *windows friendly*)
NOW=$(date +%m-%d-%Y_%H-%M)
mkdir /home/pi/weather/${NOW}

sudo timeout $6 rtl_fm -f ${2}M -s 60k -g 45 -p 55 -E wav -E deemp -F 9 - | sox -t wav - $3.wav rate 11025
PassStart=`expr $5 + 90`
if [ -e $3.wav ]
/usr/local/bin/wxmap -T "${1}" -H $4 -p 0 -l 0 -o $PassStart ${3}-map.png
/usr/local/bin/wxtoimg -m ${3}-map.png -e ZA $3.wav ${3}.png
/usr/local/bin/wxtoimg -m ${3}-map.png -e NO $3.wav ${3}.NO.png
/usr/local/bin/wxtoimg -m ${3}-map.png -e MCIR $3.wav ${3}.MCIR.png
/usr/local/bin/wxtoimg -m ${3}-map.png -e MSA $3.wav ${3}.MSA.png

# copies files to the new folder and deletes the original ones
cp /home/pi/weather/*.png /home/pi/weather/${NOW}/
rm /home/pi/weather/${NOW}/*-map.png
rm /home/pi/weather/*.png
rm /home/pi/weather/*.wav

Now in the schedule_all.sh add the following line at the end:
atq > /home/pi/weather/passes_`date +"%m-%d-%Y"`.txt

This will create a txt with a name like "passes_05-30-2019.txt" and inside this file will list the passes for that day though they are not in order.
There is probably a more efficient way to do this but I am somewhat new to Linux and just doing this took a couple of days to get it correct.

1 reply

Reply 3 months ago

Good job Romaytech, I was looking for something like that, I'll also have to take a look at what you said n6vmo has done concerning viewing via a web page.


3 months ago

Buster Lite update:
Make sure to install git when you come to "Install the most recent build of rtl-sdr" step after cd ~
code: sudo apt-get install git


5 months ago

I am getting the same UTC error as some other people while running the schedule_all:
date: invalid date ‘TZ="UTC" @’
Changed https to http, timezone from CEST (I am in Europe) to UTC, using Curl instead of wget... (so all suggestions below) but still not working.

What else can I try? Why I keep getting this error? Thanks in advance.

2 replies

Reply 5 months ago


After several hours, found the problem. If I execute the schedule_all.sh with sudo rights, it is not working. I must execute it from pi user without root rights, then problem is gone :)


Reply 5 months ago


pi@raspberrypi:~/weather/predict $ sudo ./schedule_all.sh [ HAD ERRORS ]

pi@raspberrypi:~/weather/predict $ ./schedule_all.sh [ WORKED OK ]


5 months ago

Hey there,

The blue RTL-SDR stick has a ppm of about 45. So the ppm-correction of 55 here in this code <sudo timeout $6 rtl_fm -f ${2}M -s 60k -g 45 -p 55> seems fine. Now I'm having a Nesdr Smartee with a ppm of -1 more or less (tested using rtl_test -p) . Does that mean I can basically cut out the -p parameter at all?

When having an LNA lined up, the gain in the same line of code should be lowered or taken out entirely as well?