2012年5月31日木曜日

SparkFun USBホストシールド

 今日のおもちゃは、SparkFunのUSBホストシールドです。スイッチサイエンスさん、千石さん等で入手できます。元になっているのはこのプロジェクトなのかな?ライブラリ等がダウンロードできます。また、シールド自体には(少なくとも自分が買ったものは)ピンソケットが実装されていなかったので、別途スタック用のピンソケットを用意してハンダ付けしました。


 こちらのプロジェクトサイトを見るとキーボードやゲームコントローラなどのHIDやGPS、デジカメ等いろんな物を接続して動かしていて、びっくりなんですが、今回、自分が試してみたいのはADK (Android Open Accessory Development Kit)です。通常のAndroidのソフト開発ほど巷に情報は溢れていませんが、Google先生にお伺いを立てると、結構、色々やられている先人の方々がいらっしゃるので参考になります。まだ、始めたばかりでちゃんと理解していないのですが、Android端末とArduino(等のマイコン)を接続する手段としてマイコン側のUSBホスト機能を使う場合には、Google謹製のいわゆるADKによる接続と、それ以外にもMicrobridgeという方法があるようです。
 ADKはGoogle謹製の公式な手法ですが、Androidのバージョンが3.1(または2.3.4)以上でないと対応しておらず、しかも、バージョン的に対応していても、該当APIを端末メーカが入れておいてくれないと使えないので、「使える端末がそれなりに限られる」ようです。
 MicrobridgeはAndroidのADB(デバッグ)機能を利用しているので、ほとんど端末を選ぶことなく利用できるようです。ただし、ADBを使うので端末をデバッグモードにしておかないと行けません。
 幸い?手元には新旧いくつかのAndroid端末がありますので、それぞれ試していこうと思っています。

2012年5月21日月曜日

SmartWatchの開発環境

SmartWatchのアプリケーションはどうやって開発するのだろうと思って調べてみました。Sonymobileのサイトに Smart Extension SDK をダウンロードできるページ があるので、これをダウンロードしてきます。が、それ以前に、Androidのアプリケーションを開発するための標準的な環境が必要ですので、Eclipse Android SDK の環境が必要です。Androidの開発環境構築に関してはネット上 や書籍等で様々な情報が手に入ります。
標準的なAndroid開発環境ができた状態で、「Android SDK Manager」を起動して、Android 2.3.3(API10)の中にある「EDK2.0」をインストールします。メーカー・機種依存のSDKなので通常はインストールされていないと思いますが、全選択で行った場合などは既にインストールされているかもしれません。EDK2.0をインストールしたら、「AVD Manager」を起動して、エミュレータを作成しておきます。「新規」ボタンでターゲットにEDK2.0を選択して、あとはスキンなどを適宜選択してAVDを作成しておきます。
先にダウンロードした Smart Extension SDK のzipファイルを解凍すると、PDFファイルと幾つかのフォルダが作成されます。その中の「Code_examples」フォルダの中にTutorialのPDFドキュメントと

  • SampleControlExtension
  • SampleNotificationExtension
  • SampleSensorExtension
  • SampleWidgetExtension

  • SmartExtensionAPI
  • SmartExtensionUtils
という6個のサンプルプロジェクトフォルダが作成されます。
TutorialのPDFをざっと見た感じでは、上の4プロジェクトがアプリやウィジェットのサンプルプログラムで、下の2プロジェクトはそれらで使うライブラリのようです。「SmartExtensionAPI」がSmart Extensionの基本的なAPIで「SmartExtensionUtils」は「SmartExtensionAPI」を使いやすくするためのライブラリのようです。上の4個のサンプルプロジェクトは下の2つの「SmartExtensionUtils」は「SmartExtensionAPI」をライブラリとして利用して作成されているようです。
自分はeclipseを使い慣れていないせいか、こういったSDKやネットで公開されているようなサンプルプロジェクトをeclipseにインポートしようとすると、ほぼ必ずうまくいきません・・・。当然今回もうまくインポートできませんでした。そこで、Android 2.1用のプロジェクトを新規に作成し、ソース(~.java)やリソース、xmlファイルなどを元からコピペしながら、import文やxmlファイル内のパスなどを手で直して、まずは「SmartExtensionAPI」プロジェクトをエラーが出ない状態まで持って行きました。同様にして、「SmartExtensionUtils」プロジェクトも準備しました。
次に「SampleControlExtension」をコピーしつつ、アニメーション表示などの部分をそぎ落として、タッチイベントとスワイプイベントを取得するだけのサンプルを作成してみました。
Youtubeにエミュレータの画面キャプチャをUpしたんですが、なんか、Upされた動画が壊れてますね。ナナメってます。なんでだろう。


