RaspberryPi[45] NMEA 発生器

どこかで書いた気もするけど、いろいろ変更したので再度あげておきます。NMEAフォーマットで受信する機器ってGPSのほかにもいろいろとあるんですね。そんなときのために、事前に作っておいたテキストファイルを一行ずつ、USBポートに出力するプログラムと作りました。USBもttyUSB0とttyUSB1に対応しています。送信時間も設定できます。ボーレートも変更できるように修正してみました。ただ、ボーレートは9600とか入れるのではなく、9600なら13、38400なら15と入れるように手を抜いています。ソースコードを挙げておくので、適当に修正してください。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <time.h>
#include <sys/ipc.h>
#include <stdlib.h>
#include <sys/shm.h>
#include <sys/socket.h> //socket()
#include <sys/ioctl.h>  //ioctl()
#include <arpa/inet.h>  //htons(), inet_addr()

#define SERIAL_USB0 "/dev/ttyUSB0"
#define SERIAL_USB1 "/dev/ttyUSB1"

#define TRUE 1
#define FALSE 0
#define DATA_SIZE_CMN  256
#define MAX_LINE_LENGTH 9000

char nmea_file_name[128];

int PortNumber = 60000;  // default port

int gettimeofday();

float chg_deg(float lat)
{
  float deg;
  int deg_int;
  float minutes;
  float deg_min;

  deg_int = (int)lat / 100;
  minutes = lat - (deg_int * 100 );
  deg_min = deg_int + minutes / 60.0;

  //  printf("di:%d mi:%f dm:%f\n",deg_int,minutes,deg_min);

  return deg_min;
}

void arg_error()
{
  printf("Argment error!! type as below\n");
  printf("sudo ./gen_gps -f nmea_file_name -u 0/1 -i 1 -s 20 \n");
  printf("-d      : display ->0/1\n");
  printf("-b      : baudRate: 9600->13 38400->15 \n");
  printf("-f      : GPS NMEA read from a file instead of real GPS. It needs nmea file name after -g\n");
  printf("-u 0/1  : ttyUSB0 ->0 or ttyUSB1 ->1\n");
  printf("-i #    : GPS interval Typically 1 sec \n");
  exit(0);
}

int main(int argc, char *argv[])
{
  unsigned char msg[] = "serial port open...\n";
  int fd;
  struct termios tio;
  int baudRate = B9600;
  int i;
  int k;
  int arg_err_flg = FALSE;
  int skip = 0;
  int msg_cnt = 0;
  time_t t;
  FILE *file;
  int loop_counter = 0;
  int speed;
  int usb;
  int display = 0;


  FILE *nmea_file;
  char line;
  unsigned char buf[DATA_SIZE_CMN] = {0};
  unsigned char buf2[MAX_LINE_LENGTH][DATA_SIZE_CMN];


  if (argc < 3)
  {
    arg_error();
  }

  // Check argv
  arg_err_flg = FALSE;
  for (i = 0; i < argc; i++)
  {
    if (strcmp(argv[i], "-d") == 0)
    {
        printf("stop\n");
      sscanf(argv[i + 1], "%d", &display);
    }
    
    if (strcmp(argv[i], "-b") == 0)
    {
      sscanf(argv[i + 1], "%d", &baudRate);
    }
    
    if (strcmp(argv[i], "-f") == 0)
    {
      strcpy(nmea_file_name, argv[i + 1]);
    }
    if (strcmp(argv[i], "-u") == 0)
    {
      sscanf(argv[i + 1], "%d", &usb);
      if (usb > 1) arg_err_flg = TRUE;
    }
    if (strcmp(argv[i], "-i") == 0)
    {
      sscanf(argv[i + 1], "%d", &speed);
      speed = speed * 1000000;
    }

    if (arg_err_flg == TRUE) arg_error();
  }

  if (display == TRUE) printf("br:%d nmea_file:%s ttyUSBport:%d gps_freq :%dsec skip:%d \n", baudRate,nmea_file_name, usb, speed / 1000000, skip);

  if (usb == 0) {
    fd = open(SERIAL_USB0, O_RDWR);
    if (fd < 0)
    {
      printf("USB0 open error\n");
      return -1;
    }
  } else {
    fd = open(SERIAL_USB1, O_RDWR);
    if (fd < 0)
    {
      printf("USB1 open error\n");
      return -1;
    }
  }

  tio.c_cflag += CREAD;
  tio.c_cflag += CLOCAL;
  tio.c_cflag += CS8;
  tio.c_cflag += 0;
  tio.c_cflag += 0;

  cfsetispeed( &tio, baudRate );
  cfsetospeed( &tio, baudRate );

  cfmakeraw(&tio);

  tcsetattr( fd, TCSANOW, &tio );


  ioctl(fd, TCSETS, &tio);


  nmea_file = fopen(nmea_file_name, "r");
  if (nmea_file == NULL)
  {
    printf("Could not open %s\n", nmea_file_name);
    exit(0);
  }

  i = 0;

  while (1) {
    if (fgets(buf, DATA_SIZE_CMN, nmea_file) == NULL) break;
    strcpy(buf2[i], buf);
    if (display == TRUE) printf("R:%d: %s", i, buf2[i]);
    i++;
  }

  fclose(nmea_file);

  while (1) {
    for (loop_counter = 0; loop_counter < i; loop_counter++) {
      if (display == TRUE) printf("\rS:%d %s", loop_counter, buf2[loop_counter]);

      write(fd, buf2[loop_counter], DATA_SIZE_CMN);
      usleep(speed);
    }

    for (loop_counter = i; loop_counter > 0; loop_counter--) {
      if (display == TRUE) printf("\rS:%d %s", loop_counter, buf2[loop_counter]);

      write(fd, buf2[loop_counter], DATA_SIZE_CMN);
      usleep(speed);
    }
  }
  exit(0);
}

./gen_gps -f nmea_file_name -u 0/1 -i 1 -s 1

  printf("sudo ./gen_gps -f nmea_file_name -u 0/1 -i 1 -s 20 \n");
  printf("-d      : display ->0/1\n");
  printf("-b      : baudRate: 9600->13 38400->15 \n");
  printf("-f      : GPS NMEA read from a file instead of real GPS. It needs nmea file name after -g\n");
  printf("-u 0/1  : ttyUSB0 ->0 or ttyUSB1 ->1\n");
  printf("-i #    : GPS interval Typically 1 sec \n");

NMEAフォーマットはの例です。

$GNGGA,063441.20,3527.100673042,N,13937.902454837,E,4,13,0.91,205.863,M,41.731,M,4.2,2108*69
$GNVTG,240.3,T,0.0,M,13.5,N,25.0,K,A*38
$GNGGA,063441.30,3527.100823803,N,13937.903106614,E,4,13,0.91,205.863,M,41.731,M,4.2,2108*62
$GNVTG,240.3,T,0.0,M,13.5,N,25.0,K,A*38
$GNGGA,063441.40,3527.100974564,N,13937.903758391,E,4,13,0.91,205.863,M,41.731,M,4.2,2108*6F
$GNVTG,240.3,T,0.0,M,13.5,N,25.0,K,A*38