OrangePi-PCを使ってみる

複数ポートを使ったシリアル通信

OrangepiPCには3つのシリアルポートがありますが、とあるフォーラムで同時に複数のポートを使って通信できないという書き込みがありま した。
そこで、時間が取れたので検証してみることにしました。
ポート1とポート2の2つのポートを使って、2台のRaspberryと同時に通信してみます。
ソースは以下の通りです。
一応、3ポート全て使えるようにしています。

//
// Multi Serial Receive Program
//
// cc -o MserialRead MserialRead.c -lwiringPi
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <linux/ipc.h>
#include <linux/msg.h>
#include <sys/types.h>
#include <wiringPi.h>
#include <wiringSerial.h>

#define DEBUG    0
#define BAUDRATE 115200
#define    TIMEOUT  10000

// Re define message structure
typedef struct mymsgbuf
{
  long mtype;
  char rdata[64];
} mess_t;

// Reeveive data from UART
int readSerial(int fd, char * buff, int blen, int timeout) {
  unsigned long endTime;
  int ch;
  int pos = 0;

if(DEBUG)printf("millis=%d\n",millis());
  endTime = millis () + timeout;
if(DEBUG)printf("endTime=%d\n",endTime);
  buff[pos] = 0;

  while (1) {
    if (millis () > endTime) return -1;
    if (serialDataAvail (fd)) {
      ch = serialGetchar (fd);
if(DEBUG)printf (" -> %02x\n", ch);
      if (ch == 0x0d) {

      } else if (ch == 0x0a) {
        return pos;
      } else {
        if (pos < blen) buff[pos++] = ch;
        if (pos < blen) buff[pos] = 0;
      }
    } // end if
  } // end while
}


int main(int argc, char **argv)
{
  int qid;
  key_t msgkey;
  pid_t pid;

  mess_t buf;

  int msglen;

  int readlen;
  char buff[64];

  int fd1,fd2,fd3;
  char device1[32],device2[32],device3[32];

  memset(device1,0,sizeof(device1));
  memset(device2,0,sizeof(device2));
  memset(device3,0,sizeof(device3));
 
  if (argc < 2) {
    printf("%s SerialDevice1 {SerialDevice2} {SerialDevice3}\n",argv[0]);
    return 0;
  } else if (argc == 2) {
    strcpy(device1,argv[1]);
  } else if (argc == 3) {
    strcpy(device1,argv[1]);
    strcpy(device2,argv[2]);
  } else {
    strcpy(device1,argv[1]);
    strcpy(device2,argv[2]);
    strcpy(device3,argv[3]);
  }
  printf("device1=[%s] device2=[%s] device1=[%s]\n",device1,device2,device3);

  msgkey = ftok(".",'m');
  printf("msgkey=%x\n",msgkey);
  msglen = sizeof(mess_t) - sizeof(long);
  qid = msgget(msgkey, IPC_CREAT | 0660);

  if(strlen(device1)) {
    pid=fork();
    if (pid == 0) {
      printf("SON1 - QID = %d\n", qid);

      //Open port
      if ((fd1 = serialOpen (device1, BAUDRATE)) < 0) {
        printf ("Unable to open serial device: %s\n", strerror (errno)) ;
        return 1 ;
      }

      if (wiringPiSetup () == -1) {
        printf ("Unable to start wiringPi: %s\n", strerror (errno)) ;
        return 1 ;
      }

      //Receive data
      while(1) {
        readlen=readSerial(fd1, buff, sizeof(buff),TIMEOUT);
if(DEBUG)printf("readSerial(%s)=%d\n",device1,readlen);
        if (readlen == -1) continue; // time out
if(DEBUG)printf("readSerial(%s) buff=[%s]\n",device1,buff);

      //Send to Father
        buf.mtype = 1;
        strcpy(buf.rdata,buff);
        msgsnd(qid, &buf, msglen, 0);
        printf("SON1 - MESSAGE=[%s]\n", buf.rdata);
        serialPrintf (fd1,"You are Welcome!! This is %s\n",device1);
      }
    }
  }


  if(strlen(device2)) {
    pid=fork();
    if (pid == 0) {
      printf("SON2 - QID = %d\n", qid);

      //Open port
      if ((fd2 = serialOpen (device2, BAUDRATE)) < 0) {
        printf ("Unable to open serial device: %s\n", strerror (errno)) ;
        return 1 ;
      }

      if (wiringPiSetup () == -1) {
        printf ("Unable to start wiringPi: %s\n", strerror (errno)) ;
        return 1 ;
      }

      //Receive data
      while(1) {
        readlen=readSerial(fd2, buff, sizeof(buff),TIMEOUT);
if(DEBUG)printf("readSerial(%s)=%d\n",device2,readlen);
        if (readlen == -1) continue; // time out
if(DEBUG)printf("readSerial(%s) buff=[%s]\n",device2,buff);

      //Send to Father
        buf.mtype = 2;
        strcpy(buf.rdata,buff);
        msgsnd(qid, &buf, msglen, 0);
        printf("SON2 - MESSAGE=[%s]\n", buf.rdata);
        serialPrintf (fd2,"You are Welcome!! This is %s\n",device2);
      }
    }
  }

  if(strlen(device3)) {
    pid=fork();
    if (pid == 0) {
      printf("SON3 - QID = %d\n", qid);

      //Open port
      if ((fd3 = serialOpen (device3, BAUDRATE)) < 0) {
        printf ("Unable to open serial device: %s\n", strerror (errno)) ;
        return 1 ;
      }

      if (wiringPiSetup () == -1) {
        printf ("Unable to start wiringPi: %s\n", strerror (errno)) ;
        return 1 ;
      }

      //Receive data
      while(1) {
        readlen=readSerial(fd3, buff, sizeof(buff),TIMEOUT);
if(DEBUG)printf("readSerial(%s)=%d\n",device3,readlen);
        if (readlen == -1) continue; // time out
if(DEBUG)printf("readSerial(%s) buff=[%s]\n",device3,buff);

      //Send to Father
        buf.mtype = 3;
        strcpy(buf.rdata,buff);
        msgsnd(qid, &buf, msglen, 0);
        printf("SON3 - MESSAGE=[%s]\n", buf.rdata);
        serialPrintf (fd3,"You are Welcome!! This is %s\n",device3);
      }
    }
  }



  printf("FATHER - QID = %d\n", qid);

  while(1){
    msgrcv(qid, &buf, msglen, 0, 0);
    printf("FATHER - MESSAGE=[%d][%s]\n", buf.mtype,buf.rdata);
  }

  msgctl(qid, IPC_RMID, 0);

  return 0;
}

Raspberry側の送信プログラムは前回を少し変更しIPアドレスを送信 する様にしています。
結果はこのように問題なく通信できることを確認しました。
シリアル通信は別プロセスで起動しているので、同時に通信することも可能です。
シリアルでしか通信できない複数のデバイス(GPSなどが該当するかも)と通信するときには
OrangePiは役に立ちます。



次回は /dev/ttyS0 を使ったシリアルログインを紹介します。