金属バンドにしました

  スマホ以前に携帯を持つようになってから、おそらく十年以上は腕時計をしていませんでした。あたらしいおもちゃとしてSmartWatchを買ってからは毎日腕時計として装着しているわけですが、買った時についてくるラバーバンドがあまり良くありません。質が悪いということではないのですが、汗で蒸れてしまって、不快なんです。長袖の柔らかい生地の服を着ているときは、服の袖の上にSwartWatchを装着することで、何とかなっていたんですが、スーツの時のシャツや、暖かい日の半袖のときに直接肌にはめると、30分おきくらいにベルトを外していたりしました。
そこで、買い物に行った際に時計屋さんに寄って、金属のベルトを買って来ました。SmartWatchには付録のベルトの他に、自分で用意したベルトを使えるように金属製のステーがついてきます。幅20mmの通常の時計ベルトが使えます。金属ベルトに変えたことで、一日身につけたままでも大丈夫なようになりましたし、気持ちおもちゃっぽい外観が本物の時計っぽく?見えるようになった気がします。
ちなみにSmartWatch自体の電池はメールや着信などのイベント通知を受ける目的で使っている分には数日は持ちますので、充電は2~3日に一度行えば自分の場合は間に合います。時計として、2~3日に一度充電が必要とかありえませんが・・・、スマホとかモバイルPCとかのガジェット類としては毎日充電はふつうのコトなので、自分としてはあまり抵抗はありません。


2012年5月16日水曜日

アナログ入力で距離センサを試す。

今日は午前三時頃に目が覚めてしまい、眠くもならないので、夜なべでケーブルづくりです。


 久しぶりに圧着したら、端子金具が曲がってしまいました・・・。しばらくやらないと、こういうものは鈍ってしまいますね。で、なぜにこんなケーブルを作っているかというと


 先日、実家に戻った際に在庫の中から、シャープのPSD距離センサがいくつか発掘されたので、今いじっているArduinoにでもつないでみようと思ったからです。しかし、このコネクタ、小さくて作りづらいです。なんか他のにしてくれればよかったのに。


 とりあえず、お試しなので、基板側のコネクタをブレッドボードに挿して、電源、グランド、それとセンサの出力をArduinoのアナログ入力へ接続します。


センサの発光素子が光っているのがわかります。赤外線なので肉眼では見えませんが、デジカメを通すと光っているのがわかります。赤外線リモコンの作成などをするときにとりあえず赤外LEDが光っているのかとかを確認するのにも、携帯のデジカメなどを使うと便利です。

PSDセンサの出力電圧を距離に変換するのですが、このセンサの出力はリニアではありません。


きちんと距離を図りたいのであれば、何点か電圧と距離のテーブルを持って、その間を補間して求めるようなことが必要になるかと思います。今回は「なんとなく前方に障害物がある」くらいを検出出来れば、モーターシールドを載せたおもちゃの台車に使えないかな?と、そんな程度なので、ある閾値を判別出来ればよしとしようと思います。

はじめは単純に Loop内でアナログ入力を拾って、その数値をコンソールに出力していましたが、O'Reilly Japan の 「Prototyping Lab (小林 茂さん著)」にちょうどそのまま、PSDセンサで距離を測る解説が掲載されていたので、そのスケッチを使わせてもらいました。処理としては、上の電圧-距離グラフを反比例式に見立てて、定数を測定したアナログ値で割り算することで距離を求めます。センサの個々の特性により定数は適宜決める必要があります。また、センサには直近は測れないデッドゾーンがありますから、取り付け位置を奥まらせるとか、オフセットを載せるとかで調整することになります。

2012年5月8日火曜日

