Skip to content

Instantly share code, notes, and snippets.

@lxe
Last active November 14, 2024 16:14
Show Gist options
  • Save lxe/c1756ca659c3b78414149a3ea723eae2 to your computer and use it in GitHub Desktop.
Save lxe/c1756ca659c3b78414149a3ea723eae2 to your computer and use it in GitHub Desktop.
Receive GOES-16 and GOES-17 Images with a Raspberry Pi and RTL-SDR dongle

Receive GOES-16 and GOES-17 Images with a Raspberry Pi and RTL-SDR dongle

Also see the original Pieter Noordhuis's guide

Hardware

You need:

  1. Raspberry Pi Model B (or B+) with a MicroSD Card $35-40
  2. An RTL-SDR dongle:
  3. LNA and SAW filter for around 1.69GHz
  4. A 1.6 - 1.9 GHz parabolic grid antenna
  5. Adapter (depending on the antenna terminal):
  6. Cable(s)

Total: ~$185

Assembly:

[Antenna] --- [Adapter] --- [(input) SAWBird+ (output)] --- RTL-SDR (with Bias Tee)] --- [Raspberry Pi]

Software

Prep your Raspberry Pi and install necessary drivers and software.

0. Get your Raspberry Pi ready

  • Download Raspbian Lite Image and Etcher
  • Use Etcher to write the image to the SD card.
  • Mount the SD card as a volume on your machine.
  • Follow this procedure to configure WiFi and SSH.
  • Plug the card into your Raspberry Pi and turn it on.
  • Find the IP address of the Raspberry Pi using your gateway/router administrative interface.

Now you can SSH into your Raspberry PI as pi with a default password raspberry.

1. Get everything up to date

From now on all commands should be run on the Raspberry Pi.

sudo apt update
sudo apt dist-upgrade

# reboot the device
sudo reboot

2. Install dependencies

# get the packages necessary to build and run goestools
sudo apt install git build-essential cmake libusb-1.0 libopencv-dev libproj-dev

3. Install librtlsdr

Grab the latest librtlsdr source, compile it, and install the shared libraries/includes.

# download, compile, and install librtlsdr
git clone https://github.com/steve-m/librtlsdr.git
cd librtlsdr
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr -DINSTALL_UDEV_RULES=ON ..
sudo make -j2 install

# load udev rules and blacklist the DVB driver shipped with the OS
sudo cp ../rtl-sdr.rules /etc/udev/rules.d/
sudo ldconfig
echo 'blacklist dvb_usb_rtl28xxu' | sudo tee --append /etc/modprobe.d/blacklist-dvb_usb_rtl28xxu.conf

# reboot the device
sudo reboot

4. Test your the RTL-SDR dongle

rtl_test 

You should see something like this:

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

If it hangs, just press crtl-c to exit. It doesn't have to finish.

If there are errors, or if the device is not recognized:

  • Reinstall the driver from Step 3
  • Ensure the dongle is secured in the USB port
  • Remove all USB hubs and plug in into the Pi directly
  • Make sure you power your Raspberry Pi with at least a 2.5A power supply
  • Check the device using lsusb command. You should see ID 0bda:2838 Realtek Semiconductor Corp. RTL2838 or something of the like listed there. If not, try the previous steps.
  • Run dmesg and check for errors such as error -71 related to the USB device. This may mean that your RTL-SDR receiver might be broken. This happened to me, so I ordered another one, which ran fine.

5. Install goestools

git clone https://github.com/pietern/goestools.git
cd goestools
git submodule init
git submodule update --recursive
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr ..

# this will take a while on a raspberry pi
sudo make -j2 install 

6. Create goesrecv.conf config

cat <<EOF > ~/goesrecv.conf
[demodulator]
mode = "hrit"
source = "rtlsdr"

[rtlsdr]
frequency = 1694100000
sample_rate = 2400000
gain = 5
bias_tee = false

[costas]
max_deviation = 200e3

[decoder.packet_publisher]
bind = "tcp://0.0.0.0:5004"
send_buffer = 1048576

[monitor]
statsd_address = "udp4://localhost:8125"
EOF

