Ringでリモコン

あのRingが届きました。


iPhoneアプリで好きなジェスチャーとアクションを対応付けして使います(もちろん設定後は、アプリがバックグラウンドに回っていてもRingの操作を受け付けてくれます)。
標準アクションだけでもいろいろな操作に対応していますが、任意のURLにGETリクエストを送ることができるため、新しいアクションを作るのも比較的簡単。そこで、ひとまず部屋にあるものをいろいろ操作して魔法気分を味わってみることにしました。


とりあえず、照明のON/OFF。


ArduinoEthernetシールドをつけ、付属スケッチのWebサーバをちょっと改造して、アクセスがくるたびに適当なピンの出力のHIGH/LOWが切り替わるようにします。そして、その出力をSSRに入れ、AC出力をトグルできるようにします。


そんでもって、適当なジェスチャー(電球を描いてるつもり)に対して、 ArduinoのwebサーバのURLを開くアクションを設定すれば、準備は完了。

早速、実際に照明をON/OFFしてみました。(ピコピコ鳴ってるのはArduinoに取り付けた圧電スピーカーの音で、アクセスがあった時に鳴らしてます。)


もひとつ、同じようにルンバも操作(起動)できるようにしてみました。ルンバのリモコン操作は以下の日記で書いたようにXBeeを使ってます。
ルンバをXBeeでリモコン操作 - Okiraku Programming

同じく、CLEANボタンを押すコマンドを送信する処理を書いたCGIのURLを開くよう設定して、

試してみると…

ジェスチャー一つで部屋を掃除できるようになりました。


さて、難点もいくつか。結構大きく、重さも感じる。そのかわりバッテリはジェスチャー1000回分持つそうなのでまだましか。それよりも、iPhoneとはBluetooth接続しているのですが、RingとiPhoneが2m以内の距離にある必要があります。これはちょっと狭い。。iPhoneを目の前の机に置いていても、腕を伸ばしただけで接続が切れるレベル。しかも再接続に失敗することが多い。特にMacなどBLEを喋れるデバイスが近くにあると高確率で再接続できないような気がします。 iPhoneアプリをホームボタンのダプルプッシュで強制終了して再起動すると概ね再接続できますが。。


というわけで、常用はちょっと困難ですが、なかなか魅力的なデバイスではあります。

販促品のLEDファンのデータを書き換えてみた

とあるカンファレンスのIntelブースで、販促品(?)のLEDつきファンを貰いました。
スイッチを入れるとファンが回転し、羽根に入っている7つのLEDが空中に文字を描き出すというもの。
もともとは求人広告として、「We're Hiring!」の文字とURLをアニメーション表示するようになっていました。


さて、このファンですが、よく見るとピンソケットが付いています。きっとマイコンか何かのプログラミング用だろうと思い、気になったので分解してみました。



なにやらピンソケットの近くにチップがあります。型番はT24C04A。検索してみると512 x 8bitのEEPROMでした。きっとこれにデータが入ってるのだろうと想像がつきます。


裏面見たらご親切にもシルクが入ってました。左からPAD, GND, CLK, VDD, DATAの5本。CLK, DATAはI²Cの信号ですから、ここからデータ書き換えできそうですね。



まずはArduinoを接続してデータを読み出してみます。
データシートを参考に、データを読み出すプログラムを書きます。I²C通信はArduinoならWireライブラリを使えば簡単。また、そのまんまEEROMを読み書きするサンプルスケッチがIDEに付属していますから、参考になるでしょう。
I²Cのアドレスは0x50。256byteから先を読むときはPADで1に切り替え、I2Cアドレスを0x51にするようです。*1


とりあえず256byte分を読み出した結果は