Motor Shield

 前回の Wireless SD Shield を用いたお試しで、XBeeとBluetoothでのワイヤレス接続は出来るようになりました。XBee WiFi による無線LAN接続がまだ成功していませんが、そっちは放おって置いて他のShieldへ浮気です。
 今回のおもちゃは Motor Shield R3 です。基本的にはArduino の PWM(アナログ)出力端子にモータードライバICが接続されたものです。デジタル出力端子を使って方向とブレーキ信号を制御します。実家に戻れば東芝のTA72とかTA84とかのHブリッジドライバICの在庫があるので自作する手もあるんですが、なんとなくコレクション的に純正のMotor Shieldを買ってしまいました。
 仕様または回路図(あるいは実物のIC)を見ると STマイクロのL298 というドライバを使っているのがわかります。
 Motor Shield には 外部電源とモーター接続用のターミナル端子6口の他に電流センサ(アナログ入力)の機能などもあるようです。2chのDCモーターの制御ができ、Arduinoの D3とD11のPWMでそれぞれのモーターのパワーを、D12、D13のディジタル出力で回転方向を制御します。
 まずは、モータ用に別電源を使うようにするためにパターンカットをしました。このMotor Shield R3 はデフォルトの状態だと Vin からモータ電源を引いてきます。ターミナルに外部電源を接続して利用するためには基板裏側の「Vin Connect」というパターンをカットする必要があります。


 上の画像の部分のパターンをカットするんですが、はじめここのパターンカットが中途半端な状態でモータが動いたり動かなかったりという状態になってしまいました。外部端子からの電源とVinからの電源がぶつかっていました。改めてきちんとカットすることで正常に動くようになりました。

 Motor Shield の外観はこんな感じです。


 Motor Shield なのでモーターを動かさないと意味が無いので、今回は、たまたま手持ちのあった タミヤのリモコンロボットセットの一部を使いました。とりあえず、こんなような感じで接続して、


  今は電源は有線で供給しているし、基板も車体に載せていないので、車体をひっくり返して車輪の回転を確認します。


 作りかけの中途半端な状態ですが、ソースはこんな感じ。

// Motor Shield Rev.3 のピン設定。
#define PIN_CH1_PWM 3
#define PIN_CH1_DIR 12
#define PIN_CH1_BRK 9
#define PIN_CH2_PWM 11
#define PIN_CH2_DIR 13
#define PIN_CH2_BRK 8

// 各モータの配置・配線で正逆転を適宜変更。
#define CH1_CW HIGH
#define CH1_CCW LOW
#define CH2_CW LOW
#define CH2_CCW HIGH

#define DIR_CW 0
#define DIR_CCW 1

static char CHAR_CR = 0x0d;
static char CHAR_LF = 0x0a;

char rcvChar;
char rcvBuf[64];
int rcvCnt;
boolean isRcvCmd;
int spd1, spd2;

// 回転方向(出力ピン)の設定。
// ch - 設定チャネル 1 or 2
// dir - 回転方向 DIR_CWで正転、DIR_CCWで逆転
// 戻り値 なし。
void setDirection(int ch, int dir)
{
if(ch == 1)
{
if(dir == DIR_CW)
{
digitalWrite(PIN_CH1_DIR, CH1_CW);
}
else if (dir == DIR_CCW)
{
digitalWrite(PIN_CH1_DIR, CH1_CCW);
}
}
else if (ch == 2)
{
if (dir == DIR_CW)
{
digitalWrite(PIN_CH2_DIR, CH2_CW);
}
else if (dir == DIR_CCW)
{
digitalWrite(PIN_CH2_DIR, CH2_CCW);
}
}
}

// 各チャネルのモータ出力(スピード)設定。
// ch - 設定チャネル 1 or 2
// spd - 設定出力。0~255
// 戻り値 なし。
boolean setMotorSpeed(int ch, int spd)
{
if ((ch != 1) && (ch != 2)) return false;
if (spd > 255) spd = 255;
if (spd < -255) spd = -255;

if (spd < 0)
{
spd = -1 * spd;
setDirection(ch, DIR_CCW);
}
else
{
setDirection(ch, DIR_CW);
}

if (ch == 1)
{
analogWrite(PIN_CH1_PWM, spd);
}
else if (ch == 2)
{
analogWrite(PIN_CH2_PWM, spd);
}

return true;
}