If you're using a NooElec SmarTee dongle with an always-on bias tee, or if you're powering your SAWBird through the micro USB port, set bias_tee = false under [rtlsdr].

If you're using RTL-SDR.com dongle, set bias_tee = true to power the SAWBird board.

7. Roughly point your antenna at the satellite

Find where the GOES-16 or GOES-17 satellites are in the sky at your location using agsattrack.com.

Note the azimuth and elevation.

Use an actual real compass to point your dish at the azimuth. I've been using the iPhone phone compass, which has a 20-30 degree error, rendering it practically useless.

You can also use https://www.dishpointer.com/ which will draw a line on the aerial map where to point your dish -- I found that to be more helpful than the compass.

Adjust your dish angle according to the elevation. Use your smartphone level app, or just eyeball it.

IMPORTANT: Polarization Skew

You should also adjust the skew of your dish roughly according to what https://www.dishpointer.com/ says under "LNB Skew". For GOES-17 I had to point the antenna's left long edge (if facing the same direction as the dish) up at 45 degree angle.

8. Run goesrecv and perform fine antenna adjustments

goesrecv -v -i 1 -c ~/goesrecv.conf

This will show output every second that looks something like this:

...
2018-09-15T21:52:03Z [monitor] gain:  8.44, freq: -2121.4, omega: 2.589, vit(avg):  2400, rs(sum):  0, packets: 0, drops:  55

The vit(avg) stat shows the average viterbi error rate over 1 second interval (if running with -i 1).

If there's no signal, the vit value should be over 2000. When signal is stronger it should decrease.

This should help you point the antenna correctly. Slightly rotate the dish right or left and note whether the vit errors are increasing or decreasing.

Once you're at the local error minimum, perform the same process to find the minimum error rate while slightly adjusting the vertical angle.

When the vit errors are at their lowest, you've pointed the antenna. Double check the antenna position again with a compass to make sure you're pointed at the intended satellite.

If you can't pinpoint the signal even after precicely adjusting the antenna, flip the dish 90 degrees and try again.

9. Restart goesrecv and play around with the config parameters.

If your vit errors are under 400, and you're observing no packet drops, you're all set!

If the average errors are at around 1500-1800, try the following:

  • Terminate and restart goesrecv. This should allow it to readjust the gain and frequency offset to get a better read on the signal.

  • Cool the Raspberry Pi and the RTL-SDR dongle. I've noticed that temperature might significantly affect reception quality.

  • Play around with goesrecv.conf parameters. Try adjusting the gain and sample_rate. For the NooElec XTR or other E4000 tuners, you might need to set your gain to 10 or below.

Once you decreased the error rates, but your vit is still over 400, try making very slight adjustments to the antenna again.

10. Process packets into images

While goesrecv is running, in a separate session, run:

goesproc -c /usr/share/goestools/goesproc-goesr.conf -m packet  --subscribe tcp://127.0.0.1:5004

Once goesproc receives enough packets, it will start writing images and text to the locations described in /usr/share/goestools/goesproc-goesr.conf.

Writing: ./goes16/m2/ch13/2018-09-15/GOES16_M2_CH13_20180915T231750Z.jpg
Writing: ./goes16/m2/ch13_enhanced/2018-09-15/GOES16_M2_CH13_enhanced_20180915T231750Z.jpg
Writing: ./goes16/m2/ch02/2018-09-15/GOES16_M2_CH02_20180915T231750Z.jpg
Writing: ./goes16/m2/fc/2018-09-15/GOES16_M2_FC_20180915T231750Z.jpg
Writing: ./goes16/m1/ch07/2018-09-15/GOES16_M1_CH07_20180915T231820Z.jpg
...

11. TODO: Automatically restart goesrecv, store images on S3, send metrics to statsd and Grafana, and make videos!

Stay tuned!

@Romulo-jose
Copy link

Good evening everyone. I have a problem running the command line: goesrecv -v -i 1 -c ~/goesrecv.conf.
When executing in the terminal it returns the following error: terminate called after throwing an instance of 'std::invalid_argument'
what(): Error: line 6: no equal?
Abortado
Have any of your colleagues already gotten this error or do you know how to fix it?

