###はじめに
共立プロダクツのプチロボ制御ソフトは、Windows版しか提供されていません。そこで、Linuxでも操作できるようにしてみたかったので、コントロールボードとPC間のシリアル通信をするための準備のためにC言語でのシリアル通信コードの学習もかねて簡単なソフトウェアを作ってみた。
###コントロールボードについて
サーボモータを最大20個も操作できます。また、A/D入力にも対応しており、デジタル出力用のピンも出ています。サーボモータ用の操作には、I2C通信を使うケースが多く、シリアル通信での制御はあまり見かけません。せっかく手元にある玩具なので、もう少し深く楽しんでみたくなったのですが、はじめから準備されたWindowsソフトで遊ぶだけでは物足りません。
「WR-MSXX」の通信プロトコルは、共立電子の専用サイトからダウンロードが可能です。
https://drive.google.com/open?id=1lnpenY3FXI092F3Dacd8IQRRztPIJDvg
ZIPファイルをダウンロードして、解凍したフォルダのtutorial > pdffiles とたどると、ハードウェアマニュアルのPDFが無料で提供されています。(wr-xx_hardware2.pdf)更に、ハードウェアの回路図があります。PICが2個使われています。
・PIC16F687
・PIC16F886
PIC16F687がFT232RL経由でPCにつながります。2つのPIC間は、I2C通信設定のようです。以前から、Raspberry PiとPICとの組みあせには興味があったのですが、まさに、その実験にうってつけの製品だと思いました。
###C言語でのシリアル通信コードについて
特に役に立ったのは、そのものズバリ、「The Linux Serial Programming HOWTO」(日本語版)です。
http://linuxjf.osdn.jp/JFdocs/Serial-Programming-HOWTO.html
###ダミーコード・サンプル
いろいろとわからないことが多かったものの、結果的には簡単なコードになりましたので、全文を掲載します。結局、シリアル通信に使用するデバイスドライバファイルの扱いは、K&Rの「プログラミング言語C」の第8章2節の「低水準入出力ーーReadとWrite」の解説がとても役にたちましたが、それ以外は、「Cの絵本」を片手に学習したものです。
/***********************************************************************************************************
* サンプルプログラム(Linux版 WR-XX返信ダミープログラム)無限ループ
* Lian Ivvakanni (12-19-2020)
* プログラムの内容
* ・Wonder Roid Motion Maker V343.1.1からのA/D入力取得コマンド(コマンド 5)を受信して
* WM:Wait data stack Memory状態「空」(=0)を送信する
* WR-XX 通信プロトコルガイド(第2版)仕様
* RS232C 通信設定(半二重通信)
* ・通信速度 :38400bps
* ・データ形式 :バイナリーモード出力
* ・データ :8ビット
* ・ストップビット :1
* ・パリティ :無し
* ・ハンドシェイク(フロー制御):無し
* ・シリアルポート :/dev/ttyUSB0
*
***********************************************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define MODEM_DEVICE "/dev/ttyUSB0"
#define BAUD_RATE B38400
#define N 255
int main(int argc, char *argv[])
{
int fd, i, rlen, slen;
struct termios tio;
char s[8], rBuf[N] = {'\0'}, sBuf[N] = {'\0'};
// WMデータ
unsigned long mwData[] = {0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x46,0x00};
// AD入力取得コマンド(コマンド 5)
unsigned long cmd_five[] = {0xFD,0x04,0x05,0xFE};
memset(&tio, 0, sizeof(tio));
tio.c_cflag = BAUD_RATE | CS8 | CLOCAL | CREAD;
tio.c_cc[VTIME] = 0; // キャラクタ間タイマは未使用
tio.c_cc[VMIN] = 0; // 文字受け取りブロックなし
// サーボ制御出力コマンド(ヘッダ)
slen = sizeof(mwData) / sizeof(mwData[0]);
sBuf[0] = 0xFD;
sBuf[1] = slen + 4;
sBuf[2] = 0x15; //
sBuf[slen + 3] = 0xFE;
for (i = 3; i < slen; i++) {
sBuf[i] = mwData[i-2];
}
/* 出力データのデバッグ
for (i = 0; i < slen + 4; i++){
printf("%02X ", sBuf[i]);
}
printf("\n");
*/
fd = open(MODEM_DEVICE, O_RDWR);
if (fd < 0) {
perror(MODEM_DEVICE);
exit(-1);
}
tcflush(fd, TCIFLUSH);
ioctl(fd, TCSETS, &tio);
while(1){
rlen = read(fd,rBuf, sizeof(rBuf));
if(rlen < 0)
printf("Device Read Error...\n");
if(rlen == 0)
continue;
else if(rBuf[1] == cmd_five[1] && rBuf[2] == cmd_five[2]){
// デバイスへ書き込み
write(fd, sBuf, 15);
} else {
for(i = 0;i < rlen; i++){
sprintf(s,"%02X", rBuf[i]);
printf("%s ",s);
}
printf("\r\n");
}
rlen = 0;
}
close(fd);
return 0;
}
おわりに
たったこれだけのことを理解するために、2週間ほどかかりました。やはり、独学というのは時間がかかって大変ですが、ある程度理解できたときの喜びもひとしおです。
これから、操作コマンドの送信用のプログラムはできていませんが、シリアル通信でサーボモータのコントロールは、結構大変そうです。UARTは、基本的な通信方式なので、ぜひとも基本的な仕組みは知っておきたかったので、もう少し学習をつづけておきたいと思います。