// モータ出力 ch1,2設定。
// ch1spd - ch1の出力。0~255
// ch2spd - ch2の出力。0~255
// 戻り値 なし。
void setMotorSpeed2(int ch1spd, int ch2spd)
{
setMotorSpeed(1, ch1spd);
setMotorSpeed(2, ch2spd);
}

// モータ設定の初期化。
// 引数 なし。
// 戻り値 なし。
void initMotor()
{
pinMode(PIN_CH1_PWM, OUTPUT);
pinMode(PIN_CH1_DIR, OUTPUT);
pinMode(PIN_CH1_BRK, OUTPUT);
pinMode(PIN_CH2_PWM, OUTPUT);
pinMode(PIN_CH2_DIR, OUTPUT);
pinMode(PIN_CH2_BRK, OUTPUT);

setMotorSpeed2(0, 0);

digitalWrite(PIN_CH1_BRK, LOW);
digitalWrite(PIN_CH2_BRK, LOW);
}


// 初期設定。
void setup()
{
initMotor();

spd1 = 0;
spd2 = 0;
setMotorSpeed2(spd1, spd2);

Serial.begin(9600);
}

// メインループ。
void loop()
{
// シリアル受信処理。受信バッファにデータがあれば、
if (Serial.available() > 0)
{
/// 1文字読み込み。
rcvChar = Serial.read();
if ((rcvChar == CHAR_CR) || (rcvChar == CHAR_LF))
{
/// 改行(終端)文字の場合は、
if (rcvCnt > 0)
{
//// 既に1文字以上受診していれば、文字列終端(null)を
//// 設定して、コマンド受信フラグを立てる。
rcvBuf[rcvCnt] = '\0';
isRcvCmd = true;
rcvCnt = 0;
}
}
else
{
/// 改行文字でない場合は配列に順次取り込み。
rcvBuf[rcvCnt] = rcvChar;
rcvCnt++;
}
}

// コマンド解析処理。
if (isRcvCmd == true)
{
Serial.println(rcvBuf);
isRcvCmd = false;

if (rcvBuf[0] == '0')
{
digitalWrite(PIN_CH1_BRK, HIGH);
digitalWrite(PIN_CH2_BRK, HIGH);
spd1 = 0;
spd2 = 0;
setMotorSpeed2(spd1, spd2);
delay(200);
digitalWrite(PIN_CH1_BRK, LOW);
digitalWrite(PIN_CH2_BRK, LOW);
}
else if (rcvBuf[0] == '+')
{
spd1 += 25;
spd2 += 25;
if (spd1 > 255) spd1 = 255;
if (spd2 > 255) spd2 = 255;
setMotorSpeed2(spd1, spd2);
}
else if (rcvBuf[0] == '-')
{
spd1 -= 25;
spd2 -= 25;
if (spd1 < -255) spd1 = -255;
if (spd2 < -255) spd2 = -255;
setMotorSpeed2(spd1, spd2);
}

Serial.print(spd1, DEC);
Serial.print(",");
Serial.println(spd2, DEC);
}
}

2012年5月4日金曜日

