2014年1月30日木曜日

Intel Galileo お試し。

 スイッチサイエンスさんでIntel Galileoボードの在庫が復活していたので、遊びでいじってみることにしました。とりあえず、ポチッと購入したものの、使い道は全く考えていません。というか、Galileoボードに関しては、「冷やかしでボード自体をちょっといじってみる」くらいしか用途が思いつきません。Linuxで電子工作的なことをやるなら、ハードウェア制御が余り入らなければ、Raspberry Piで、よりハードウェアな制御が欲し(くてLinuxも画像処理やネットワークで使いたい)い場合は、BeagleBone BlackとかRaspberry Pi + Arduino のコンビが自分としては今のところベストソリューションな感じです。
 しかし、世間(といってもかなり狭い人々の間の世界ですが・・・)で話題になっている以上、色物として触っておかないわけには行きません。(なんでさ?)
 一応、正規のArduinoの一種ですし、HDMIやサウンド入出力がないところからすると、Raspberry PiやBeagleBoneと言うよりは、「超速っのArduino」っていう部分を狙っているんだろうなぁ?という気はするので、もしかすると、RPiとBBBとの使い分けもできるかもしれません。

 まずは、Galileo用のArduino IDEをここからDownloadして、展開します。インストールは必要なく、展開してArduino.exeを起動するだけですが、ネットで見た感じだと、フォルダの長さ(階層の深さ)や間にスペースの入ったパス等が問題になるようなので、C:\の直下などに展開しておいたほうが無難なようです。

 で、早速、GalileoボードをACアダプタで起動(ACアダプタより先にUSBコネクタを接続すると壊れるかもってさ!Arduinoとかの代わりにホビーMakerを意識しているボードとは思えないんだけど・・・)して、USBに接続しようとした所、USB CllientのコネクタにマイクロUSBコネクタがささりません。よく見ると、コネクタが潰れてる・・・。化粧箱や運送されてきた箱は綺麗だったので、ボード自体の不良です・・・。まったく・・・。今まで、色々なマイコンボードを沢山購入して、使いましたが、こんな、潰れたUSBコネクタがくっついたのが検品通って出荷されるとか、初めてです。Galileoボードのクオリティの低さっていうか・・・そもそも製品としてダメダメなんじゃないの?感がなんだか心配になってきます・・・。
 送り返して交換してもらえばいいのですが、悪いのはIntelでスイッチサイエンスさんには非はないですし、なによりも、面倒なので、ラジペンで潰れたUSBコネクタを無理やりこじ開けます。



バキメキゴキボキっガリゴリッ!!



 まったく、めんどくさいボードです。で、無理やりUSBコネクタをねじ込んで、電源を入れてもPC側から認識されません。おかしいな?こじり過ぎて、USBコネクタのハンダが剥がれちゃったかな?と色々チェックしていると1分くらいしてから、やっと、「新しいハードウェア・・・、ドライバを・・・」となりました。Galieo側が起動しないとPC(Windowsマシンです)からも認識されないようです。で、ドライバはそのままでは入りません。まあ、これはArduinoでもモデルによってはそうなので、(Galileo専用の)Arduino IDEをダウンロードして解凍しておいたフォルダの「driver」フォルダを指定してドライバーをインストール・・・しようとすると「見つかりません」って言われます。なんでよ?ネットで先人の知恵を借りると、どうも、ドライバは「Arduino(IDEのルートフォルダ)\hardware\arduino\x86\tools」フォルダにある「linux-cdc-acm.inf」のinfoファイルを選択してインストールするらしい。driverフォルダにGalileoってフォルダ作って入れておいてよ・・・。

 もうダメ、ここまでで既にテンションが半分くらいに下がって来てる。

 デバイスマネージャで見ると「Gadget Serial v2.4」のように見えます。



 右クリックして、ドライバの更新で、


 手動でインストールするを選択して、
