This code is highly accurate, if provided with proper data. Recently, I collected side-by-side data from plan-13 and the respected Predict program and compared their results for satellite latitude and longitude. A day's worth of data regarding CO-57, a low and fast-moving satellite, resulted in a worst-case difference of 39.5 km between plan-13's predicted latitude and longitude and that of Predict. On average, the difference was 14.5 km. (The actual results might be better than this. Since both programs were called independently and each refer to the system real-time clock, it is likely that occasionally the real-time clock turned over a second between one program running and the other. )
Though Plan-13 is a well-established program, I have plans to add to it. When N1VTN ported the BBCBasic version of Miller G3RUH, he did not include the code required to determine if a satellite is in eclipse. This would be useful, however, for tracking AO-07 and Delfi C3, which will not operate in eclipse.The doppler shift routines are more complicated than those in the C code base. They needed to be rewritten because of the lack of a true 'double' variable type in the ATMega/Arduino platform. Rather than undergoing the expense of importing the int64_t libraries to do 64-bit integer math (adding about 3 kB), I made an specialized routine that uses the long datatype. This makes the following assumptions:
Highest doppler shift factor: 1.15E-5 (= 5000 Hz excursion at 435,240,125 Hz)
Lowest doppler shift factor: 2.30E-9 (= 1 Hz excursion at 435,240,125 Hz)
Under these circumstances, if we truncate the frequency value by dividing it by 100,000, the worst error at this same frequency is under 2 Hz. (99,999 * 1.15E-5 = 1.15)
Unfortunately, using the
unsigned long
variable type for frequencies means that the maximum frequency that can be handled by this code is 4,294,967,295 (2^32 - 1). It would be nice to be able to work with, say, S-band downconverters, so I will probably re-address this issue later if there is some room left.
TleEEPROM
This library allows the Arduino to store and access keplerian element sets with its onboard 1kB EEPROM. It is complemented by a small utility program written in C (currently only for Linux/Mac OS), that packs the data on a host computer and communicates it reliably to the Arduino.
Here are the calculations of the storage technique. In every two-line element set, the element format is very regular. In fact, the only thing that keeps a database of TLEs from being a simple lookup table is the variable length of the satellite names. Now since we probably want to communicate this name in CW and therefore long names will be a bother there, too, the system described here limits the name of satellites to 6 characters long, with null characters filling unused bytes.
The following is not quite up to date, but gives the general idea:
In this case, each TLE takes up 50 bytes. This is because the elements comprise 11 double numbers, which each take 4 bytes. 44 bytes + 6 bytes for name = 50 bytes per bird. If all we need to determine is the location of the bird, then we can use the EEPROM to track 20 of them.
If, however, we want to be able to do doppler tuning on these satellites, additional information needs to be stored and associated with the tles.
address (pointer into EEPROM address of keps = 2byte int),rxUp(long),rxDown(long),modeup(byte), modeDown(byte),offsetUp,offsetDown
This totals 20 bytes.
The simplest approach would be to give each satellite a single one of these mode-lines. But for some satellites like AO-51 that change their mode frequently, this would cause the user to have to re-burn the EEPROM too frequently. I've concluded that useres need to be able to associated an arbitrary number of modelines with the satellites. The following overall storage layout makes this possible:
0 | 1 |
2 | 3 |
4 | (4 + 50 * tleCount ) |
(5 + 50 * tleCount ) | (25 + 50 * tleCount ) |
Bytes 0 to 1:
tleCount
an integer indicating the number of 50-byte tle sets stored in the EEPROM.
Bytes 2 to 3:
modelineCount
an integer indicating the number of 20-byte modelines stored in the EEPROM.
Bytes 4 to 54 tle of the first bird, etc.
Bytes 4 to (4 + 50 *
tleCount
): tles
Bytes (5 + 50 *
tleCount
) to (25 + 50 *
tleCount
) first modeline, etc.
Byte (5 + 50 *
tleCount
+ 20 *
modelineCount
) last byte in data set.
CW
This is a morse-code signaling library. Although there are many such libraries already published for the Arduino (including the one in the library tutorial), none allow the caller to control the output through callback functions. My goal was to signal satellite positions, etc. with a small speaker. Rather than write write a different library for every technique of signaling, I wrote this library with two callback functions, one to start the signal, the other to end it. The example sketch signals morse through a blinking LED.
FT817
This library controls a FT-817 amateur radio from Yaesu by means of its CAT commands.
Ansiterm
This library provides functions for transmitting ANSI terminal codes on the Arduino 'Serial' object. Alongside obvious functions like reset(); and boldOn();, it offers higher-level functions like xy(x, y), which sets the cursor at any location, and fill(x1, y1, x2, y2, YELLOW), which fills the background of a rectangle within the terminal with the stipulated colour. Its example sketch shows what it can do.
You should ensure that you are viewing this sketch in an ansi-complient terminal. The serial terminal packaged with the Arduinio IDE is not ansi-compliant. Most MacOs and Linux terminals are fully compliant. On windows, it is a mixed bag: I like RealTerm, though it will not allow you to change the colour of the characters printed in the terminal, so the setForegroundColor(BLUE);
function will not work.
Projected Work
I plan to write a library to control the Kenwood TH-D7A, another radio commonly used for portable satellite communications. I suppose it would be wise to write a superclass for this library and the FT817 library.