Wireless Shield

 Ethernet Shieldに続いて、Wireless SD Shieldを試してみました。Wireless ShieldはXBeeのモジュールを搭載できるシールドです。XBeeのモジュールはコネクタが2mmピッチとやや特殊なので、その変換を考えなくてすむのと、スイッチ切り替えでUSB経由でモジュールをPC接続できるので設定ユーティリティやモジュール単体の通信テストの際にも便利です。
 まず、XBee ZBモジュールを2つ用意してWireless SD ShieldとPC間で通信というのは問題なく出来ました。Arduino側にシリアルポートから受信した文字をエコーバックするプログラムを入れておいて、PC側のターミナルから送受信を確認しました。CQ出版さんのエレキジャックのページとかが参考になりました。ただ、考えてみるとXBeeというかZigBeeは省電力ということなのでバッテリー動作や太陽電池等でセンシングをしてその情報を離れたホストに送るような使い方には向いていると思うのですが、自分の用途としては(といっても、まだ目的は決めてないけど、なんとなく今想定しているのは)ノートPCとかタブレットやスマホ等のAndroid端末に標準で内蔵されているような無線の機能がいいかなぁ?と思い、XBee WiFiも試してみました。当初、単純にWireless SD ShieldのZBモジュールをWiFiモジュールに挿し換えてみたんですが、設定用のX-CTUというDigiのツールですら認識してくれません。そこで、調べてみようとGoogleで「XBee Wi」くらいまで入力したところ検索候補に「XBee WiFi コンデンサ」と出てきます。電源か・・・。で、その検索候補で検索してみると、やはり電源系が原因でうまく動かなかったみたいな情報がたくさん出てきます。このあたりを見ると断続的に大電流を吸い込むので大きめのコンデンサを入れる対策が効果があるとのことで、早速実施。すると、無事X-CTUで認識して、アクセスポイントの検索まで行ってくれるようになりました。しかし、接続しようとするとタイムアウトしてうまく接続できません。う~んいいところまで来てるんだけど・・・。この先は後日、試してみようと思います。


 上の写真がパスコンを追加したところ。ちなみに左の方にはっているラッピング線は


 せっかくなのでBluetoothも試したいと思い、SparkFunのシリアル通信モジュールを載せてみました。このBluetooth通信モジュールはあまり資料がなかったんですが、こちらのサイトを参考にさせていただいて、すんなり通信成功。助かりました。ありがとう。

2012年5月1日火曜日

Ethernet Shield

Arduino の特徴として”Shields"(シールド)と呼ばれる、スタック基板での拡張があります。PC104等で使うような足長のピンソケットで基板を積み重ねて、ブロック感覚で機能拡張ができます。この手法は、自分もH8やSHマイコンで実験回路を組むときによく使います。 今回は「Ethernet Shield」(イーサネットシールド)を入手して、お試ししてみました。




Arduino は UNO R3 で Ethernet Shield は microSDスロット付きのR3です。ArduinoとEthernet ShieldはSPIを使って通信しているようです。SPI通信に使用しているのはICSPの6ピン端子のようです。加えてmicroSDの制御用にD4ピンが使われているようです。ってことは、ICSPで接続できないArduinoではこのEthernet Shieldは使えないってことかな?ちなみにEthernetのコントローラはWiznetの W5100 です。

Arduino-IDEのサンプルを元に、telnetでArduinoに接続して文字を送信すると、Arduinoが受信した文字をエコーバックしつつ、シリアル(USB)に出力しつつ、microSDにも書き込むような動きをさせてみました。


#include <spi.h>
#include <ethernet.h>
#include <sd.h>

// DHCPか固定IPかの選択。(trueでDCHCP)
boolean isEnableDHCP = false;