0x2, 0xD, 0x7F, 0x7F, 0x2, 0x7F, 0x7F, 0x41, 0x5A, 0x5A, 0x5A, 0x67, 0x70, 0x6F, 0x6F, 0x77, 
0x60, 0x7F, 0x7E, 0x20, 0x6E, 0x7F, 0x77, 0x6F, 0x6F, 0x77, 0x60, 0x7F, 0x7E, 0x20, 0x6E, 0x7F, 
0x70, 0x6F, 0x6F, 0x77, 0x0, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x73, 0x6A, 0x6A, 0x6A, 0x71, 0x77, 
0x6F, 0x6F, 0x77, 0x60, 0x7F, 0xF, 0x17, 0x7F, 0x7F, 0x73, 0x6A, 0x6A, 0x6A, 0x71, 0x1, 0x7E, 
0x71, 0x7E, 0x1, 0xB, 0x7D, 0x6A, 0x6A, 0x6A, 0x77, 0x71, 0x6E, 0x6E, 0x77, 0x0, 0x71, 0x6E, 
0x6E, 0x6E, 0x71, 0x7F, 0x21, 0x6E, 0x7E, 0x7D, 0x5F, 0x6F, 0x77, 0x7B, 0x7D, 0x41, 0x5A, 0x5A, 
0x5A, 0x67, 0x77, 0x6F, 0x6F, 0x77, 0x60, 0x71, 0x6E, 0x6E, 0x6E, 0x71, 0x7F, 0x7F, 0x7C, 0x7C, 
0x7F, 0x7F, 0x7E, 0x0, 0x5E, 0x7F, 0x7F, 0x41, 0x3E, 0x3E, 0x41, 0x7F, 0x3E, 0x0, 0x3E, 0x7F, 
0x7E, 0x7E, 0x7E, 0x7E, 0x0, 0xA, 0x7E, 0x7E, 0x7E, 0x7E, 0x0, 0x41, 0x3E, 0x3E, 0x3E, 0x41, 
0x41, 0x3E, 0x3E, 0x3E, 0x41, 0x4F, 0x37, 0x37, 0x37, 0x0, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x39, 
0x36, 0x36, 0x36, 0x4E, 0x0, 0x5F, 0x67, 0x5F, 0x0, 0x7E, 0x7E, 0x7E, 0x7E, 0x0, 0x40, 0x37, 
0x37, 0x37, 0x40, 0x4F, 0x37, 0x37, 0x37, 0x0, 0x9, 0x39, 0x36, 0x36, 0x36, 0x4E, 0x40, 0x37, 
0x37, 0x37, 0x40, 0x50, 0x35, 0x36, 0x3E, 0x41, 0x3E, 0x36, 0x36, 0x36, 0x0, 0x7, 0x79, 0x7E, 
0x79, 0x7, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x39, 0x36, 0x36, 0x36, 0x4E, 0x40, 0x37, 0x37, 0x37, 
0x40, 0x7E, 0x7E, 0x7E, 0x7E, 0x0, 0xE, 0x49, 0x36, 0x36, 0x36, 0x5D, 0x7F, 0x7E, 0x0, 0x5E, 
0x7F, 0x7F, 0x41, 0x3E, 0x3E, 0x41, 0x4E, 0x36, 0x3A, 0x3C, 0x5E, 0x7F, 0x71, 0x72, 0x7F, 0x7F, 

となっていました。データを眺めてみると、8bit目が全部0で、7つのLEDのそれぞれが0〜6bit目に対応していそうだなあと気づきます。


適当に可視化してみたのがこちら
最初の1byteは、恐らく2画面を切り替えて表示という意味。その後は1byteで文字数が来て、1文字あたり5byteでビットパターンが続いています。いろいろ試してみた結果、0-6bit目がそれぞれのLEDに対応、0だったらLED点灯、1だったらLED消灯と判明しました。なんか後ろの方に使われてないデータが残ってますが、デフォルトのデータかテストパターンか何かかな、きっと。


さて、仕様が分かったら、今度は適当にデータを書き換えてみます。
"HAPPY HACKING!"、"by NeoCat"の二つのパターンを作成し、上記のフォーマットでバイナリにしたデータがこちら。これをArudinoのプログラムに埋め込んで、EEPROMに書き込みます。


そしてファンを回してみると…*2


結論:リバースエンジニアリング楽しい。*3

*1:最初アドレスを勘違いしていて、なんで全く反応がないんだ〜!?とハマっていました。

*2:振動でファンがだんだんずれていってるけどご愛嬌。

*3:というほど大げさなものでもないですが。

ArduinoとKinectでラジコンヘリを飛ばしてみた

KinectとProcessing、Arduinoを使って、ラジコンヘリを飛ばすしかけを作ってみました。


動画:

赤外線ラジコンヘリ

飛ばすのはFS-IRH100 (F103)という室内用のラジコンヘリ
赤外線方式のコントローラが付いてきます。


2000円台という安さながら、慣れるとかなり安定して飛ばすことができ、大人から子供まで十分楽しめます。ちょっとぶつかったくらいなら壊れることもなく、交換用のブレードも付いてくるので安心です。

4ch赤外線コントロール ラジコンヘリコプター FS-IRH100 (メタリックブルー)

4ch赤外線コントロール ラジコンヘリコプター FS-IRH100 (メタリックブルー)

バッテリー交換可能になった改良型も出ており、スペアバッテリー付きでも売られていました。飛行時間は5分弱といったところで、頻繁に充電することになるので、こちらの方が良いかもしれません。( 同型を2台買うと言う手もあります。:P )

続きを読む

USBミサイルランチャーをArduinoでコントロール

久しぶりにUSBホストシールドで遊んでみました。

USBで制御できるミサイルランチャー(カメラ付き)を手に入れたので、これをArduinoから動かしてみます。

必要なもの

ライブラリのインストー

IDEは、最新版のArduino 1.0を使います。


準備として、ホストシールドのライブラリをダウンロードしてインストールする必要があります。
下記GitHubではUSBホストシールドライブラリ2.0が公開されています。2.0では、Arduino IDE 1.0対応、USBハブ対応などが行われています。

GitHub - felis/USB_Host_Shield_2.0: Revision 2.0 of USB Host Library for Arduino.

USBホストシールド2.0との差分の対策

このライブラリはUSB Host Shield 2.0という新しいバージョンのシールド用になっています。
いま現在国内で入手しやすいと思われる、スイッチサイエンスなどで販売されているSparkFunバージョンと比べると、USBホストのリセットの仕方が変わっています*1。そのため、SparkFunバージョンでこのライブラリを動作させる際には、少し細工が必要です。


具体的には、ArduinoのRESETピンと、デジタル7ピン(古いシールド*2の場合は8ピン)とを、ジャンパワイヤなどで接続しておきます。これで、Arduinoのリセット時にUSBホストもリセットされるようになります。*3

上記は(古いシールドなので)8ピンをRESETに接続したところ。


他の注意点として、USB電源だけではUSB機器への供給電圧が不足するため、9〜12V程度のACアダプタをArduinoに接続しておかないと、動作が不安定になって機器が認識されなかったりするので注意が必要です。

ミサイルランチャーのプロトコルを解析

USBを使ってミサイルランチャーをコントロールするためには、どんなプロトコルで制御されているのかを知る必要があります。といってもデータシートがあるわけではないので、USBパケットをキャプチャして解析する必要があります。

とりあえず、ベンダーIDをプロダクトIDを調べます。下記はMacにつないで"システム情報"でUSBを見たところ。このミサイルランチャーの場合、USBハブが内蔵されており、そこにカメラとミサイル制御デバイスが接続されている、という構成になっていました。ミサイルの方のベンダーIDは0x2123, プロダクトIDは0x1010です。


USBキャプチャはWindowsマシンで行いました。まずはフリーのUSBスニファー「Snoopy Pro」を導入しておきます。また、メーカーページからダウンロードしたWindows版制御ソフトをインストールし、動かせるようにしておきます。


Snoopy Proを起動するとUSBデバイス一覧が表示されるので、先ほど調べたベンダーID&プロダクトIDを持つデバイスを探し、右クリックしてInstall and Restartを選ぶと、USBLogウィンドウが開き、キャプチャが始まります。


この状態で、制御ソフトのボタンを上下左右や発射ボタンをクリックして、制御パケットをキャプチャします。このとき長くボタンを押すと大量のパケットがキャプチャされてしまって解析の手間が増えるので、短く一瞬だけクリックするのがポイント。


実際に上下左右、発射ボタンを押した時のキャプチャ結果はこんな感じでした。(右に出てるのは制御ソフト。動作音や発射警報音が鳴ったりと結構凝ってますw)


out down と表示されているのが、PCからUSBへの出力パケットです。その下のout upはUSBからの応答です。FunctionにCLASS_INTERFACEと表示されていますが、これはミサイルランチャーがHID(Human Interface Device)という規格に準拠しているためです。HIDでは、GetReport / SetReport というリクエストでデバイスとの入力 / 出力を行います。上のキャプチャはいずれも、SetReportをしていることを表しています。その右のData部分が、実際に送受信されている内容です。


Data部分を見ていくと、動き始める時に 「02 ** 00 00 00 00 00 00」(**は下なら01、上なら02、左なら04、右なら08、発射なら10)、止まる時に「02 20 00 00 00 00 00 00」というデータが送られていることが分かりました。Arduinoからでも、たぶんこれと同じものを送ってやりさえすれば動くのではないかと想像できます。簡単ですね。実際にはこの他にも動作状況を取得するためのパケット(GetReport)が流れているのですが、とりあえずは無視しておきます。


次に、左ボタンを押下した時のデータを詳細表示してみます。

SetReportリクエストを送るためには、SetupPacketのうちの4つめと3つめ、report_type / report_id という番号も必要になります。今回はそれぞれ、report_type=2, report_id=0でした。

Arduinoからミサイルランチャーを動かしてみる


さて、だいたいプロトコルの見当がついたら、Arduinoで実際に動かしてみます。一般のデバイスに対応するにはライブラリのcdc*.h, cdc*.cppを複製してインターフェースを実装することになるのですが、今回はHIDに準拠しているので、ライブラリ標準で用意されているHIDUniversalというクラスで取り扱えるため、かなり簡単になります。


実際のスケッチはこんな感じ。

#include <Usb.h>
#include <usbhub.h>
#include <hid.h>
#include <hiduniversal.h>

USB             Usb;                // USBホストシールド制御用
USBHub          Hub(&Usb);    // 使用するハブの数だけ定義しておく
USBHub          Hub2(&Usb);
HIDUniversal    Hid(&Usb);    // HIDデバイス

void setup()
{
  Serial.begin(115200);
  Serial.println("Start");

  // USB初期化
  if (Usb.Init() == -1)
    Serial.println("OSC did not start.");
      
  delay(200);
}

void loop()
{
  Usb.Task();  // 定期的に呼び出す必要あり
  
  // シリアルから文字を受信
  if (Serial.available()) {
    byte c = Serial.read();
    if      (c == 'd') c = 0x01; // DOWN
    else if (c == 'u') c = 0x02; // UP
    else if (c == 'l') c = 0x04; // LEFT
    else if (c == 'r') c = 0x08; // RIGHT
    else if (c == 'm') c = 0x10; // LAUNCH MISSILE!
    else if (c == 's') c = 0x20; // STOP
    else return;
    
    byte cmd[8] = {2, c, 0, 0, 0, 0, 0, 0};    // 送信するコマンド(Data)
    // 引数1,2には0を指定。以降、report_type=2, report_id=0 でcmdをSetReport送信
    Hid.SetReport(0, 0, 2, 0, sizeof(cmd), cmd);
  }
}

ミサイルランチャーに内蔵のUSBハブでHIDが接続されているため、USBHubクラスのインスタンスを少なくとも1つ定義しておく必要があります(1つ定義すると1段分のハブを認識できるようになる)。あとはHIDUniversalクラスのインスタンスを1つ定義します。そうしておいて、setup()でUsb.Init()を呼び、loop()でUsb.Task()を何回か呼んでいると、自動的にHIDデバイスを検索してHidインスタンスを通じて操作できるようにしてくれます。


このスケッチをArduinoに書き込んで、ミサイルランチャーとUSBホストシールドを接続し、シリアルから l/r/d/u/s/m のいずれかの文字を送ると、それぞれ左回転/右回転/下/上/停止/ミサイル発射 の動作をしてくれました。素直なデバイスです。^^;

上下左右は限界に達するか停止コマンドを送るまで回り続けます。いっぽうミサイル発射時は、1発発射したあたりで勝手に止まってくれるので、停止信号などは送らなくても大丈夫でした。


なお、上記スケッチをビルドすると30KB近くになって、ほぼArduinoのフラッシュを使い切ってしまいますが、この容量の約半分はHIDUniversalクラスが表示するデバイス情報メッセージのせいです。ライブラリのhiduniversal.cppの232行目あたりにある部分を下記のように無効化すると、あっという間に15KBほどサイズが小さくなります。

	USBTRACE("HU configured\r\n");
#if 0
	{
		HexDumper<USBReadParser, uint16_t, uint16_t>    Hex;
		ReportDescParser                                Rpt;

		if (rcode = GetReportDescr(0, &Hex))
			goto FailGetReportDescr;
	        
		if (rcode = GetReportDescr(0, &Rpt))
			goto FailGetReportDescr;
	}
#endif


ドア開閉をセンサで検知して発射するようにしたら、侵入者を撃退(?)するデバイスができるかも。(いやそれだと主にミサイル食らうのは自分か…。)

あと内蔵のカメラが使えたりするとさらに面白いんですが、さすがに処理能力的に厳しいかな。。

追記

ルンバに載せて移動砲台にしてみました。
http://d.hatena.ne.jp/NeoCat/20120220/1329699693 →最後の動画

*1:従来はデジタル7ピンまたは8ピンがUSBホストコントローラのRESETに接続されていましたが、USBホストシールド2.0では、USBホストコントローラのRESETに、ArduinoのRESET信号がそのまま入力されるようになっています。

*2:従来ライブラリのRESETの定義に修正を加えて使っていたもの

*3:もちろん、setup()でこのピンにリセットパルスを送出するという方法もとれます。

「Arduinoスーパーナビゲーション」でTwitterライブラリを紹介頂きました

書籍「Arduinoスーパーナビゲーション しくみと応用テクニック」で拙作のTwitterライブラリを紹介していただきました。

Arduinoスーパーナビゲーション しくみと応用テクニック

Arduinoスーパーナビゲーション しくみと応用テクニック

Arduinoは電気回路やプログラミングの細かい事柄に気を回さなくても、気軽に電子工作を楽しめることから、最近いろいろな作品に使われているマイコン+開発環境です。

初めてマイコンを使った作品にトライするときには、仕様の読み方が分からなかったり、ちょっとした設定のミスでつまずいたりしがちです。この本では、Arduinoで作品作りを始めるための最初の一歩(必要なモノから環境の作り方など)から始めて、いろいろな基本動作(LEDを光らせたり、センサで計測したり、喋らせたり通信したり)をさせるための方法を丁寧に解説していて、スムーズにArduinoの使い方を覚えられるように道しるべになってくれます。


この基本動作の一つ「通信する」の中で、拙作のライブラリでTwitterにつぶやく方法を説明していただいています。
また、その応用として、自宅の侵入者を検知してTwitterにつぶやく「自宅警備員」という作品の作り方を紹介。
他にもAndroidとの接続などを含めた8つの作品の作り方が紹介されていて、眺めているだけでいろいろ試してみたくなってきます。


Twitterライブラリもセンサの値などのアウトプット先として手軽に応用できますので、ぜひいろいろなアイデアにトライしてみてください。

Arduino 1.0対応Twitterライブラリを公開

Arduino 1.0が2011/11/30に正式リリースされました。
新しいArduinoに対応したり、ライブラリの強化などが図られています。(詳しい変更点はRelease Noteを。)
個人的にはEthernetライブラリが強化され、DNSDHCP機能を標準でサポートした点が嬉しいところ*1


さて、これに伴ってTwitterライブラリもアップデートしました。
使い方は今までと同様で、簡単にArduinoからTwitterにツイートを送信できます。
今まではEthernetDNSが別途必要でしたが、標準でDNS対応したことで導入の手間が不要となりました。
なお0022以前のIDEでも新しいバージョンのライブラリを利用することも可能となっています。その場合は従来通りEthernetDNSライブラリが必要です。


ダウンロードや使い方の説明は、こちら(英語)から。ライブラリに付属しているExampleも参考にしてください。

*1:EthernetDNSやEthernetDHCPと比べると若干バイナリサイズが大きく消費するROMが増加するのが玉にきず?

Arduino用のLSM303DLH(デジタルコンパス+加速度センサ)ライブラリ

1つのチップに3軸の地磁気センサ(デジタルコンパス)と3軸の加速度センサを内蔵した、LSM303DLHというチップを搭載したSparkfunのボードがスイッチサイエンスなどから販売されています。お値段も円高効果か3000円を切っていてお買い得。

LSM303DLH搭載傾き補償付きデジタルコンパス・加速度センサモジュール--販売終了 - スイッチサイエンス

ちなみに地磁気センサ単体だと、水平から傾けた場合に正しく方位がとれません。これは地磁気のベクトルは水平ではなく傾いているため(この傾きを伏角と言います。関東だと49°らしい。結構斜めですよね)。傾きの成分を拾ってしまい、誤差が出ます。そこで加速度センサで重力の方向を検知して、傾きを補償することで、正確な方角を計算する必要があります。


例によって、このセンサをArduinoで使うためのライブラリを作ってみました。

http://neocat.jp/arduino/Library-LSM303DLH.zip


展開してできたLSM303DLHフォルダを、Macならホーム/Documents/Arduino/libraries/ 、WindowsならMy Documents\Arduino\libraries\ に入れ、ArduinoIDEを再起動すれば準備完了です。

File→Examples→LSM303DLH→LSM303DLH_sample を開くと、サンプルスケッチを見られます。


このコードをArudinoにアップロードし、ソース中にある通りにLSM303DLHとArduinoを配線してSerial monitorを見ると、加速度センサX/Y/Z、地磁気センサX/Y/Zの値(計6軸)の数値が転送されてくるのが見られます。



また、センサの出力からボードの姿勢を計算して3DでビジュアライズするProcessingのコードも、LSM303DLH/samples/LSM303DLH_sample/Processing_SampleProject/RotateXYZ/RotateXYZ.pde に入っています。


プロジェクトのファイルをProcessingで開いて、シリアルポートの名前を自分のArduinoのボードに合わせて修正してから実行すると、冒頭のようなボードの絵が表示されます。そして、実物を回転させると同じように3Dで回転するはずです。
※フォント周りでエラーがでる場合は、Monaco-24 をTools → Create Fontメニューから生成してあげてください。


表示されている数値は、6軸の値、およびX軸の方角(裏面にSparkfunと書かれている方向が北だと0°、時計回りに-180°〜179°で表示)です。ちゃんと補償された方角になっているはず。(計算間違ってたらすんません><)



なお、感度などの設定は全てデフォルト値になっています。変更したい場合は、データシートに従ってレジスタの値を

LSM303DLH.write_reg(アドレス, 値);

として書き換えてください。アドレスが00h〜12hは磁気センサ、20h〜は加速度センサのレジスタを書き換えることができます。

更新速度は begin() に渡す定数を変えることで変更できます。デフォルトでは、加速度センサはlow-powerモードの10Hz (ローパスフィルタは37Hz)、地磁気センサは15Hzで更新される設定になっています。詳しくはライブラリのヘッダファイルを見てください。