When I was working with the NC Nearspace group on our high-altitude balloon, we experimented with two different methods of tracking it once aloft: ham radio APRS, and a commercial system called “SPOT“.

We had some early failures with APRS.  But over time, we have found that it’s a pretty nice technology, if you use the proper equipment.

APRS, or “Automatic Packet Reporting System”, is a system that passes data packets over radios. It can be used for passing text messages, but most people use it for telemetry: tracking a vehicle’s position with a GPS, or on a weather station that broadcasts its weather readings every so often.

Since we have been playing with APRS on our balloons, I wanted to learn more about it. I have been keeping my eyes open for a reasonably-priced handheld radio that can encode and decode APRS packets. Sure, some people use a special radio modem (called a “TNC”) to do the encoding/decoding, but it’s important to me to have the modem and the radio in a single package, so I won’t have a big tangle of wires. This week, one such radio popped up on eBay, and so I bought it. While I waited for it to arrive, I did some homework on APRS and what it could do.

Building an iGate at home

My "mobile" radio at home

I already have two 2-meter radios: a small handheld “handy talkie” and a larger “mobile” radio that is designed to be installed in a car. So I tuned the mobile rig to 144.390 MHz and listened. It was a lot of static, with occasional squawks of data.

Most of the time, if you wanted to decode the squawks, you would buy a packet TNC (modem) to convert the squawks to data, and you’d hook the modem to a computer to use that data. But then I read an article about using your computer’s sound card to encode and decode the packets directly, with no modem at all. Heck, I was sitting around at home waiting for my new handheld-with-built-in-modem to arrive. Why don’t I try to do this modem-less setup?

Look, Ma, no modem!

The first thing I did was hook the speaker output from the radio to my computer’s “audio in”. Optionally, I could have hooked the computer’s “audio out” to the microphone input of the radio. That second step is more complicated than you’d think, because I would also need to hook SOMETHING — maybe a parallel port pin — to the radio’s “push to talk” or “PTT” to turn the transmitter on before it’s ready send a squawk of data over the air.  You really don’t want to just let it transmit all of the time… because other people are using that radio channel, too.

My modest Linux server

I chose the simple receive-only option, setting up my Linux-based server to “listen” to the radio. I downloaded a package called soundmodem, which is a APRS decoder program. It listens to the noise and the squawks, and it outputs a stream of decoded data.

Soundmodem is hard to set up on a headless server, because the normal setup process involves running a graphical configuration program called “soundmodemconfig”.  Since my server is “headless”, I don’t have a monitor or a keyboard or a mouse.  I just connect to it over the network.  So I could not run soundmodemconfig.  So instead, I ran this program on my laptop and I copied the resulting configuration file back to the server. It was a pretty simple XML file that looked like this:

/etc/ax25/soundmodem.conf

<?xml version="1.0"?>
<modem>
  <configuration name="KISS">
    <channel name="Channel 0">
      <mod mode="afsk" bps="1200" f0="1200" f1="2200" diffenc="1"/>
      <demod mode="afsk" bps="1200" f0="1200" f1="2200" diffdec="1"/>
      <pkt mode="KISS" ifname="sm0" file="/dev/soundmodem0" unlink="1"/>
    </channel>
    <chaccess txdelay="150" slottime="100" ppersist="40" fulldup="0" txtail="10"/>
    <audio type="soundcard" device="/dev/dsp1" halfdup="1"/>
    <ptt file="none" gpio="0" hamlib_model="" hamlib_params=""/>
  </configuration>
</modem>

The important parts are where it says it’ll read the audio device /dev/dsp1 and it’ll create a KISS-mode packet device called /dev/soundmodem0.

To start the APRS decoder program, I just run /usr/sbin/soundmodem /etc/ax25/soundmodem.conf &. If it all works, then I can just do tail -f /dev/soundmodem0 and see some packets on the screen, with some header garbage and then some readable payload data with a bunch of callsigns.  That is enough of an indication that the decoding is working correctly.

The iGate software

The second piece of software I installed was a digipeater package called APRS4R. I had read a story about a guy who put a small TNC (radio modem) board inside of a Linksys WRT54G router and turned it into a very small portable digitpeater. He ran APRS4R on the router, and so I figured that this program must be pretty lightweight. So I should be able to run it on my modest Linux server.

