LoginSignup
4
0

More than 1 year has passed since last update.

産業用ネットワークRS-422にSpresenseを接続してみました

Last updated at Posted at 2022-09-25

Next Step社製の 「Sony Spresense 用 RS-422/485 AddOnボード」 をVisual Studio CodeベースのSPRESENSE開発環境「SPRESENSE SDK」から利用してみました。RS-422/RS-485は産業向けネットワークとして人気の高いネットワークで、差動信号を用いた伝送により長距離を、ノイズの影響を少なく通信できる特徴を備えています。RS-485は半二重通信、RS-422は全二重通信です。

RS-422/485に対応したPLC自体は珍しくなく、Raspberry Pi由来のものもありますが、 SPRESENSEをRS-422/485に対応させることにより、長寿命・低消費電力・ファンレス・コンパクトなPLCを実現することができます。

DSC01453.jpeg

今回購入したデバイス

関連するコミット

配線方法

「Sony Spresense 用 RS-422/485 AddOnボード」ボード背面のハンダ付けが必要です。

  • MASTER側とSLAVE側で以下のジャンパ設定をします
  • JP1:2-3をショート:I2S端子を制御に利用
  • JP2:2-3をショート:I2S端子を制御に利用
  • JP3:終端抵抗 = 有効(クローズ)
  • JP4:RS-422(オープン):全二重通信
  • JP5:RS-422(オープン):全二重通信

DSC01456.jpg

また、RS-422を利用するので、
MASTERのAとSLAVEのY、MASTERのBとSLAVEのZ、
MASTERのYとSLAVEのA、MASTERのZとSLAVEのBをケーブルで接続してください。

DSC01455.jpg

ビルド方法

SDKコンフィグを開き「Examples」にある「rs422」を選択してください。RS-422/RS-485の受信・送信制御にI2SのピンあるいはEMMCのピンを利用します。同居するアプリケーションにご注意ください。

スクリーンショット 2022-09-25 14.16.32.png

スクリーンショット 2022-09-25 14.17.47.png

スクリーンショット 2022-09-25 14.17.04.png

プログラムの構造

NextStep社製のボードではRS-422/RS-485がSPRESENSE Main Board上のUART2と接続されています。SPRESENSE SDKでは、NuttXというRTOS(リアルタイムOS)が、ハードウェアを制御してくれますが、本環境ではこれらのポートは「/dev/ttyS2」というファイルで表現されます。このファイルをopenしてUART通信を行い、RS-422/RS-485の信号を生成します。

UART通信ポートの初期化

ttyS2はUART通信用に以下のソースコードで初期化します。

  struct termios tio;

  /* Open and Setup RS485_TTY_NAME */

  comm_tty = open(RS485_TTY_NAME, O_RDWR | O_NOCTTY);
  ret = errno;
  if (ret != 0)
    {
      printf("could not open %s\n", RS485_TTY_NAME);
      return -1;
    }

  tcgetattr(comm_tty, &tio);

  tio.c_cflag |= CREAD;   /* Enable receive */
  tio.c_cflag |= CLOCAL;  /* Local line, no modem control */
  tio.c_cflag &= ~CSIZE;  /* Clean the bits */
  tio.c_cflag |= CS8;     /* Data bit 8bit */
  tio.c_cflag &= ~CSTOPB; /* Stop bit 1bit */
  tio.c_cflag &= ~PARENB; /* Paritiy none */
  cfsetspeed(&tio, RS485_TTY_SPEED);

  tio.c_iflag = 0;
  tio.c_oflag = 0;
  tio.c_lflag = 0;
  tio.c_cc[VTIME] = 0;
  tio.c_cc[VMIN] = 1;

  tcflush(comm_tty, TCIOFLUSH);
  tcsetattr(comm_tty, TCSANOW, &tio);

  fcntl(comm_tty, F_SETFL, O_NONBLOCK);

データの受信

UARTはいつデータが来るかわからないため、ファイルディスクリプタに対してpoll関数で待ちます。また、すべてのデータが一度に届くとは限らないため、要求長データが揃うまでループしてデータを繋げていきます。

  int ret;
  struct pollfd fds[1];
  int nfds = 1;
  int done = 0;
  fds[0].fd = comm_tty;
  fds[0].events = POLLIN | POLLRDNORM;

  while (remain > 0)
    {
      ret = poll(fds, nfds, 500);
      while ((ret = poll(fds, nfds, 0)) > 0)
        {
          if (ret > 0)
            {
              if ((fds[0].revents & (POLLIN | POLLRDNORM)) != 0)
                {
                  ret = read(comm_tty, pbuf + offset, remain);
                  offset += ret;
                  remain -= ret;
                  done += ret;
                }
            }
        }
    }

データの送信

送信は簡単です。write関数で書き込み、すべてのデータが送出完了するまでループします。

  int done = 0;
  while (remain > 0)
    {
      ret = write(comm_tty, pbuf + offset, remain);
      offset += ret;
      remain -= ret;
      done += ret;
    }

以上のコードを組み合わせて、プログラムを作りました。正確には、追加でコマンドパーサーなどを実装しており、MASTER側で生成するメッセージの先頭4文字(ヌル文字含む)を変えることにより、SLAVE側の挙動を切り替えられるようにしました。

プログラムの利用方法

Slave側を先に起動し、NuttShell(RTOS:NuttXのシェル)上で「rs422 -s」を実行、スレーブを起動します。次にMaster側に移動し、同じくNuttShell上で「rs422 -m」を実行、マスターを開始すると、マスターからコマンドがスレーブへ送出され、下記のシーケンスの後、マスターが終了します。スレーブは、初期状態に戻ります。

  • ini

    • マスターから"ini"コマンドを送出
    • スレーブ側でバッファを確保、初期化
    • 完了をACK応答
  • dat

    • マスターから"dat"コマンドを送出
    • スレーブ側のバッファをマスターへ送出
    • マスター側でバッファ内容をチェック
  • fin

    • マスターから"fin"コマンドを送出
    • スレーブ側でバッファを解放
    • 完了をACK応答

おわりに

ノイズに強い有線接続の伝送線が準備できました。
色々なアプリケーションに利用できそうですね。

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0