Some time back, we acquired a BigIR antenna. This antenna can automatically tune itself to some optimal length according to the desired frequency. For extra convenience, the controller of the antenna can be made to track the current frequency of the transceiver. Our current transceiver setup makes this a bit of an hassle, however, since we want all our transceivers to have the possibility to transmit on all antennas, and this would require a rather weird CAT (computer assisted transceiver) network.
We therefore wanted to develop a software-based system more suited for our needs. Before we could do that, we needed to be able to arbitrarily control the SDA 100 controller from a computer.
Late Saturday afternoon struggles
We first thought we would have to emulate a radio and implement full CAT control for this fake radio system that then could communicate with SDA100 through SDA100’s transceiver interface. We got as far as creating the directory
fake_transceiver and open
ic9100.c in the Hamlib source code in order to figure out how CAT is implemented on the other end, until LA3WUA Øyvind luckily found out from the specifications that a far simpler communication protocol is available.
Connecting a standard crossed serial cable from a computer to the “Data OUT” port makes a serial interface available. Here, we’d just have to send
?A\r in order to obtain the current frequency, and
@A\r followed by a hexadecimal representation of the frequency in order to set the current frequency. Perfect! A simple interface for simple people like us. We found some closed-source GUI software programs like
PstRotatorAz that had this implemented, but did not really fit our purposes. We therefore borrowed a serial cable and serial-to-USB-converter from our local information technology committee, and set up a serial interface in order to hack together something ourselves.
Despite some failure, we finally managed to send
?A\r to the controller and get
@A\x00\x15\x7f\xe8\x00\x179c\r back. Out of desperation, we also found that sending the exact same string back would set 1409000 as the frequency if the controller was at another frequency, which meant we’d only have to figure out what to replace and not have to decipher the entire documentation. After a wild ride, we were able to figure out that 1409000 could reproduce
struct.pack('>i', 1409000), and we were able to successfully both set and get frequencies to and from the controller.
Since we had such difficulty finding working examples except for closed source binary applications from Windows (which were, however, helpful in verifying that remote control of SDA100 worked fine), we are making our code available on GitHub for others to find when they start having the same desires and/or frustrations as us.
The Python module we’ve developed can be found here: https://github.com/bjorgan/steppir. We plan to use this for a system where we’ll sniff the current desired frequency from N1MM or similar and push it to SDA100 when desired.
We create a serial interface by
ser = serial.Serial("/dev/ttyUSB0", 9600)
and ask for the current frequency by
This produces 11 bytes which can be read by
message = ser.read(11)
The actual frequency is located at zero-indexed positions 2-5, while the other bytes are related to motor status and versioning. Converting the frequency bytes to an understandable number can be done by
frequency = struct.unpack('>i', message[2:6])
which would be in deca-Hertz. This is converted to Hertz by multiplying by 10.
Setting a new frequency is simply done by converting a given frequency to a hexadecimal byte array by
hex_freq = struct.pack('>i', int(frequency))
and then constructing a set command by
cmd = b'@A' + hex_freq + b'\x00\x179c\r'
We obtained the last part (
\x00\x179c) from messages we got back from the controller. We didn’t bother figuring out how to construct valid bytes here since the documentation was confusing and that set of bytes apparently worked fine. B)
Finally, we’ve encapsuled the above code in a Python module, so that you’d just have to clone the GitHub repository, install the module according to the
README and then set and get frequencies by its more high-level interface. Happy length adjustment!