ゼミのお話/ロボット工学者養成所/一覧/シリアル通信によるデバイス制御/センサ情報取得プログラム作成

2018-04-16 (月) 15:53:00 (844d)

概要

  • armadillo300のシリアルデバイス経由でプログラムにより距離センサから信号を受け取る.ここで,センサに係わる機器としては以下のものがある.
    • AGB65-ADC
      • シリアルポート経由で受けた指令を元にセンサからの信号を数値化・整形して返す機器である.この機器が扱うシリアルデバイスはTTLレベル信号であり,論理0が0V,論理1が5Vである.
    • 距離センサ
      • 物体との距離を電圧で表すデバイスである.測定できる距離はデバイスによって異なる.
connection_adcconverter.png
  • 図1 各デバイス接続図

実験前準備等

準備・確認

  • 全ての電源が入っていることを確認
  • TeraTerm?でarmadillo300にログインできていることを確認
  • 演習用のディレクトリを作成し,そのディレクトリに移動していることを確認
    • 演習後は消すこと
    • 演習用ディレクトリにて,プログラムファイルを作成し,コンパイル,実行を行うこと.
    • コンパイル例:プログラムファイル:sample.c, 実行ファイル:sample
      • gcc sample.c -o sample
    • 実行
      • ./sample

AGB65-ADC簡易使用方法

  • AGB65-ADCへシリアル信号で個別の命令を送ることで,その命令に合った形式で結果が返ってくる.つまり,まずarmadillo300上のプログラムがどのようなデータが欲しいかコマンド送信すると(データリクエスト),AGB65-ADCは要求されたデータを返信する(データリプライ).
    • AGB65-RSCと基本的な使い方は同じであるが,返ってくる値を読み取る必要がある.
  • 以下のように配列を定義して用いる.
    • データリクエスト用データ.以下の配列をシリアル送信する.
      • unsigned char command[4] = {255, 120, 1, 1};
シンクロバイト(255)ADCにデータの通信開始を知らせるデータで,常に「255」である.
ID(120)ADCに設定された固有のID(AGB65シリーズを複数接続したときの判別用.ADCの場合,出荷時のIDは「120」.)
送信バイト数(1)送信される命令の(バイト)数.シンクロバイト,ID,送信バイト数は数えない.
命令1(1)全ポート(16ポート)読み取り(精度8bit)
  • データリプライ用データ.データリクエストした後,以下の配列をシリアル受信する.
    • unsigned char data[20];
data[0]:シンクロバイト(255)ADCからデータの通信開始を知らせるデータで,常に「255」である.
data[1]:ID(120)リクエストされたADCのID(ID=120にリクエストした場合,120の値が入っている.)
data[2]:データバイト数(17)ADCからarmadillo300に向けて送信される命令のバイト数.シンクロバイト,IDは数えない.
data[3]:命令1(1)armadillo300からADCにリクエストされた命令を返信.command[4]の値.
data[4]〜data[19]:[ポート1の結果]〜[ポート16の結果]各ポートにささっているセンサの取得結果
  • 上記のデータを以下のように送受信すると配列dataの中にセンサの情報が格納されている.厳密には,data[0]〜[3]の値を使って正常にデータを受信できているか確認する必要がある(プログラムを参照)
    • int main(){ ...
    • ...
    • write(fd, command, sizeof(command));
    • read(fd, data, sizeof(data));
    • ...
    • }

AGB65-ADCにて得られる距離センサの出力電圧と実測距離の関係

  • 電源投入後、約40mS後から信号線に距離に応じて出力される.
  • この出力は28〜48mS毎にアップデートされる.
  • 出力電圧と距離の関係は図1のようになる.
AS-PSD-3.jpg
  • 図1 出力電圧と距離の関係図

プログラミング演習

  • 下記のプログラムを作成,実行してサーボの制御について学ぶ.

センサ値読取プログラム

  • AD-PSDセンサからのセンサ値を表示
    • 100m秒(100000μ秒)毎にデータ取得,表示する.これを100回(10秒)繰り返す.