Thank you all.

@marquitosweather
Copy link

marquitosweather commented Oct 2, 2020 via email

@Romulo-jose
Copy link

Good morning Marcos,

I tried all your suggestions and the error continues ...
My system is installed on a Linux Mint machine. I don't believe that is why. I have a friend who has the same configuration as mine and this error does not appear.

@emanuelcaldeira
Copy link

Hi!
I have a problem running the second command

goesproc -c /usr/share/goestools/goesproc-goesr.conf -m packet --subscribe tcp://127.0.0.1:5004
terminate called after throwing an instance of 'std::runtime_error'
what(): Failure at /home/pi/goestools/src/goesproc/handler_goesr.cc:138, Unhandled key in ancillary text "grid_mapping"
Abortado

What it could be?
Thanks

@mudhwk
Copy link

mudhwk commented Nov 14, 2020

Very Nice writeup - it took about an hour to configure the pi, then had a few minor glitches, then it "just worked!"...

I'm using an RPI 4, with an rtl_sdr, Nooelec sawtooth filter and this antenna: ttps://excel-wireless.com/product/1710-1880-mhz-grid-parabolic-antenna-20-dbi/

Looking through this thread, I see 2 other folks had the same glitches I did, and I want to share my solutions:

(>Romulo-Jose) what(): Error: line 6: no equal? Make sure you don't have the "cat <<EOF and EOF lines at the beginning and end of your .conf file. They were intended to help populate the file, but if you cut and pasted and grabbed them by accident you will get this error.