APRS4R is written in Ruby (that’s what the “for R” ending means), and it is configured using a single text file. Here is the configuration file that I came up with.

--- !ruby/object:APRS4R::APRS4RConfiguration
version: 1.0.2
devices:
  device0: !ruby/object:APRS4R::AX25SocketConfiguration
    name: rf0
    type: AX25Socket
    enable: true
    remote:
    deprecated:
    call: KR4JB
    device: /dev/soundmodem0
    port:
    baudrate: 9600
    mode: kiss/tnc2/northlink
    speed:
    duplicatePeriod: 20
    timeout:
    parameters: !ruby/object:APRS4R::KISSDeviceConfiguration
      name: kiss port
      type: KISSDevice
      enable: true
      remote: false
      deprecated: false
      device: /dev/soundmodem0
      baudrate: 9600
      port:
      speed: 1200
      timeout: 300
      txdelay:
      persistence:
      slottime:
      duplex:
  device1: !ruby/object:APRS4R::ISSocketConfiguration
    name: is0
    type: ISSocket
    enable: true
    remote:
    deprecated:
    hosts: [third.aprs.net]
    port: 14580
    username: KR4JB
    filter: "# filter m/100"
    duplicatePeriod: 20
    timeout: 60
plugins:
  plugin1: !ruby/object:APRS4R::BeaconPluginConfiguration
    name: igate is beacon
    type: BeaconPlugin
    enable: true
    remote:
    deprecated:
    device: is0
    period: 1200
    offset: 30
    message: !ruby/object:APRS4R::APRSMessage
      source: KR4JB
      destination: AP4R10
      path: []
      payload: "!3546.30N/07852.07W-&APRS4R CARY NC"
  plugin10: !ruby/object:APRS4R::GatewayPluginConfiguration
    name: rf02is0 Gateway
    type: GatewayPlugin
    enable: true
    remote:
    deprecated:
    call:
    inDevice: rf0
    outDevice: is0
    localOnly:
    replacePath:
    path:

My house on the map at APRS.FI

It’s kind of verbose, but it basically defines two devices called “rf0” (the radio) and “is0” (the internet).

Then it defines a few “plug-ins”, which are actions. I use two actions: a beacon that sends my call letters and position to the APRS internet site, and a gateway that forwards (some) packets from the radio to the internet.

If I had hooked up my radio to transmit as well as receive, then I would have also transmitted a beacon on the rf0 channel, and probably forward some of the incoming internet packets to the radio.

The only tricky bits in this file were:

  • For the “is0” destination, I chose a random host from a list that I saw in example files. Mine is “third.aprs.net”.
  • The “destination” in the beacon is AP4R10. That is the code for the APRS4R software package. I have no idea why I send my beacons TO some oddly-named station to signify that I am using this digipeater software package.
  • The “payload” string in the beacon is "!3546.30N/07852.07W-APRS4R CARY NC". It consists of a few parts: a bang, my latitude, slash (means “primary icon set”), my longitude, minus (means “house icon” in the primary icon set), and the rest is a comment with my software package name and my location city and state.
  • I had a hard time choosing which SSID (dash number after my callsign) to use. I finally decided that it does not really matter, because there are several conflicting conventions. But I like using “KR4JB” with no suffix to mean “home”. I will use “-1” for my new handheld and “-2” on the (internet-only) OpenAPRS app my iPhone.  If I buy more toys, they will get higher numbers.  Balloons typically use “-11”.

Stuff I didn’t do – and why

There were other APRS4R plugins that did stuff like full two-way digipeating and sending beacons on the radio. But my station is a one-way iGate, so I did not need them. My station forwards packets that it hears on the radio to the internet. It does not forward internet packets to the radio.

And my station is not a digipeater, it does not retransmit packets that it has heard on the air.

I run my station as a receive-only iGate for two reasons:

  • Most immediately, I did not have a cable to hook into the microphone jack of my mobile radio, and rigging up the PTT looks like a hassle.
  • More importantly, you need to coordinate with other digipeaters and gateways around you before you start transmitting packets over the air.

This has all been a lot of fun, and I have learned a lot about packet radio.  Since I went down a few wrong paths, I learned a lot of stuff that was not immediately applicable.  But in this article, I have summarized the parts that got my receive-only iGate working in a single afternoon.

Now I am waiting for my new APRS-capable radio to show up!