Using APRS to Determine Repeater Coverage

Here at the University of Texas at Dallas, we operate a repeater on 145.430MHz (K5UTD-R). For 5 years, it sat on the top of a 50′ tower, on a 50′ roof, giving us about 100′ feet above ground level. The end goal is to relocate this repeater to a higher tower on campus. This would make use of an antenna that is ~250′ AGL (if not a little more), as opposed to 100′ AGL. Moving this repeater took a lot of time and coordination, so in the mean time, I determined I would experiment with the APRS network to get a general idea of how coverage will change.

Is this an exact science? Not at all. The predicted coverage relies on many different variables; some are in my control, but most are not. The general principle is that you can make use of stations beaconing their positions, and compare the position packets you hear on one antenna with packets heard on the other. This will loosely correlate with the changes in repeater coverage when the transition is complete. This takes advantage of the APRS network, and the fact that many radio operators run GPS-based tracking systems in their cars. Data from these systems can be received on 144.39MHz.

The basic premise of this experiment is not to see where the repeater can be heard, but rather what the repeater can hear. As mentioned above, this experiment takes advantage of radio operators persistently beaconing their position using systems similar to what they will use for voice communications.

To get an estimate of what the repeater can hear in the “pre-move” and “post-move” configurations, I collected two datasets at two separate times. The first dataset was using an antenna on the roof of the Engineering and Computer Science building. The antenna had similar height and gain to the old repeater antenna. Due to hardware constraints, I could not simultaneously run two IGates to collect data on both antennas. This is one source of error.

The IGate operated on the rooftop tower from Jan 26 to Feb 18. This gave me about 3 weeks worth of data to work with. The IGate operated with the larger tower from Feb 26 to March 8. This was only about a week and a half worth of data.

In this particular setup, the IGate consisted of a Raspberry Pi with the TNC Pi addon board. The radio was an Icom IC-229H, and would beacon two packets every 10 minutes (status/position). The APRX daemon was used to internally log and gate the packets to the internet. The log files are what I used to produce the map seen below.

Parsing the log file is no easy task. As you would have expected, there is a library written in Perl to parse APRS packets, so I wrote the script in Perl. I wrote several filters to only give me packets that I locally received. The filters discarded packets that have been digipeated, came in over the APRSIS servers, were not position packets at all, or had a distance greater than 150 miles. I also wrote in a filter that discarded packets with a speed greater than 100mph, as planes will skew the data.

The Perl script was written to spit out a KML file. It would take several minutes to run, as the log file is >113MB, but would result in a 6MB KML file ready for Google Earth.


The image above is what the script produced. These are the packets that were heard directly from the transmitting station. The blue dots represent the packets heard on the new, higher antenna, while the red dots represent the packets heard on the older, lower antenna.

Obviously the higher antenna heard packets much further out than the lower antenna, with one exception. There is a 60° slice of the old coverage area to the south that is not covered by the higher antenna. This is because the antenna is side-mounted on the north side of the new tower. Aside from that, the higher antenna appears to cover much more of the metroplex than the lower antenna.

Anyway, it was a major project to move the repeater, and a lot of fun to write the script and produce the map while we had downtime. This type of map is easy to produce, and can be done by modifying my script to suit your needs.

PiBalloonII is finished!

After a few months of gathering pieces, writing code, and actually building the payload, PiBalloonII is ready.

The subsystems of PiBalloonII consist of:

  • Raspberry Pi B+
  • uBlox NEO-6M GPS (UART/TTL level)
  • TI TMP513 Power Monitoring System (I2C)
  • DS18B20 Temp Sensor (1-Wire)
  • DHT11 Humidity Sensor (Proprietary)
  • BMP180 Pressure Sensor (I2C)
  • Dorji DRA818V 2M Transceiver (UART/TTL level)
  • 8xAA Ultimate Lithium batteries (in two 4xAA configuration)

Each of the sensors listed above is interfaced to the Pi with their respective protocol. Due to the nature of the sensors, some can update very quickly, while others can take up to two seconds. The barometer can update at 53Hz, while the humidity sensor can update once every two seconds. Because of this, it’s easiest for each sensor to maintain its own log file.

The GPS feeds a program called GPSD. This program makes it very easy to cross-interface multiple types GPS units, while also providing libraries to Python. As learned on the first PiBalloon, it’s best to set the GPS in high-altitude mode. I didn’t know such a mode was needed, and at 12,000 meters, the GPS started sending garbled data. The GPS purchased has a battery, so it’s easy enough to set the configuration on the computer and it will maintain the settings.

The TI TMP513 is the coolest sensor on the payload. It will measure voltage and current, while also providing up to three external temperature sensors. Here is a snippet of the TMP513 log file:

1417641807.10, 12.368, 318, 30.44, 27.00, 20.44, 318, 676
1417641808.31, 12.172, 680, 30.44, 27.38, 178.25, 318, 680
1417641809.27, 11.972, 683, 30.50, 28.19, 255.94, 318, 683
1417641809.93, 11.984, 689, 30.50, 28.25, 255.94, 318, 689
1417641810.58, 11.964, 606, 30.50, 27.62, 248.38, 318, 606
1417641811.68, 12.180, 304, 30.50, 29.25, 255.94, 304, 606
1417641812.74, 12.352, 311, 30.44, 27.00, 18.94, 311, 606
1417641813.42, 12.352, 323, 30.44, 27.00, 19.31, 323, 606
1417641814.08, 12.352, 312, 30.44, 26.94, 19.31, 312, 606
1417641814.76, 12.356, 312, 30.44, 26.94, 19.19, 312, 606

The first column is UNIX epoch time. All log files will share this property. The second column battery voltage, followed by current (in mA). The fourth column is the onboard temperature sensor on the TMP513, then a remote internal temperature sensor and a remote external temperature sensor. The last two columns are idle current and transmit current.

As you can see, a temperature of 255.94C is very unlikely, so I’m going to write it off as RFI problems on the remote sensor. Fortunately, we have a digital sensor for the external temperature readings, with almost no chance of RFI.

The DS18B20, DHT11, and BMP180 measure temperature, humidity, and pressure respectively. I much prefer the DS18B20 to the TMP513 for temperature readings at the moment, as I don’t yet fully understand how to calibrate the 513 and minimize RF interference.

The final item on the payload list is the Dorji DRA818V. This is our 2 meter transceiver. Originally I planned to fly two of these, but after much thought and some technical difficulties, I determined that we could move a similar amount of data, with little compromise, using only one radio. The compromise made pertains to the quality of the SSTV images. Because SSTV can’t use the transmitter continuously, I opted for a 36 second Robot 36 image instead of a 5 minute Scottie DX image. The visual difference is definitely noticeable, but it’s not worth the trouble of maintaining a second transmitter.

To save time, the scripts will compile APRS packets while the SSTV image is transmitting. Theoretically, I could reduce the cycle down to about 45 seconds, but I’m going to opt to keep it at 60 seconds to give the transmitter some time to unkey and cool (ever so slightly).

Using the Energizer Ultimate Lithium Batteries, I’m able to get a predicted 4 hours of use from 8 batteries. The Pi uses about 300mA, transmitter 750mA and we lose 100mA in the voltage regulators, so we can assume 1.25A of draw at any given time. After cross referencing the datasheets, I can predict we will see at least 4 hours, if not more from a given set of batteries.

All of the code can be found on GitHub.