Marine VHF Scanner

Intro

To provide a bit more information about ship movements and communication on my Drierivierenpunt live stream I’ve installed a marine VHF scanner alongside the camera.

Required items

If you’d like to build your own you need a couple of items to get this working.

  • A SBC. I’ve used an obsolete Orange Pi Zero. But a Raspberry Pi 1/2/3/4 would work better because of GPU acceleration.
  • A software defined radio. I’ve used a basic RTL2832U RTL-SDR
  • RTL-Airband to scan the frequency band
  • VHF/UHF antenna

Armbian

Download Armbian

Download Armbian (for Orange Pi Zero) to get a basic setup going and install the following dependencies

sudo apt install build-essential libmp3lame-dev libshout3-dev libconfig++-dev libfftw3-dev librtlsdr-dev libsoapysdr-dev

RTL-Airband

Checkout the RTL-Airband source

git clone https://github.com/szpajder/RTLSDR-Airband.git
cd RTLSDR-Airband
git checkout unstable

Compile the source with Narrow FM and SoapySDR support

make PLATFORM=armv7-generic NFM=1 WITH_SOAPYSDR=1

Install RTL-Airband

sudo make install

Edit configuration file

After it installs edit the default configuration file located at:

sudo nano /usr/local/etc/rtl_airband.conf

And replace it with the following configuration settings

devices: ({
  type = "soapysdr";
  device_string = "driver=rtlsdr,rtl=0";
  gain = 30;
  mode = "scan";
  sample_rate = 2.4;
  antenna = "RX"
  channels:
  (
    {
#      squelch = 30; #squelch global
      freqs = ( 156.8, 156.2, 160.8, 157.1, 161.7, 156.575, 156.725, 156.975, 161.575 );
      squelch = ( -1, -1, -1, -1, -1, -1, -1, -1, -1); #squelch per channel
      modulation = "nfm";
      labels = ( "Nood", "Heerjansdam Schip", "Heerjansdam Wal", "Merwedebrug Schip", "Merwedebrug Wal",  "Stadsbrug", "Jachthavens", "Dordrecht Schip", "Dordrecht Wal" );
      outputs: (
          # For local IceCast server
        {
          disable = false;      # set to true to disable
          type = "icecast";
          server = "127.0.0.1";
          port = 8000;
          mountpoint = "local";
          name = "Drierivierenpunt";
          genre = "Marine";
          username = "source";
          password = "password";
          send_scan_freq_tags = true;
          description = "Local IceCast Server";
        },

          # For remote BroadCastify server
        {
          disable = true;      # set to false to enable
          type = "icecast";
          server = "audiox.radioreference.com";
          port = 80;
          mountpoint = "broadcastify-mountpoint";
          name = "broadcastify-name";
          genre = "broadcastify-genre";
          username = "source";
          password = "broadcastify-password";
          send_scan_freq_tags = true;
          description = "broadcastify-description";
        }
      );
    }
  );
 }
);

Parameters

RTL-Airband supports two modes

  • Scan – Scan a range of predefined frequenties and pipe them into a single audio channel
  • Multichannel – Watch a range of channels and pipe them into multiple audio channels

As you can see in my configuration file I’ve set it to scan mode. There are a few things you need to change for your particular use case. Obviously you need to set your own frequencies and labels but mainly the following settings need to be adjusted for each individual user:

  • Gain – Receiver sensitivity. Too low, you won’t receive any signal. Too high results in a lot of static noise.
  • Freqs – Frequency list of AM / NFM channels of interest.
  • Squelch – Noise reduction level. Set to -1 per channel for automatic mode. Or manual is a certain channel is too strong

Finetuning

To verify if all channels are set to the right gain and squelch mode run RTL-Airband in the foreground and verify that no particular channel is too strong so that RTL-Airband doesn’t ‘sticks’ to that particular channel.

rtl_airband -f

Which gives the following result

 156.800                                                                       

 173/109  161.575 
 129/109  161.575 
 133/110  156.800 
 165/110  156.800 
 185/155  156.200 
 349/155  156.200 
 458/121* 160.800 
 186/121  160.800 
 205/123  157.100 
 164/123  157.100 
 177/113  161.700

The first column indicates the received signal snr, second column the amount of squelch applied and the third column the active frequency. If a signal is applicable for being sent to Icecast or Broadcastify an asterisk is attached as you can see at frequency 160.800. If a signal is too strong you will see asterisks continuously and you have to lower the gain or raise squelch.

Broadcastify

Final result of my setup can be heard at Broadcastify (Dutch)

Icecast2

To use a local Icecast2 service instead of Broadcastify follow these steps.

sudo apt update -y && sudo apt upgrade -y
sudo apt install icecast2 -y

A screen appears asking you if you’d like to configure Icecast2. Enter ‘Yes”

  • Icecast2 hostname: localhost
  • Icecast2 source password: <enter a password>
  • Icecast2 relay password: <enter a password>

To start the Icecast2 service and enable it on startup

sudo systemctl start icecast2
sudo systemctl enable icecast2

Check is the Icecast2 service is running

sudo systemctl status icecast2

And finally point your browser at http://localhost:8000 to view the incoming stream under “Mountpoint list”

Enclosure

An optional step i took is to design an enclosure for the Orange Pi Zero and the RTL-SDR.

nl_NLDutch