各種ライブラリ、ハードウェア使用法

eyebotには数多くのAPI関数ライブラリが用意されていて、C言語を知っている人なら誰でも簡単にモータやセンサなどを制御することができます。ここでは、外部ハードウェアとeyebotの接続法や、ライブラリの使用法を解説します。

ライブラリやハードウェアの詳細についてはeyebotのページのコントローラの項を参照してください。

モーター

接続

eyebotには、エンコーダー付きモーター用の9pinのコネクタが2つついています。 普通のDCモーターを接続する場合には、この9ピンコネクタの

   ・・・☆ <- MOTOR+
 ・・★・・ <- MOTOR-

の2ピンに接続します。はかってみたところ電位差は7.2Vくらい(電源電圧と同じ?) でした。

API

まず、使用するモータを初期化し、ハンドラを取得します。 パラレルポートに近いpinがLEFTMOTOR,遠い方がRIGHTMOTORです。

 MotorHandle mh;
 mh = MotorInit(LEFTMOTOR);

取得したハンドラを使って、モータの速度を設定します。 モータの速度は-100(後退)〜0(停止)〜100(前進)が設定できます。 ちなみにこの速度はPWMで制御されています(例:速度10の時は、 1秒間に0.1秒だけ駆動電圧が出力される、と言った感じ)

 MotorDrive(mh, 100); 

終了時にはハンドラを開放します。

 MotorRelease(mh);

エンコーダ

2相インクリメンタル矩形波形式のロータリーエンコーダが接続可能です。 ロータリーエンコーダには通常Vcc, 出力A, 出力B, GNDの4つのピンがついていると 思いますが、それらのピンをモータ端子の以下のピンに接続することで エンコーダを使用することができます。

   ・●☆・ <- ☆:出力A ●:GND
 ・・・★○ <- ★:出力B ○:Vcc(定電圧化されていない)

エンコーダの入力電圧が5Vなどと指定されている場合、電源、GNDはデジタルI/O端子 など別のところから引っ張ってくるとよいでしょう。

API

エンコーダもモータと同様、ハンドラ取得>値読み取り の順で使用します。 ハンドラの取得は以下のように行ないます。

 QuadHandle qh;
 qh = QUADInit(QUAD_LEFT); /* or QUAD_RIGHT for MOTOR B */

このハンドラを用いて、エンコーダの回転角をINT値で得ることができます。

 i = QUADRead(qh);

1回転でいくつこの値が増減するかは、エンコーダのパルス数によります。 (例えば50パルスなら50*4状態(00,10,11,01)なので、1回転で200増減)

取得値を0にリセットしたい場合は以下のAPIを用います。

 QUADReset(qh);

他にも、進んだ距離を返してくれるAPIなどがあります。それらを用いる場合、 HDTを編集して1mでいくつ取得値が増減するかを指定する必要があります。

サーボモータ

接続

eyebotにはサーボモータ接続用のピンが12組あります。各pinの意味は

 1 ◎ <- PWM信号
   ○ <- Vcc(駆動電圧)
   ● <- GND

です。モータ用PINに近いところがSERVO1, そこから横にSERVO6、 下段SERVO7〜SERVO12と並んでいます。

エンコーダを使うときはSERVO1〜SERVO4までは使えません。 コンパスを使うときはSERVO5〜SERVO6は使えません。 (Vω駆動インターフェースでは両方が使われています) これは、TPUが競合しているためです。使用するTPUはHDTを書き換えれば 変更可能です。

API

APIはほぼモータと同じです。サーボの回転角は0〜255が指定可能です。

 ServoHandle sh;
 sh = SERVOInit(SERVO1);
 SERVOSet(sh, 255);
 SERVORelease(sh);

アナログ入力

接続

eyebotは最大6個のアナログ入力を読み取ることができます。アナログ入力用 のピン(シリアルポート近く)のピン配置は以下のようになっています。

 GND In6 In4 In2 5V
 GND In7 In5 In3 5V

In2〜In7の各ピンは、0V〜4Vまでの電圧を読み取ることができます。 0V=0, 4V=1000として、0〜1023の10bit値に変換して読み取ります。
センサの出力が0〜4Vに入るように電圧増幅してつなげることで、 各種センサを簡単に利用することができるでしょう。
ちなみに、In0はマイク入力、In1は電池残量をはかるために使われています。

API

各PINの電圧値は以下の関数で取得できます。

 OSGetAD(2) // In2の電圧値を取得

結線してないピンの値取得は、以降正常な値の取得ができなくなる ことがあるみたいなので、やめたほうがいいです。
また、複数のアナログ入力を読み取る場合、ある程度の間隔をおいて 行わないと、正確な値が読み取れないようです。

 i2 = OSGetAD(2);
 OSWait(5); // 50ms待つ
 i3 = OSGetAD(3);
 OSWait(5);

