リグエキスパートのAA-30.ZEROシリアル通信プログラム

あなたの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;
}

このプログラムは以下のようにして使います。

% 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"