01:#include <sys/types.h>
02:#include <sys/stat.h>
03:#include <sys/ioctl.h>
04:#include <fcntl.h>
05:#include <termios.h>
06:#include <unistd.h>
07:#include <stdio.h>
08:#include <stdlib.h>
09:#include <string.h>
10:#include <sys/time.h>
11:
12:#define SERIAL_PORT     "/dev/ttyAM1"
13:
14:int main(){
15:  int fd;
16:  fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY);
17:  if(fd < 0){
18:    printf("%s doesn't open it\n",SERIAL_PORT);
19:    return -1;
20:  }
21:
22:  struct termios oldtio, newtio;
23:  tcgetattr(fd, &oldtio);
24:  newtio = oldtio;
25:
26:  newtio.c_iflag = IGNPAR;
27:  /* 非カノニカル入力処理 */
28:  newtio.c_lflag = 0;
29:
30:  /* read関数での文字待ちうけの設定 */
31:  newtio.c_cc[VTIME] = 0; /* 値x0.1秒待つ */
32:  newtio.c_cc[VMIN] = 1; /* 値の文字分だけ入力されるまで待つ*/
33:
34:  /* バッファをクリア */
35:  tcflush(fd, TCIFLUSH);
36:  
37:  cfsetspeed(&newtio, B9600);
38:  tcsetattr(fd, TCSANOW, &newtio);
39:
40:  /* ボードの設定 */
41:  int id=120;
42:
43:  int i, j, k;
44:  unsigned char command[4] = {255, id, 1, 1};
45:  unsigned char data[20];
46:  
47:  for(i=1 ; i<=100 ; i++){
48:    printf("Getting data : %d :", i);
49:
50:    /* センサボードにデータ要請 */
51:    write(fd, command, sizeof(command));
52:    usleep(100000);
53:    /* 1文字目データ受信 */
54:    read(fd, &data[0], 1);
55:    if(data[0] == 255){
56:      read(fd, &data[1], 1);
57:      if(data[1] == id){
58:        read(fd, &data[2], 1);
59:        if(data[2] == 17){
60:          read(fd, &data[3], 1);
61:          if(data[3] == 1){
62:            for(k=4 ; k<20 ; k++){
63:              /* read(fd, data2, 16);とか聞くかな */
64:              read(fd, &data[k], 1);
65:            }
66:  
67:            for(k=4 ; k<7 ; k++){
68:              /* read(fd, data2, 16);とか聞くかな */
69:              printf("data = %d :", data[k]);
70:            }
71:            printf("\n");
72:          }
73:        }
74:      }
75:    }
76:  }
77:  
78:  tcsetattr(fd, TCSANOW, &oldtio);
79:  close(fd);
80:  return 0;
81:}

センサ値読取・距離(cm)表記プログラム

  • お題のプログラムを作成してみよう

お題

  • センサから障害物(手のひらなど)までの距離を測り,計測した距離(cm)を表示するプログラムの作成

参考

AGB65-ADC命令仕様

  • マスタ(Armadillo-300)からADCへの指示は,4〜17バイトの数値データで送る.
  • バイトサイズ(8ビット)なので,表される数値は0〜255の256種類.
  • 数値は10進数.
  • 注)データは文字データではなく,数値(バイナリ)データで送る.
  • データの基本形
    • データの基本形は次の通り.[ ]内は1バイトを表す.()内は送りえる数値の範囲.
[シンクロバイト(255)] [ID(120-123)] [送信バイト数(1-14)] [命令1] [命令2] [命令3] ...
シンクロバイトADCにデータの通信開始を知らせるデータで,常に「255」で始まる.
IDADCに設定された固有のID(AGB65シリーズを複数接続したときの判別用.ADCの場合,出荷時のIDは「120」.)
送信バイト数送信される命令の(バイト)数.シンクロバイト,ID,送信バイト数は数えない.
命令ADCに動作させたい命令.詳細は以下の表.
  • 命令の説明
命令値動作方向フォーマット
全ポート読み取り(8bit)送信[255][ID(120-127)][バイト長(1)][命令(1)]
  受信[255][ID(120-127)][バイト長(17)][命令(1)][P1結果][P2結果]...[P16結果]
1ポート読み取り(8bit)送信[255][ID(120-127)][バイト長(2)][命令(2)][ポート番号(1-16)]
  受信[255][ID(120-127)][バイト長(3)][命令(2)][ポート番号][結果]
11全ポート読み取り(12bit)送信[255][ID(120-127)][バイト長(1)][命令(11)]
  受信[255][ID(120-127)][バイト長(33)][命令(11)][P1_H][P1_L][P2_H][P2_L]...[P16_H][P16_L]
121ポート読み取り(12bit)送信[255][ID(120-127)][バイト長(2)][命令(12)][ポート番号(1-16)]
  受信[255][ID(120-127)][バイト長(4)][命令(12)][P?_H][P?_L]
254セルフチェック送信[255][ID(120-127)][長(1)][254]
  受信[255][ID(120-127)][長(1)][254]
上以外無視される.  
  • 命令の処理時間
    • ADCが送信フォーマットを受け取ってから返信フォーマットを返し終わって待機状態になるまでの時間
    • 8bit,1ポート読み取り
      • 9600bpsの場合:約12ms
      • 115200bpsの場合:約1.4ms
    • 8bit,全16ポート読み取り
      • 9600bpsの場合:約25ms
      • 115200bpsの場合:約2.6ms
    • 12bit,1ポート読み取り
      • 9600bpsの場合:約13ms
      • 115200bpsの場合:約1.5ms
    • 12bit,全16ポート読み取り
      • 9600bpsの場合:約42ms
      • 115200bpsの場合:約4ms