「Arduino(IDEのルートフォルダ)\hardware\arduino\x86\tools」フォルダを指定します。


 「Galileo」が見つかるので、選択して、インストールします。


 ドライバがインストールされれば、COMポートとして認識されるはずです。


 (専用)Arduino IDE のCOMポートを該当のポートに設定しておきます。

 さて、出回り始めて、まもないGalileoですが、Firmwareは既に何回かUpdateされているようなので、アップデートをはじめに行っておきます。「ヘルプ」→「Firmware Update」で開始されます。


 アップデートは数分かかります。こんな画面が表示されます。


 で、とりあえず、アップデートを終えて、改めて、LAN、ACアダプタをつないで、USBコネクタを接続。1分くらいしてPC側にCOMポートが認識されたところで、まずは、Hello,World!!代わりの定番、Lチカ。サンプルプログラム 「ファイル」→「スケッチの例」→「01Basics」→「Blink」を開いて、COMポートが正しく選択されているのを確認して、書込「→」ボタンを押し、虫眼鏡の「シリアルモニタ」ボタンを押してシリアルコンソールを開くとプログラムが実行されて、ボード上(バッテリ用2Pコネクタの近く)のLEDが点滅しました。



次に、以下の様なスケッチを実行。以下のスケッチは、たとえばこれとか、ネットワーク接続の方法やIPアドレスを調べる方法をGoogle先生に質問すると色々見つかるものを簡素化したものです。


 IPアドレスが分かれば、SSHDが動いているのでSSHログインできます。ログインは root / パスワード無し で可能です。


 ちなみに、Galileo はmicroSDカードスロットがあり、Arduino側からArduino風にmicroSDとして使う他に、こちらから Linux For SD Image をダウンロードして、microSDからの起動も可能です。自分はこちらを使うことにしました。ダウンロードした圧縮ファイルから解凍されたファイル群をFAT32でフォーマットしたmicroSDカードのルートに配置して、カードスロットに挿して電源を入れるだけでOKです。

 この辺りまで、ゴニョゴニョとやったところで、こちらのサイトを発見。「ひとりぶろぐ - Intelのx86 CPU搭載「インテルGalileo開発ボード」をMacで試してみた」が参考になります。

 それでは、GalileoのLinux部分を触ってみたいと思います。前述のサイトと合わせて、こちらのサイトの情報がピン情報などのリファレンスとして非常に有用です。

 ボード上のLEDを光らせてみます。sketchのバイナリファイルがあるとLinux上からの直接IO操作の妨げになる(sketch用のデーモンがIOを掴んでいる)らしいので、/sketch/ 以下にあるファイルを全て rm * してしまい、一旦再起動をかけます。ボード上のLEDはGPIO3につながっているので、

(上図はこちらのものを頂いています。)


 こんな感じで操作すると、

   echo -n "3" > /sys/class/gpio/export
   echo -n  "out" > /sys/class/gpio/gpio3/direction   → 入出力方向
   echo -n "1" > /sys/class/gpio/gpio3/value   → 点灯
   echo -n "0" > /sys/class/gpio/gpio3/value   → 消灯
   echo -n "3" > /sys/class/gpio/unexport   → 解放

ボード上のLEDの点灯・消灯が確認できます。

 次に、上記のコマンドライン操作をpythonのSimpleHTTPServerを使って、ブラウザ上から操作するというのを試します。これは、ひとりぶろぐさんのサンプルをそのままボードのLEDに置き換えたものです。(感謝)

以下、 HelloGalileoLED.py として /home/root/下に配置。

#!/usr/bin/env python

import SimpleHTTPServer
import SocketServer
import os

os.system('/bin/echo -n "3" > /sys/class/gpio/export')
os.system('/bin/echo -n "out" > /sys/class/gpio/gpio3/direction')
os.system('/bin/echo -n "0" > /sys/class/gpio/gpio3/value')

class MyRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/on':
            os.system('/bin/echo -n "1" > /sys/class/gpio/gpio3/value')
            self.path = '/on.html'
        if self.path == '/off':
            os.system('/bin/echo -n "0" > /sys/class/gpio/gpio3/value')
            self.path = '/off.html'
        return SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)

Handler = MyRequestHandler
server = SocketServer.TCPServer(('0.0.0.0', 8080), Handler)

server.serve_forever()

ブラウザ表示用のHTMLファイルを on.html として /home/root/下に配置。

<html>
<head><title></title></head>
<body>
    <h1>ON
</h1>

</body>
</html>

同様にHTMLファイルを off.html として /home/root/下に配置。

<html>
<head><title></title></head>
<body>
<h1>OFF</h1>
</body>
</html>

/home/root/ で

   python ./HelloGalileoLED.py

として起動します。PCのブラウザから

   http:// GalileoのIPアドレス /on   → LED点灯
   http:// GalileoのIPアドレス /off   → LED消灯