デジタル入出力

接続

eyebotは4つのデジタル入力、8つのデジタル出力を行うことができます。 それらのピンは基板中央付近にあり、ピン配置は以下のようになっています。

 GND GND
  5V  5V
 In7 In6
 In5 In4
 Ou7 Ou6
 Ou5 Ou4
 Ou3 Ou2
 Ou1 Ou0

In4〜In7はデジタル入力用のピンです。(In0〜In3は赤外線センサーで使われています) なぜかショートしやすいので注意。

入力側の読み取り値は0V=0, 5V=1です(閾値は不明)。 出力側ピンは、1のとき5V, 0のとき0Vを出力します。

入力API

デジタル入力は、以下の関数で読み取れます。8つある入力値は、BYTE型の戻り値の 各bitに対応しています。引数にはラッチのポート(0〜3)を指定するらしいですが、 何のことか不明。0で問題なく動きました。

 b = OSReadInLatch(0);
 if(b & 0x10) ... // In4が5Vのとき

出力API

デジタル出力は、以下の関数で行うことができます。

 BYTE mask, value;
 mask = 0xfa;  // Out1, Out3の出力を変更
 value = 0x01; // Out1=1, Out3=0に変更
 OSWriteOutLatch(0, mask, value);

mask, valueの各bitが、各ピンに対応しています。 maskで0に指定されたピンの値が、valueで指定した値で上書きされます。 第1引数はラッチポートの指定ですが、良く分からないので0で(ぉ

無線通信

無線モジュール付きのeyebotは、互いに無線で通信することができます。

初期化

無線の初期化は以下のように行います。

 RADIOInit();

この関数を呼び出すと、まず既にあるネットワークがないか探し、 あればそれに接続し、なければ自分で新規ネットワークを構築します。

ネットワーク内のeyebotはIDで識別されます。IDは、eyebot設定画面の

 Hrd -> Set -> Rmt -> RemoteID

で設定可能です。プログラム中からは、

 RadioIOParameters rp;
 RADIOGetIoctl(&rp);
 rp.id = ID;
 RADIOGetIoctl(rp);

で設定することも可能です。(この関数はRADIOInit()より先に呼び出す 必要があります。また、この関数で通信速度なども設定可能です。)

送受信

データの送信方法は以下のとおり。

 BYTE msgbuf[MSGMAXLEN];
 RADIOSend(1, 20, msgbuf); // ID:1のeyebotに20byteのデータを送信
 

受信方法は以下のとおり。

 BYTE fromId, msgbuf[MSGMAXLEN];
 int len;
 if(RADIOCheck()) // メッセージが届いているとtrue
     RADIORecv(&fromId, &len, msgbuf);

以上の処理で、fromIdに送信元eyebotのIDが、lenにメッセージ長が、 msgbufにメッセージが格納されます。RADIORecv()はメッセージが来るまで 待ち続けるので、その前にRADIOCheck()でメッセージがあるか確認しています。

メッセージ長は、MSGMAXLEN以下でなければなりません。 この定数はtypes.hに定義されています。処理系のバージョンにより 変わる可能性があるので要参照。手元の処理系では35でした。

PCとeyebotの無線通信

LinuxにおけるPC側プログラムのコンパイル方法

PC用無線モジュールがあれば、eyebotとPCを通信させることができます。 無線モジュールは、PCのシリアルポートおよびPS/2端子(電源用)と 接続して用います。

PC側プログラムのプログラミングには、

  • 普通のgcc + eyebotのヘッダファイル群 + eyebotとの通信用ライブラリ

を用います。例えば/usr/local/robios/以下に処理系がインストールされている場合、

 cp /usr/local/robios/pc-appl/wireless/linux/lib/libradio.a .
 gcc -I/usr/local/robios/include radiopc.c libradio.a

とすることでradiopc.cをコンパイル可能です。 (注:libradio.a radiopc.c の順だとエラーになるかも。またgccの 環境によっては/usr/include/ansidecl.hがないと怒られるかもしれません)

プログラム内では、

 #include "eyebot.h"
 #include "remote.h"
 
 int main(){
   RadioIOParameters rp;
   RADIOGetIoctl(&rp);
   rp.speed = SER38400;
   rp.interface = SERIAL2; // 無線モジュールを接続したポート
   RADIOSetIoctl(rp); // RADIOInit() より前にこの処理を行う
 
   RADIOInit();
   ...

とすることで、無線通信用のAPI群をeyebotと同じように使うことができます。

注意

PC用無線モジュールは、無線ネットワークのマスタになることはできません。 PC側プログラム実行時に、他のeyebotが見つからない場合、初期化エラーになります。 PC側プログラムを実行する前に、eyebot側の無線初期化を完了してください。

また、PCとの無線通信は途中で回線が切断され、再接続されないことがあります。 なるべく近距離で実行する、自前でACK処理を記述するなどの処理が必要です。 詳しくは無線のページ参照。

WindowsにおけるPC側プログラムのコンパイル方法

WindowsにおいてもほぼLinuxと同じ方法でコンパイルすることができます。 ただ、cygwinのgccでは「__imp___iobが未定義よ」と怒られたりするので、 MinGW(Win用GCC。rob61win.exeに同梱)を使用したほうがよいようです。

(1)eyebotのインストールフォルダ(デフォルトではC:\eyebot)にある MinGW-xxx.exeをインストールします。

(2)コンパイルしたいプログラム、およびWin用無線通信ライブラリ(libradio.a  デフォルトではc:\eyebot\robios61\pc-appl\wireless\windows\lib に存在) を任意のフォルダに置く。

(3)DOSプロンプトで(2)のフォルダに移動し、以下を実行。(robiosのインクルード フォルダがc:\eyebot\robios61\include, MinGWのgccの所在がc:\MinGW\binとするとき)

 c:\mingw\bin\gcc -Ic:\eyebot\robios61\include radiopc.c libradio.a

という手順で無線通信を行なうプログラムがコンパイル可能です。

シリアル通信

API

シリアルポートを用いて、1byte単位の送受信が可能です。 初期化は以下のAPIで行ないます。速度設定、エラー制御、eyebot側シリアルポート (通常はSERIAL1)を設定しています。

 OSInitRS232(SER115200, RTSCTS, SERIAL1);

1byte送受信は以下のAPIで行ないます。

 OSSendCharRS232(char c, SERIAL1);
 OSRecvRS232(char *c, SERIAL1); // 受信するまで待つ

他にも、送受信のバッファを管理する関数群が用意されています。

 OSFlushInRS232(SERIAL1); // 受信バッファをクリア
 OSFlushOutRS232(SERIAL1); // 送信バッファをクリア
 OSCheckInRS232(SERIAL1); // 受信バッファに入っている文字数
 OSCheckOutRS232(SERIAL1); // 送信バッファに入っている文字数

PCとの通信

PCとシリアルケーブルで接続し、通信を行なうことができます。例えば、

 cat > /dev/ttyS0 # キーボード入力をeyebotに送る
 cat < /dev/ttyS0 # eyebotからの受信データを表示

のように扱うことができます。

PCのプログラム中で通信を行なう場合、上記のリダイレクトを用いるのが 簡単でよいと思います。複雑な通信処理を行ないたい場合、 Serial Programming HOWTO などが参考になるかもしれません。

recv_program < /dev/ttyS0のようにした場合、ファイル受信後はctrl-cで手動終了 してやる必要がありそうです。プログラム中で/dev/ttyS0を扱った後は、終了時に

 kill(getpid(), SIGINT) // 自分にctrl-cを送る

をしてやることで、シェルに処理を戻すことができます。 (これをしないと、いつまでたっても終了しないプログラムになります?)

カメラ

eyebotには標準で(?)カメラがついてきます。低解像度では80*60, 24bitフルカラーor8bitグレースケールの撮影が可能で、より高解像度な撮影も可能です。

初期化は以下のように行ないます。引数はNORMAL固定です。

 i = CAMInit(NORMAL);

CAMInitの返り値は、接続されているカメラの種類をあらわしており、種類により高解像度撮影時の解像度が異なります。手元のeyebotでは返り値は19(eyecam-3 (6620))で、解像度は176*144でした。

高解像度撮影は以下のように行ないます。

 BYTE buf[176*144], colbuf[176*144*3];
 CAMGetFrameMONO(buf);   // 8bitグレースケール撮影
 CAMGetFrameRGB(colbuf); // 24bitカラー撮影

低解像度(80*60)撮影は以下のように行ないます。

 image buf;
 colimage colbuf;
 CAMGetFrame(buf); // グレースケール撮影
 CAMGetColFrame(&colbuf, 0); // カラー撮影

image, colimageはtypes.h内で次のように定義されています。

 #define imagecolumns 82
 #define imagerows 62
 typedef BYTE image[imagerows][imagecolumns];
 typedef BYTE colimage[imagerows][imagecolumns][3];

image, colimage型の画像データは、LCD画面に直接表示できます。 また、これらの画像データを画像処理(ラプラス、ディザ、etc)する多くのAPIが 提供されています。