センサ情報取得プログラムの作成

概要

armadillo-300のシリアルデバイス経由でプログラムにより距離センサから信号を受け取る.ここで,センサに係わる機器としては以下のものがある.

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

図1. 各デバイス接続図

実験前

準備・確認

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

AGB65-ADC簡易使用方法

AGB65-ADCへシリアル信号で個別の命令を送ることで,その命令に合った形式で結果が返ってくる.つまり,まずarmadillo300上のプログラムがどのようなデータが欲しいかコマンド送信すると(データリクエスト),AGB65-ADCは要求されたデータを返信する(データリプライ).

AGB65-RSCと基本的な使い方は同じであるが,返ってくる値を読み取る必要がある.

大まかな流れは,センサ情報リクエストする配列をAGB65-ADCへ送信し,その後AGB65-ADCからセンサ情報を受信する.

まずデータリクエスト用配列は以下のようになる.

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のようになる.
V-cm

図2. 出力電圧と距離の関係図

プログラミング演習

下記のプログラムを作成,実行してセンサ値の取得について学ぶ.

センサ値読取プログラム

AD-PSDセンサからのセンサ値を表示

  • 100m秒(100000μ秒)毎にデータ取得,表示する.これを100回(10秒)繰り返す.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#define SERIAL_PORT     "/dev/ttyAM1"

int main(){
  int fd;
  fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY);
  if(fd < 0){
    printf("%s doesn't open it\n",SERIAL_PORT);
    return -1;
  }

  struct termios oldtio, newtio;
  tcgetattr(fd, &oldtio);
  newtio = oldtio;

  newtio.c_iflag = IGNPAR;
  /* 非カノニカル入力処理 */
  newtio.c_lflag = 0;

  /* read関数での文字待ちうけの設定 */
  newtio.c_cc[VTIME] = 0; /* 値x0.1秒待つ */
  newtio.c_cc[VMIN] = 1; /* 値の文字分だけ入力されるまで待つ*/

  /* バッファをクリア */
  tcflush(fd, TCIFLUSH);
  
  cfsetspeed(&newtio, B9600);
  tcsetattr(fd, TCSANOW, &newtio);

  /* ボードの設定 */
  int id=120;

  int i, j, k;
  unsigned char command[4] = {255, id, 1, 1};
  unsigned char data[20];
  
  for(i=1 ; i<=100 ; i++){
    printf("Getting data : %d :", i);

    /* センサボードにデータ要請 */
    write(fd, command, sizeof(command));
    usleep(100000);
    /* 1文字目データ受信 */
    read(fd, &data[0], 1);
    if(data[0] == 255){
      read(fd, &data[1], 1);
      if(data[1] == id){
        read(fd, &data[2], 1);
        if(data[2] == 17){
          read(fd, &data[3], 1);
          if(data[3] == 1){
            for(k=4 ; k<20 ; k++){
              /* read(fd, data2, 16);とか聞くかな */
              read(fd, &data[k], 1);
            }
  
            for(k=4 ; k<7 ; k++){
              /* read(fd, data2, 16);とか聞くかな */
              printf("data = %d :", data[k]);
            }
            printf("\n");
          }
        }
      }
    }
  }
  
  tcsetattr(fd, TCSANOW, &oldtio);
  close(fd);
  return 0;
}

センサ値読取・距離(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」で始まる.
ID ADCに設定された固有のID(AGB65シリーズを複数接続したときの判別用.ADCの場合,出荷時のIDは「3」.)
送信バイト数 送信される命令の(バイト)数.シンクロバイト,ID,送信バイト数は数えない.
命令 ADCに動作させたい命令.詳細は以下の表.

命令の種類は以下のものがある.

命令の種類
命令値 動作 方向 フォーマット
1 全ポート読み取り(8bit) 送信 [255][ID(120-127)][バイト長(1)][命令(1)]
    受信 [255][ID(120-127)][バイト長(17)][命令(1)][P1結果][P2結果]...[P16結果]
2 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]
12 1ポート読み取り(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