// ネットワーク設定。
/// MACアドレスは必須。シールド裏側のシールを参照。
byte mac[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
/// 以下、固定IPの場合に適宜設定。
IPAddress ip(123, 123, 123, 123);
IPAddress gateway(123, 123, 123, 123);
IPAddress subnet(255, 255, 255, 0);

// port23(telnet)でサーバーオブジェクト作成。
EthernetServer server(23);
boolean gotAMessage = false;

// SDカード書込み用ファイル。
File sdFile;

// 初期化。
void setup()
{
// シリアルポートの初期化。
Serial.begin(9600);

// Ethernetデバイスの初期化。
Serial.print("Initializing Ethernet...");
if (isEnableDHCP == true)
{
/// DHCPで初期化。
if (Ethernet.begin(mac) == 0)
{
//// DHCP取得に失敗。
Serial.println("Failed to configure Ethernet using DHCP");
while(true);
}
else
{
//// DHCP取得できたら、IPをシリアルに出力。
Serial.print("IP Address: ");
for (byte b = 0; b < 4; b++)
{
Serial.print(Ethernet.localIP()[b], DEC);
Serial.print(".");
}
Serial.println();
}
}
else
{
// 固定IP。
Ethernet.begin(mac, ip, gateway, subnet);
}

// SDカードの初期化。
Serial.print("Initializing SD card...");
//pinMode(10, OUTPUT);
if(!SD.begin(4))
{
Serial.println("SD card initialization failed!");
return;
}

// リスナ開始。
server.begin();

// ファイルオープン。
sdFile = SD.open("test.txt", FILE_WRITE);
// ファイルへ書き込み。
Serial.println("Writing to test.txt...");
sdFile.println("Start...");
// ファイルクローズ。
sdFile.close();

}

// メインループ。
void loop()
{
// クライアント接続を取得。
EthernetClient client = server.available();

// クライアント接続があれば、
if (client) {
// メッセージ有り状態で無い(接続開始)なら
if (!gotAMessage) {
// シリアルポートにメッセージ出力。
Serial.println("We have a new client");
// メッセージ有り状態へ。
gotAMessage = true;
}

// クライアントからのデータを取得。
char thisChar = client.read();
// クライアントへエコーバック。
server.write(thisChar);
// シリアルポートへも出力。
Serial.print(thisChar);

// ファイルへも書込み。
sdFile = SD.open("test.txt", FILE_WRITE);
sdFile.print(thisChar);
sdFile.close();

}
}




Arduino の開発環境

Arduiono はAtmelのAVRマイコンが搭載されたマイコンボードなわけなんですが、特徴として「オープン」なことを謳ってます。Arduinoの公式サイト へ行くと回路図などのハードウェアの資料とともに開発環境のArduino-IDEもダウンロードできます。早速、IDEをダウンロードして展開して開発環境を準備しました。現行のIDEはVer.1.0 でそれ以前のVer.0.23からは大きく仕様変更されたようで、ネット上のリソースや書籍のサンプルを利用しようとした場合にコンパイルが通らないことがあるようです。そのような場合は、船田さんの日本語Arduino Wiki がとても役に立ちます。すばらしい資料をありがとうございます。

ディアゴのROBO XERO

 20号くらいから溜めっぱなしになっていたディアゴスティーニのROBO XERO を29日と30日を使って組み立てました。あと10号くらいで完結なので、動き出すのが楽しみです。

 それにしても、自分はいったいディアゴにいくら貢いでいるんだろう。次は戦車あたりかな?
おくればせながら、Arduinoというものを触り始めました。子供の時からにわかマイコン野郎だった自分としては飛びつくのが遅れましたが、すでにH8とかSHで遊んでいたのであまりその存在を気にしてなかったという感じだったのです。しかし、
先日何気なくアマゾンを徘徊していたらマイコン基板らしきものが目を引いて、見てみたらArduinoというちまたでは有名なオープンのプラットフォームみたいな感じだったので、教えてGoogle先生っ!ってやったら、皆さん色々やられていて、ミーハーマイコン野郎としては、
慌ててポチッたわけですが、目的とか使い道はいっさい考えていません・・・。でも、アマゾンでクリックして即日マイコンが届くって凄くない?いまどきあたりまえ?ボク的にはマイコンっていったら、秋月とか千石とかそういう(どういう?)ダークな世界?で扱われて、若松とかマルツで売っているのを見て垢抜けたな?って思ったんだけど。アマゾンで売ってるですよ。春のワンピース特集とかお鍋とかDVDとかと一緒に。すげぇー。イイ時代ニナッタナーと思います。


SmartWatch MN2 を買いました。

 Sonyの SmartWatch MN2 を買いました。これで、メールもXperia本体を取り出して確認する必要も減るし、スケジュールの参照や通知もできることは極力Smartwatch側でやれば、Xperiaのバッテリー節約もできる・・・って思ったら、どうもそうは行きませんでした。Bluetooth通信をしているのでその分の消費は覚悟していたんですが、むしろXperiaのバッテリーの減りが急加速したような・・・。
 自分でSmartWatchのアプリを作れるのか調べてみたところ、Sony Mobile のページにSDK等の資料 があったんですが、どうもそれを読むと(英語が苦手で解釈が間違っているかもしれないけど)、SmartWatchのアプリってSmartWatch側で動くんじゃなくて、Android本体側で動いて、画面やタッチ等のUI情報をBluetoothでSmartWatchとAndroid本体間でやり取りしているように見えます。つまり、SmartWatchを使えば使うほど本体のCPUとかが稼働して本体の電池が消費されるような・・・。
う~ん。ちょっと思惑が外れたかな。まあ、おもちゃとしては面白いからいいんだけど。
 あと、外観とか質感は本当に「おもちゃ」みたいです。iPod nanoとか普通の腕時計を期待すると、かなりがっかりな、スカスカのプラスチィックで、お菓子のおまけについてくる子供のおもちゃみたいな感じです。