NOAA Satellites Pt 1


Mind the cable.

Haven’t made a post in a while, thought I’d do something about that.

So I’ve recently got back into dabbling with NOAA satellites, to that end I’ve setup a test antenna in my bedroom. Initially I was running a Cat5 network cable to it since I wanted to stream I/Q data to my PC and decode there, but it made having to leave my room a bit of a chore so away went that plan. The new plan is to perform everything locally on the Pi itself.

My plan was to run the RTLSDR dongle for the duration of the pass thus I needed pass data. My original idea was to scrape for their pass data but that didn’t come to pass because I’m dumb and can’t screen scrape properly. So I moved onto PyPredict which is a python implementation of Predict. From there I have two files: and then a bash script to tie it all together. The only additional software packages required are ‘at‘, ‘sox’, and ‘rtlsdr’.

File contents of

import predict

#taken from Celestrak, key is listen frequency
tles = {“137.62M”:”””NOAA-15
1 25338U 98030A 16171.46844711 .00000091 00000-0 57250-4 0 9995
2 25338 98.7825 175.6224 0010714 173.1560 186.9768 14.25734421941311″””,
1 28654U 05018A 16171.47137809 .00000008 00000-0 29790-4 0 9993
2 28654 99.1968 178.4618 0014530 13.2675 346.8875 14.12289036571056″””,
1 33591U 09005A 16171.49671812 .00000064 00000-0 59996-4 0 9991
2 33591 99.0401 128.2883 0013351 208.9844 151.0587 14.12082119379461″””}

#taken from the first result on stackexchange
import datetime
def convert_time( unixtime ):
return datetime.datetime.fromtimestamp(
).strftime(‘%H:%M %Y-%m-%d’)

qth = (lat,long) # lat (N), long (W), alt (meters)
data = {}

for freq, tle in tles.iteritems():

name = predict.observe(tle, qth)[‘name’].strip()
t = predict.transits(tle, qth)
p =

while (p.peak()[‘elevation’] < 15):

p =
print name, “pass too low, recalculating”

data[name] = {}
data[name][‘frequency’] = freq
data[name][‘start_unix’] = p.start
data[name][‘start’] = convert_time(data[name][‘start_unix’])
data[name][‘duration_seconds’] = int(p.duration())
data[name][‘duration_minutes’] = convert_time_short(data[name][‘duration_seconds’])
data[name][‘elevation’] = p.peak()[‘elevation’]
#print name, data[name][‘start’], data[name][‘elevation’]

import json

with open(‘satpredict.txt’, ‘w’) as fp:
json.dump(data, fp)

This computes all three NOAA satellites at once because why not. Computation is cheap. Data is passed to the via JSON.

Contents of

import array
import json
import sys

ppmshift = ’55’
name = sys.argv[1]
input_sample_rate = ’48k’
output_sample_rate = ‘11025’
gain = ’20’
f = open(‘satpredict.txt’)

data = json.load(f)

timeoutstr = ‘timeout ‘ + str(data[name][‘duration_seconds’])
rtlstr = ‘rtl_fm -f ‘ + data[name][‘frequency’] + ‘ -M fm -p ‘ + ppmshift + ‘ -s ‘ + input_sample_rate + ‘ -g ‘ + gain + ‘ -‘
soxstr = ‘sox -t raw –buffer 128 -r 48000 -e signed -b 16 – ‘ + name + ‘_i.wav’
sox2str = ‘sox ‘ + name + ‘_i.wav ‘ + name + ‘.wav rate ‘ + output_sample_rate

f = open(name + ‘_sched.txt’, ‘w’)

print timeoutstr, rtlstr + ‘ | ‘ + soxstr
print sox2str

I’m not entirely sure about my rtl_fm or sox settings here, they remain to be validated. They do work, but all I’ve decoded is static. I did struggle for a bit getting rtl_fm to work properly with sox.

From here the bash commands are printed to the console which are then transferred to a .txt file housing all the commands scheduled to be run at the pass time.

Contents of


TIEMSTAMP=$(date +%s)

python $SAT >> $TIEMSTAMP.txt
echo ‘rm ‘$ >> $TIEMSTAMP.txt
echo ‘bash $SAT’ >> $TIEMSTAMP.txt

echo $TIEM

at -m $TIEM < $TIEMSTAMP.txt
rm $SAT’_sched.txt’

The purpose of is to schedule everything, then roll over to the next pass after the the current pass is completed.


So now all I have to do is get wxtoimg or aptdec working on the raspberry pi, and so far I’ve encountered the usual hiccups when I work in linux: that being ‘wxtoimg’ doesn’t exist after installing it 🙁