の動作が確認できるはずです。起動したコンソールでCntl+Cでプログラムを停止できますが、gpioの開放処理を入れていないので、手動で

   echo -n "3" > /sys/class/gpio/unexport   → 解放

する必要があります。

 とりあえず、今回はここら辺まで。気が向いたらArduino用シールドやセンサを試してみたいと思います。今回はじめていじってみた感想としては、「ラジペンがないとはじめられないようじゃ、Arduinoの手軽さはないなぁ」というところでしょうか。









2014年1月25日土曜日

USB Sniper RIfle を Raspberry Pi で動かしてみた。

 以前に Raspberry Pi で USBスカッとミサイルランチャーを動かしたことがあるんですが、先日ネットを徘徊していたところ、上海問屋でUSBスナイパーライフルというのが売っていたので、じゃあ、解析してみようかなということで、ポチリました。




 ものとしては、Axpro というところの製品のようです。スカッとミサイルランチャーのときのようにUSB SniferでUSBに流れているパケットを調べようとしたところ、非常に複雑でコマンドの長さも上下左右・発射それぞれバラバラでした。これは、解析は無理かな?って思ったんですが、デバイスマネージャをよく見たら、Serial-USB変換デバイスとしてCOMポートとして認識されています。ミサイルランチャーの時はHIDデバイスとして認識されていたので、直接バイナリデータを送ってやることで制御出来ましたが、今回はそうは行きません。ただ、Raspberry PiでもこのデバイスがUSB-Serial変換デバイスとしてttyとして見えてしまえば、あとはファイルへコマンドを書き込めばいいだけです。
 さて、改めて、COMポートデバイスとしてスナイパーライフルを解析してみたところ、実際にやりとりされているコマンドは極めて簡単で、テキストでUP-xxとかLEFT-xx、FIRE-xxみたいなコマンドに終端文字LFを付けて送信しているだけです。実際には、開始時に何らかの初期化コマンドを送っていて、これには何種類かあるようなのですが、今回はキャプチャした内容から適当に一種類を選択して初期化時に送信します。あとは、UP-30とかLEFT-60とか方向にハイフンと数字30、60、90で移動角度の大きさ具合が選べるような感じのコマンドをLF付きで送ります。コマンドに対する応答もレスポンスしているみたいですが、今回は無視です。
 それと、カメラも付いているので、これも映るといいな。

まずは、Raspberr Pi でデバイスをUSB-Serialとして認識してくれるか?
試しに接続したところ、無事、"/dev/ttyUSB0"として認識してくれているようです。これなら、制御は行けそう。次にカメラ・・、こちらもOK。USBカメラとして認識しています。ならば、OpenCVでとりあえずキャプチャした画像を表示してみましょう。




 Raspberry Pi に USBスナイパーライフルを接続して、WindowsからXで接続してOpenCVのcvWaitkey でカーソルとスペースキーを取得してライフルを制御して、カメラ画像をOpenCVのフレームに表示しています。意外と簡単に動かせました。ただ、カメラの画像表示は1~2秒遅延するので、カメラの画像を見ながらの操作でターゲッティングするのは無理そう・・・。

 スカッとミサイルランチャーのときはArduinoを使って、こんなのを作ったんだけど、今回のはサイズが大きいし、外部電源が必要なので自走化は難しそう。

今回のソースはこんな感じ。

#define _POSIX_SOURCE 1

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <sys/signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <ctype.h>
#include <time.h>
#include <sys/time.h>

#include <opencv/cv.h>
#include <opencv/highgui.h>

// capture size.
#define CAP_WIDTH 320
#define CAP_HEIGHT 240

// grobal variable definition.
int fd;  // file descriptor.
struct termios oldTermIo; // for keep now setting.

// prototype.
int Serial_Open(char *serialDev);
void Serial_Close(void);
int Serial_PutChar(unsigned char c);
int Serial_PutString(char *s);
unsigned char Serial_GetChar(void);

int main(int argc, char *argv[])
{
 char rBuffer[1024];
 char sBuffer[256];
 char *serialDev = "/dev/ttyUSB0";
 char c;

 CvCapture *capture = 0;
 IplImage *frame = 0;

 // create capture.
 capture = cvCreateCameraCapture(0);

 // capture size.
 cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, CAP_WIDTH);
 cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, CAP_HEIGHT);

 // clear buffer.
 memset(rBuffer, '\0', 1024);
 memset(sBuffer, '\0', 256);

 // open serial port.
 Serial_Open(serialDev);
 sleep(1);

 // create window.
 cvNamedWindow("Sniper Rifle", CV_WINDOW_AUTOSIZE);

 // initialize.
 Serial_PutString("@CPSM\n");

 while(1)
 {
  // capture and show.
  frame = cvQueryFrame(capture);
  cvShowImage("Sniper Rifle", frame);

  c = cvWaitKey(50);
  if (c == 27)
   break;  // ESC
  switch (c)
  {
  case 82: // ^
   Serial_PutString("UP-60\n");
   break;
  case 84: // v
   Serial_PutString("DOWN-60\n");
   break;
  case 81: // <
   Serial_PutString("LEFT-90\n");
   break;
  case 83: // >
   Serial_PutString("RIGHT-90\n");
   break;
  case 32: // space
   Serial_PutString("FIRE-2580\n");
   break;
  default:
   break;
  }
 }

 // dispose OpenCV.
 cvReleaseCapture(&capture);
 cvDestroyWindow("Sniper Rifle");

 // close serial port.
 Serial_Close();

 return 0;
}

int Serial_Open(char *serialDev)
{
 struct termios newTermIo;

 // open device.
 fd = open(serialDev, O_RDWR | O_NOCTTY);
 if (fd < 0)
 {
  perror(serialDev);
  exit(-1);
 }

 // keep old setting.
 tcgetattr(fd, &oldTermIo);

 // new setting.
 newTermIo.c_iflag = 0;
 newTermIo.c_oflag = 0;
 newTermIo.c_cflag = 0;
 newTermIo.c_lflag = 0;
 newTermIo.c_line = 0;
 memset(newTermIo.c_cc, '\0', sizeof(newTermIo.c_cc));
 //bzero(newTermIo.c_cc, sizeof(newTermIo.c_cc));

 // 9600bps, 8bit, no parity, 1 stop bit, local, read enable
 newTermIo.c_cflag = B9600 | CS8 | CLOCAL | CREAD;
 // ignore parity error.
 newTermIo.c_iflag = IGNPAR;
 // raw mode.
 newTermIo.c_oflag = 0;
 // non-canonical, no echo
 newTermIo.c_lflag = 0;
 // inter-character timer
 newTermIo.c_cc[VTIME] = 0;
 newTermIo.c_cc[VMIN] = 1;

 // clear line.
 tcflush(fd, TCIFLUSH);

 // set.
 tcsetattr(fd, TCSANOW, &newTermIo);

 return (0);
}

void Serial_Close(void)
{
 tcsetattr(fd, TCSANOW, &oldTermIo);
 close(fd);
}

int Serial_PutChar(unsigned char c)
{
 if (write(fd, &c, 1) != 1)
  return (-1);

 return (0);
}

int Serial_PutString(char *s)
{
 if (write(fd, s, strlen(s)) <= 0)
  return (-1);

 return (0);
}

unsigned char Serial_GetChar(void)
{
 unsigned char c;
 
 read(fd, (char *)&c, 1);

 return (c);
}

2014年1月7日火曜日

Robi No.33~NO.45

 年末年始の時間を使って、12号分ほどたまったRobiの組み立てを行いました。前回は右足を組み立てましたが、今回のNo.33~45は左足部分になります。
 No.33は股関節サーボで実際の組み立ては後回し、No.34は床掃除用?のブラシというどうでもいい部品、No.35もサーボのID設定だけなので、実際はNo.36からの組み立てとなります。

 No,36で、左足首(横回転)のサーボにカバーを取り付けます。



 No.38ではフレームを取り付け。



 No.39 は足首部分です。




 No.40~42でスネ・膝・もも部分。





 No.43~45で股関節部分。



 両足が出来上がって


 上半身と並べたところ。


 写真ではわかりにくいですが、頭部および胴部の白いパーツがかなりひどく茶褐色に変色しています。黒色パーツと接する部分から変色が起こっています。これに関してはディアゴで対策済みパーツを支給して頂けるとです。ただ、実は頭部パーツを先行販売でやっていて一度交換してもらっているので、二度目は交換してもらえないかと心配したのですが、カスタマーサービスに連絡したところ、交換してもらえるということなので安心しました。

 これから、バッテリやらCPUボードが来るはずなので、やっと動かせる日も近い?かな?まあ、コネクタさえどうにかなれば、Robo XEROとおなじコマンド体系で動かせることは確認済みなんですが。