(>my viterbi rate doesn't drop below 2200) I had the same problem, and there are obviously many causes. In my case, the gain of "5" in the config file was absurdly low. Raising it to 55 suddenly dropped my error rate to 260 or so and images started pouring in.

Thanks for a very nice project!

--al
WB1BQE

@W1ZFB
Copy link

W1ZFB commented Feb 15, 2021

I have Syncthing loaded on my PI and it is working however I wanted to have it automatically start up using Amdorj's process (step 11). Below is what I did

Create the service to start synthing

sudo nano /etc/systemd/system/startsyncthing.service

Copy and paste the following

[Unit] Description=Start syncthing after network is loaded as user pi
After=network.target
[Service]
User=pi
Group=pi
Type=oneshot
ExecStart=/usr/bin/syncthing
[Install]
WantedBy=multi-user.target
#Then
sudo systemctl enable startsyncthing

But it's not working as I have limited experience could some tell me what I need to do to make this work? This is for my GOES weather project which is working.
Mike
mzfb@aol.com

@ikatkov
Copy link

ikatkov commented Apr 13, 2021

To ppl who came here from web search.
If you are building your own feed element or repairing some odd parabolic antenna:

The parabolic antenna's focal point is the same for any freq. You can measure the one you got and compute the focal point. You will use it later. You need to put the antenna phase center into the focal point. If you decided to build a dipole - the phase center is where there is a gap between dipole legs. If you are building something else like a horn antenna - you probably know what you are doing anyway.
You don't have to have wide brass/copper metal bands as well. The bigger the cross-section the more broadband your feed element will become. You might just solder extension copper wires like 12AWG to the brass band you got with your antenna.
Do that first and then cut the excess to make the legs the same.

The dipole gap does matter at this frequency, you need to have a dipole ~ 88.5mm end to end, including the gap.
You need to be precise by measuring, but also don't fret too much, as you will not be able to make the antenna resonant on precisely 1694MHz. This dipole will be broadband. It's not the resonance you are aiming for it's an impedance match. If you have an antenna analyzer for microwaves - it will help. At the moment of writing, you can buy them off Amazon ~$100 (nanoVNA v2)

Make legs of the dipole L/4 i.e. ~44mm. It's the matching network to 50Ohm impedance coax cable. You need to adjust them to be precisely L/4 length. Note they are soldered to the braid. Keep the solder blob small and precise otherwise, you might ruin the L/4 length. This matching network is needed to compensate for all the imperfection of your cut, solder, measuring, details of the surrounding like capacitative coupling to the trees and antenna mast. The antenna would work without it, but if you add it - it forces more power into the coax inner conductor and less power on the outer layer of the coax braid.
if you are curious - https://en.wikipedia.org/wiki/Quarter-wave_impedance_transformer

Also, note the "secondary reflector", in this grid antenna design it's not a reflector in the sense - another parabolic reflector - it's a "reflector" as in two-element Yagi. https://www.electronics-notes.com/articles/antennas-propagation/yagi-uda-antenna-aerial/theory.php
The original antenna designer used it to adjust antenna impedance back to 50. That is why it's placed in different locations in different antenna manufacturers and also has different shapes. Why 50? - https://www.microwaves101.com/encyclopedias/why-fifty-ohms

As soon as you started messing with the dipole you got - you ruin that balance. If you have the vector analyzer you can measure it and decide if you need extra capacitance or extra inductance. In practice, though, it's all the same - you will be bending and moving this metal piece on the boom until you find the local minimum at the frequency of interest.
It changes your dipole impedance that is why different people have to move it around and bend different ways. If you have nanoVNA you can observe how it changes reflected power (SWR) if you don't - you will have to look at vit(avg) in goestools/goesrecv output and bend/move it until you find the minimum.

The dipole does need to be in the paraboloid dish focus, so you will either need to add a spacer (or 3d print a new radome/enclosure) moving it out of focus is not the end of the world, your signal will drop slightly.
So all the little errors - wrong dipole measurements, wrong cuts, uneven legs, wrong solder job, wrong matching, lossy coax, bent out of shape paraboloid dish, wrong pointing, wrong skew, trees and structure obstructing the view, and finally the wrong focus - they all add up. If you start with a strong signal you have quite a budget for these errors. If you start with a weak one - you might not get enough to decode after all.

The grills of the dish also act as the polarization filter. You need to make dipole parallel to them. Some people do not bother and take a slight penalty of the higher noise floor. After all, you aiming to get a signal "good enough" to be parsable and not to make some ideal antenna.

There is no way to do everything precisely with the crude instruments you are likely to have, so you will end up trying and retrying anyway.

@jaaronson
Copy link

well since you said it wasn't a good design I took it off of here, interesting with all the mistakes that it performed way better than it did before the modifications, there was much less signal and I couldn't decode any packets before I did the mods. Thanks for your input...

@ikatkov
Copy link

ikatkov commented Apr 14, 2021

@jaaronson I'm sorry. I never said your design is bad. The ultimate test is always - "Does it work?" Yours is working. Consider putting your pictures back, it will help "the next guy".
In my comment, I was summarizing (to the best of my knowledge) the theory behind this particular antenna design to help people that come here from websearch.

@rtromeo
Copy link

rtromeo commented Apr 15, 2021

This has been Working Wonderfully with the Goes-16 Sat Kit from Amazon, I have been able to get the VIT's around 60, with no packet loss, I am using a headless Raspberry Pi setup. I have been getting Spectacular Pictures ... BIG THANK YOU for this Write UP !!!!!!!

Question, anyone know how to add SUVI (Sun / Solar images), as well as GLM (for lightning) ?, think that would be really cool !

@amdorj
Copy link

amdorj commented Apr 16, 2021

Question, anyone know how to add SUVI (Sun / Solar images), as well as GLM (for lightning) ?, think that would be really cool !

Those are unfortunately only included in the GRB (GOES ReBroadcast) downlink and are not present in the HRIT downlink.

@sativapie23
Copy link

Does anyone have any tips on setting GAIN? I cant get vit under 700. Every time I set GAIN, it just sticks to 5, no matter what I put. I can modify the goesrecv.conf and adjust the sampling rate by adding a few 0s. I do this and it instantly throws and error when starting goesrecv and it stops itself from running. So I know modify config file is working since the bad sample rate clearly was read by goesrecv. Leaving everything in working order and changing the GAIN setting, it does nothing. Ive tweaked and tuned my antenna placement as best I can for now and then started to mess with GAIN and sampling rate. But for whatever reason I cant get it to adjust. Thanks for any help.

@rtromeo
Copy link

rtromeo commented May 15, 2021

Does anyone have any tips on setting GAIN? I cant get vit under 700. Every time I set GAIN, it just sticks to 5, no matter what I put. I can modify the goesrecv.conf and adjust the sampling rate by adding a few 0s. I do this and it instantly throws and error when starting goesrecv and it stops itself from running. So I know modify config file is working since the bad sample rate clearly was read by goesrecv. Leaving everything in working order and changing the GAIN setting, it does nothing. Ive tweaked and tuned my antenna placement as best I can for now and then started to mess with GAIN and sampling rate. But for whatever reason I cant get it to adjust. Thanks for any help.

I am using the Nooelec Satellite Bundle from Amazon, with the always on NESDR SMArt Tee Bias-T and the SAWbird GOES filter LNA .
So my Config is exactly as listed above. and works Well, I set up my antenna in the Spring and as the tress bloomed I gradually lost signal as best VIT went up to 1200 (No good), found a new spot, for year round, I now have noticed my VIT varies from 80 to 120, depending (I believe on temperature), but my GAIN, also fluctuates as well, anywhere from 3.9 to 5.9 I have seen. I am assuming the issue you might have could be with your SDR.... but not certain. of course what your full set up is......

@sativapie23
Copy link

sativapie23 commented May 15, 2021 via email

@autotunafish
Copy link

autotunafish commented Jul 28, 2021

Was unable to build on latest Ubuntu 20, problems with libusb-1.0 and libopencv-dev. Changed to libusb-1.0-0 and seemed to work but couldn't work out opencv.

Changed to Ubuntu 18 and no problemo.

Edit: opencv error may have been a fluke, libusb-1.0-0-dev

@halifax57
Copy link

Might lxe or some other kind soul update the whole script? Been chasing down issues like autotunafish but cannot get it to run to the end.
Any help most appreciated. TIA.

@jchisholm59
Copy link

Hey Halifax57 judging my the "Old Bridge" and Dockyards on your profile pic you are indeed also in Halifax.. Have you had any luck with hitting Goes-16 ?
I'm just going by what I see as the visibilty "cone" on https://agsattrack.com/ and unless I'm wrong (which I hope I am) Goes-16 probably can't be seen from here.
Just ordered an antenna and SAW filter so again, hope I'm wrong!

Cheers

Jim

@pumatrax
Copy link

pumatrax commented Apr 9, 2022

I get an error when running goesproc -c /usr/share/goestools/goesproc-goesr.conf -m packet --subscribe tcp://127.0.0.1:5004

VC 8: M_SDU continuation failed; 34931 byte(s) needed to complete M_SDU, 188 byte(s) available

Has anyone overcome this issue?

@matirko
Copy link

matirko commented Apr 11, 2022

@pumatrax
Copy link

@pumatrax I'm gonna give this a shot when I get a chance https://www.reddit.com/r/amateursatellites/comments/sf2yod/goestools_updated_now_maintained_with_binary/

Oh thanks, I will try as well.

@matirko
Copy link

matirko commented Apr 12, 2022

@pumatrax
Same issue :( I'll reach out to the owner of that forked repo

@pumatrax
Copy link

@matirko same here. been at it all day. Had a weird issue with the sdr not receive the signal properly but once I got that fixed by redoing rtl-sdr libs I received the same M_SDU. Surprised the dev hasnt chimed in yet. :(

@pumatrax
Copy link

@matirko

When hunting for the error in the sorce code files of goestools and found it located in virtual_channel.cc. I am not a programmer but it seems to me this M_SDU function is not being told it has enough memory. Looks like its getting bytes available from this first line of code.

// Extract "first header pointer" field from M_PDU header
firstHeader = ((data[0] & 0x7) << 8) | data[1];

// Skip over M_PDU header
data += 2;
len -= 2;

// Resume extracting a packet if we still have a pointer
pos = 0;
if (tpdu_) {
// Double check that the number of bytes left to read correspond
// with the first header pointer. The latter takes precedence.
if (tpdu_->headerComplete()) {
auto bytesNeeded = tpdu_->length() - tpdu_->data.size();
// If the first header pointer is 2047, there is no additional
// header in the VCDU and we can read the entire thing.
auto bytesAvailable = (firstHeader == 2047) ? len : firstHeader;
if (firstHeader != 2047 && bytesAvailable < bytesNeeded) {
// Don't log error message for fill packets.
// On the GOES-16 HRIT feed these can expect 6 more bytes
// if they are aligned on the VCDU boundary. I suspect this
// number comes from the the 6 header bytes in a VCDU and
// that this is a mistake in the HRIT feed assembly code.
if (!(bytesAvailable == 0 && bytesNeeded == 6 && tpdu_->apid() == 2047)) {
std::cerr
<< "VC " << id_
<< ": M_SDU continuation failed; "
<< bytesNeeded << " byte(s) needed to complete M_SDU, "
<< bytesAvailable << " byte(s) available"
<< std::endl;
}
tpdu_.reset();
} else {
pos += tpdu_->read(&data[pos], len - pos);
if (tpdu_->dataComplete()) {
process(std::move(tpdu_), out);
}
}

@marquitosweather
Copy link

Hi everyone, I'm selling my antenna. Moved to an apartment so I have nowhere to install it. :(

https://www.amazon.com/dp/B08NLDTDM7/ref=cm_sw_r_apan_glt_i_VSVGRNSEQ1KZEWW94K15

I have it in storage and it's in pretty good condition.

@IcedOdin
Copy link

I finally got my custom VM setup. With my VM running Debian my antenna set to AZ .197.794 -N ELV. 37.695 Polarization vertical and skew 7 with nooelec sawbird+GOES I am getting a VIT of 77. Very solid data stream great pictures. If anyone wants the VM let me know i will create a file share. the sdr is a SMArtee XTR

@wwoofbum
Copy link

Compiled and installed under DragonOS, "an out-of-the-box 22.04 aarch64 Raspberry Pi based operating system."

goesrecv running fine (vit avg 400-500 with few to 0 dropped packets) with Nooelec goes dish, sawbird, SMarTee Xtr.

goesproc reports: "Invalid configuration...includes directives to add a map overlay, but goesproc was compiled without the proj library..."

So, two questions: How to modify goesproc-goesr.conf to remove (temporarily) the (currently) unsupported directives? And...

I am pretty new to managing local compilation of applications in Linux. I am basically following recipes, without much understanding. I would like to re-compile/install, after installing the proj library, but don't know where to start. Specific directions for re-compiling/installing, and/or directions to relevant references will be appreciated.

@wwoofbum
Copy link

Rebuilt on a Pi 3b. Executing goesrecv -v -i 1 -c ~/goesrecv.conf yields "Illegal instruction"

@wwoofbum
Copy link

Looking at Issues tab of PieterN's github repo: #142 reports the same issue I was having, regarding compiling under Ubuntu 22.04, which is based on Debian Bullseye. PieterN's system requires an old version of PROJ, a library involved with translation of mapping coordinates, that came standard with Debian Buster (PiOS Buster, Ubuntu before 20.xx). The PROJ version that comes with Bullseye is not backward compatible with the old version, so compiling under Bullseye will fail without modification of the make files.

On the other hand, building the system under an older version of Debian (which I did under Ubuntu 18.xx) compiles with no difficulty. Currently receiving images with vit(avg) under 400, 0 dropped packets.

@nmoon88
Copy link

nmoon88 commented Feb 2, 2023

A critical step is missing, generating the goesproc configuration file. Without knowing about this everything else is useless and currently I have goesrecv working along with my modified dish aligned perfectly but don't have a way to decode the packets of data because I am lost when it comes to creating a configuration file for goesproc. Basically what I want to do is decode all products from GOES-16 and place them into individual folders based upon the product type. Currently I can't find anything on creating goesproc configuration files to do this

@itstheburns
Copy link

I have tried multple Pis, SD cards, from SSH and directly and 32/64 bit versions of Raspian. Built the SD card using Raspberry Pi Imager. My install hangs and totally locks up the pi when it hits Scanning dependancies of target goesproc. It won't get past 92% I have pi 3b+. Any thoughts?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment