RigExpert AA-30.ZERO Serio I/O Program

Here is a short program to control your AA-30.ZERO.

/* Rig Expert AA-30.ZERO control via serial port */
/* file name = aa30zero.c */
/* % gcc aa30zero.c -o aa30zero */
/* % ./aa30zero fq7050000 sw100000 frx2 > mydata.txt> mydata.txt  */

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <termios.h>
#include <time.h>
#include <unistd.h>
#define BUFFSIZE 256
#define BAUDRATE B38400
#define MODEMDEVICE "/dev/cu.usbmodem1471"

int fd = -1;
char com_ver[BUFFSIZE] = "ver"; /* returns AA-30 ZERO 150 */
char com_fq[BUFFSIZE];          /* returns OK */
char com_sw[BUFFSIZE];          /* returns OK */
char com_frx[BUFFSIZE];         /* returns OK */

void serial_init(int fd) {
  struct termios tio;

  memset(&tio, 0, sizeof(tio));
  tio.c_cflag = CS8 | CLOCAL | CREAD;
  tio.c_cc[VTIME] = 0;
  tio.c_lflag = ICANON;
  tio.c_iflag = IGNPAR | ICRNL;
  cfsetispeed(&tio, BAUDRATE);
  cfsetospeed(&tio, BAUDRATE);
  tcsetattr(fd, TCSANOW, &tio);
}

void receive_process() {
  unsigned char buf[BUFFSIZE];
  int count;
  int writecount = 0;
  int okcount = 0;

  while (1) {
    count = read(fd, &buf, BUFFSIZE);

    if (count <= 0) {
      fprintf(stderr, "error count=%d \n", count);
      exit(1);
    }

    if (count > 1) { // exclude ^M only line
      for (int i = 0; i < count; i++) {
        fprintf(stderr, "%c", buf[i]);
      }
    }

    if (count == 3) { // OK^M
      okcount++;
      if (okcount == 3) {
        return;
      }
    }

    if (count > 15) { // pick only data lines
      for (int i = 0; i < count; i++) {
        fprintf(stdout, "%c", buf[i]);
      }
    }
    fflush(stdout);
  } /* enf of while(1) */
}

void send_command(char *string) {
  char buf[BUFFSIZE];

  fprintf(stderr, "[%s] \n", string);
  int n = strlen(string);
  for (int i = 0; i < n; i++) {
    buf[i] = *string++;
  }
  buf[n] = 0x0a;
  int nout = n + 1;
  int writecount = write(fd, &buf, nout);
}

void send_process() {

  sleep(2); send_command(com_ver);    // 1 sec is NOT enough
  sleep(1); send_command(com_fq);
  sleep(1); send_command(com_sw);
  sleep(1); send_command(com_frx);
}

int main(int argc, char *argv[]) {
  pid_t result_pid;
  struct termios oldtio;

  if (argc != 4) {
    fprintf(stderr, "Usage %s fq7050000 sw100000 frx3 > mydata.txt \n", argv[0]);
    exit(1);
  }

  strcpy(com_fq, argv[1]);
  strcpy(com_sw, argv[2]);
  strcpy(com_frx, argv[3]);

  fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY);
  if (fd < 0) {
    fprintf(stderr, "file [%s] open error. \n", MODEMDEVICE);
    return (-1);
  }

  tcgetattr(fd, &oldtio);
  serial_init(fd);

  result_pid = fork();

  if (result_pid == -1) {
    return (-1);
  } else if (result_pid == 0) {  // child process
    send_process();
    _exit(0);
  } else {                // parent process
    receive_process();
    tcsetattr(fd, TCSANOW, &oldtio);
    exit(0);
  }

  return 0;
}

You can use the program in the following manner.

% gcc aa30zero.c -o aa30zero

% ./aa30zero fq7050000 sw100000 frx3 > mydata.txt
[ver] 
AA-30 ZERO 150
[fq7050000] 
OK
[sw100000] 
OK
[frx3] 
7.000000,651.849192,-2296.917794
7.033333,520.452206,-2084.028216
7.066666,815.151558,-2043.642265
7.099999,716.516930,-2188.015629
OK

% cat mydata.txt 
7.000000,651.849192,-2296.917794
7.033333,520.452206,-2084.028216
7.066666,815.151558,-2043.642265
7.099999,716.516930,-2188.015629

% cat z.plt
reset
set title "Impedance (R, X, and Z)"
set grid
set datafile separator ","
plot   "mydata.txt" using 1:2 with line linewidth 3
replot "mydata.txt" using 1:3 with line linewidth 3
replot "mydata.txt" using 1:( abs($2+$3*{0,1}) ) with line linewidth 3

% gnuplot
gnuplot> load "z.plt"

RigExpert AA-30.ZERO (4)

Let’s see what happens with a dummy load with the frequency range of 0MHz to 30MHz.

The above figure shows the impedance curve.

This figure shows return loss.

VSWR is shown in the above figure.

The above two figures are the Smith Chart.

RigExpert AA-30.ZERO (3)

Here is a Smith Chart with a following gnuplot command.

gnuplot> plot "ant2.csv" using (arg( ($2+$3*{0,1}-50)/($2+$3*{0,1}+50) )) : (abs( ($2+$3*{0,1}-50)/($2+$3*{0,1}+50) )) with line linewidth 3

RigExpert AA-30.ZERO (2)

Now, the actual measurement of my dipole with an ATU tuned at 7038kHz.

I get such values as:

...
7.037000 45.16 0.30
7.037500 45.31 0.19
7.038000 45.33 0.09
7.038500 45.29 -0.14
7.039000 45.28 -0.24
7.039500 45.44 -0.30
7.040000 45.31 -0.56
...

Let’s draw some graphs with gnuplot.

% gnuplot
gnuplot> plot "ant2.csv" using 1:2 with line linewidth 3, \
          "ant2.csv" using 1:3 with line linewidth 3

The frequency range is from 6.5MHz to 7.5MHz, and the purple line shows R [ohm], and the green line X [ohm], respectively.

If you also want to show |Z|, the command is:

gnuplot> plot "ant2.csv" using 1:2 with line linewidth 3, \
          "ant2.csv" using 1:3 with line linewidth 3, \
          "ant2.csv" using 1:( abs($2+$3*{0,1}) ) with line linewidth 3

Using AntScope will give you the same kind of graph, but I believe you prefer to do it by yourself.

Return loss is obtained as follows:

gnuplot> plot "ant2.csv" using 1:( -20.0 * log(abs( ($2+$3*{0,1}-50)/($2+$3*{0,1}+50) )) / log(10) ) with line linewidth 3


Finally, VSWR is:

gnuplot> plot "ant2.csv" using 1:( (1+abs( ($2+$3*{0,1}-50)/($2+$3*{0,1}+50) )) / (1-abs( ($2+$3*{0,1}-50)/($2+$3*{0,1}+50) )) ) with line linewidth 3

RigExpert AA-30.ZERO

The AA-30.ZERO is an AA-30 antenna analyzer without enclosure, LCD display and keypad. The board is connected to your PC through a USB-to-RS232C converter.

I used my Arduino Uno for the conversion. You can find a simple sample program here.

// UART bridge for data exchange between 
// RigExpert AA-30 ZERO antenna & cable analyzer and Arduino Uno
//
// Receives from the Arduino, sends to AA-30 ZERO.
// Receives from AA-30 ZERO, sends to the Arduino.
//
// 26 June 2017, Rig Expert Ukraine Ltd.
//
#include <SoftwareSerial.h>

SoftwareSerial ZERO(4, 7);  // RX, TX

void setup() {
  ZERO.begin(38400);        // init AA side UART
  ZERO.flush();
  Serial.begin(38400);      // init PC side UART
  Serial.flush();
}

void loop() {
  if (ZERO.available()) Serial.write(ZERO.read());    // data stream from AA to PC
  if (Serial.available()) ZERO.write(Serial.read());  // data stream from PC to AA
}

With my Mac mini, the board worked fine. Visit https://rigexpert.com/products/kits-analyzers/aa-30-zero/getting-started-with-the-zero/ for the available commands.

The values shown are freq [MHz], R [ohm], and X [ohm], respectively. The measurement above was done with no load connected to the RF output terminal, so the values of R and X are rather large and not very stable.

Arduino IDE and its serial console can also be used depending on your liking.