W7IY Antenna Switch Version 3.0

From Stu2
Jump to navigation Jump to search

Version 3.0 uses a Beaglebone white (BB) and is based on version 2.0. W7IY Antenna Switch The new version eliminates serveral switch boxes at the station positions. (blue rotoary switch at each station) The switch software application controls two SixPaks wired in parallel, a RatPak, a StackMatch and two remote tower relays. The server and client code is written in Java/JavaFX instead of C# and Perl. I upgraded the OS on the BB to Ubuntu 13.04 from Angstrom. This greatly simplified the installation and maintance.

The code will be useful in the next project, which is to update the Beverage Switch to use a BB and software client. (We're going to use AutoKey and an App to replace the hardware client controller. The server controller will be replaced with a BB.)


Updated Client Application

The switching system was developed to allow the operators at the W4RM contest station to select an antenna. Before version 3, users had to flip switches and select antenna ports using several hardware control boxes. With version 3.0, the user can select one of several antennas by pressing a button in the client software. There are six rows of antennas and four stations. Notice that in some cases, a row may contain more than one antenna. Two SixPaks are connected together to form a 6 X 4 matrix. One row may be fed by other sets of relays, such as the Stack, which results in more than one antenna per row. Example, the StackMatch feeds row three of the SixPak. It's possible to split the stack into Full, Top/Middle or Middle/Lower.

We have 4 relay boards with 8 relays on each board. These relays control the relays mounted at the tower. We used relays instead of semiconductors (e.g MOSFETS) to help isolate the remote relays in case of a lightning strike. Each relay board contains a latch and a data bus. The data (i.e. which relay to select) is placed on the bus and the appropriate address pin is strobed. The latch drives a relay driver, which in turn energizes a relay. The data/strobe cycle takes about 100ms to complete, which makes the system very responsive. Version 3.0 uses the 8 extra relays (2 per board), which were not used in version 2.0, to control auxillary relays such as the stack match, ratpak and tower mounted relays.

Two relays were used for the StackMatch. One chooses 'AUX', which splits the stack into Top/Middle and Lower. The Top/Middle (T/M) is fed to row 3 of the SixPak. The Lower is fed into a tower mounted 'Y' relay. The Y relay switches between the 10M stack and the Lower (C31L) antenna. The StuPak client takes care of switching the relays.

The user can select 'Release All Mine' to quickly disconnect all the anntennas from the station. There is also a 'Release All' function under the File menu so that we can disconnect ALL antennas from EVERY station at once. This might come in handy when a lightning storm approaches or we are shutting down the contest station.

Special note: The switch uses a bus and address pin architecture to move data to the relay board and latch the relays. The latch is a 74HC573 ocatal latch. We experienced latching errors when one of the remote tower relays was thrown and when we plugged a large load into the AC power strip. This took many hours to track down. Turns out, even though we are essentially using relays to switch remote relays, it was important to include the flyback diodes on the tower mounted relays. The remote relays are 'high side' switched and this problem didn't show up in version 2.0 because the Array Solutions gear includes flyback diodes.

Project Documents

Here are some of the project documents:

BeagleBone Pin Configuration

I struggled with the BB pin configuration method, which changed drastically from the first BB switch. This project uses 3.8.13-bone28, which is available here: http://rcn-ee.net/deb/raring-armhf/v3.8.13-bone28/

The 3.8 kernel requires device tree overlays. More here: http://elinux.org/BeagleBone_and_the_3.8_Kernel#Device_Tree_Overlays You need to know the address offsets for the gpio pins to configure. The table is listed here: http://hipstercircuits.com/category/device-tree/ or a nicer looking table here: https://github.com/bradfa/beaglebone_pinmux_tables

This table provides the pin configurations and necessary data for the DTS file.

BB Pin Function  Offset Info                 J1 (Relay Board)
P8.14  gpio0_26  0x28  26 <&gpio1 0x1A 0x0>  PA0  1
P8.15  gpio1_15  0x3c  47 <&gpio2 0x2F 0x0>  PA1  2
P8.16  gpio1_14  0x38  46 <&gpio2 0x2E 0x0>  PA2  3
P8.17  gpio0_27  0x2c  27 <&gpio1 0x1B 0x0>  PA3  4
P8.18  gpio2_1   0x8c  65 <&gpio3 0x41 0x0>  PA4  5
P8.19  gpio0_22  0x20  22 <&gpio1 0x16 0x0>  PA5  6
P8.20  gpio1_31  0x84  63 <&gpio2 0x3F 0x0>  PA6  7
P8.21  gpio1_30  0x80  62 <&gpio2 0x3E 0x0>  PA7  8

P8.27  gpio2_22  0xe0  86 <&gpio3 0x16 0x0>  B1   22
P8.28  gpio2_24  0xe8  88 <&gpio3 0x18 0x0>  B2   23
P8.29  gpio2_23  0xe4  87 <&gpio3 0x17 0x0>  B3   24
P8.30  gpio2_25  0xec  89 <&gpio3 0x19 0x0>  B4   25

Here's my device overlay file (BB-switch-00A0.dts).


/ {
	compatible = "ti,beaglebone", "ti,beaglebone-black";

	part-number = "BB-switch";
	version = "00A0";

	exclusive-use = 
		"P8.14", "gpio0_26",
        "p8.15", "gpio1_15",
        "P8.16", "gpio1_14",
        "P8.17", "gpip0_27",
        "P8.18", "gpio2_1",
        "P8.19", "gpio0_22",
        "P8.20", "gpio1_31",
        "P8.21", "gpio1_30",
        "P8.27", "gpio2_22",
        "P8.28", "gpio2_24",
        "P8.29", "gpio_23",
        "P8.30", "gpio_25";

	[email protected] {
               target = <&am33xx_pinmux>;
               __overlay__ {

		  gpio_helper_pins:switch_pins {
			pinctrl-single,pins = <
			  	0x028 0x17
                0x03c 0x17
                0x038 0x17
                0x02c 0x17
                0x08c 0x17
                0x020 0x17
                0x084 0x17
                0x080 0x17
				0x0e0 0x17
				0x0e8 0x17
				0x0e4 0x17
				0x0ec 0x17

	[email protected] {
               target = <&ocp>;

               __overlay__ {

		switch_helper {
		     compatible = "bone-pinmux-helper";
		     status = "okay"; 
		     pinctrl-names = "default";
		     pinctrl-0 = <&gpio_helper_pins>;


To compile and move this to the /lib/firmware directory:

echo "Compiling"
dtc -O dtb -o BB-switch-00A0.dtbo -b 0 [email protected] BB-switch-00A0.dts
cp BB-switch-00A0.dtbo /lib/firmware

Then to load the dtbo file: (Note, the number after bone_capemgr can change based on the kernel/OS install.)

echo BB-switch > /sys/devices/bone_capemgr.8/slots

Software Architecture

There are two peices of software, which are both written in Java. The client is GUI based and runs under Linux or Windows. We use Windows 7 and Java 7 at the contest station, but I actually wrote the software using Netbeans in Ubuntu 13.04. The server is console based and runs under Java 8. I don't use any special features of the newer Java JRE.

Both peices of software use a library to abstract the low level calls to the BB.

Programming was done using NetBeans 7.4.


The client is written in JavaFX, which uses FXML to describe the GUI layout. I used scene builer to draft the GUI. The main GUI is linked to a controller class. The controller class binds properties of the GUI elements to setter/getter methods in the SixPak.java and the AuxRelay.java classes. These methods are used to set the GUI properties from a change listener. This architecture really decouples the GUI from the main code.

GUI rules are enforced in the client to ensure the user can't select non-sensical combinations. (e.g. Full Stack AND T/M) Addtional rules are coded into the server to enforce lock outs.

Outbound network communications occurs in a separate thread and uses UDP packets to send updates to the server. The main thread transmits packets to the UDP thread using a blocking queue. Inbound communications uses Multicast, also in another task/thread, which allows all the clients to be notified of changes. Inbound multicast packets are validated and passed back to the main thread using a change listener and a messageProperty.get(). The property is passed to an update GUI method, which updates the GUI properties.

A heartbeat 'ping' runs in a separate thread to monitor network connectivity.


The BB pins were configured using Device Tree Overlays as above. The actual pins used are configured in a separate data file, pinmap.cfg.

The server uses a thread/task to monitor incoming UDP network packets. The packets are validated and passed to 'the brain' which does a few more validation checks and then sens the request to the controller. The update requests are passed to relay board objects (which contain relay objects) using static 32bit wide state variables. The controller maintains the switch state.

Low level calls are handled by BBMux, which interacts with the BB userland /sys files to change the GPIO pin state. Code for BBMux was found on the Internet and modified to fit my needs. Unfortunately, I lost track of the orginal author.

After the request is processed, the brain sends the packet to the network using simple Multicast.

System.out.println requests were replaced with Log4J calls. There is an external configuration file to allow run time logging level configuration. logconfig.txt