LEGO Marioをセンサとして利用したい(5) - 利用可能なポートの調査
今回は、Portの中の各モードについて調査を進めていきましょう。
この記事の内容は未完です。BLE予備知識ゼロ、もちろんLEGO Wireless Protocolの知識もゼロ、電子工作は趣味レベルの自分が、レゴマリオでセンサの値を読み取るまでの現在進行系のログです。
前回のおさらい
前回の記事では、入出力に利用されるPortがレゴマリオには5つあることを明らかにしました。さらにPortの中にModeという概念があり、実際に具体的な値として利用するにはModeを指定する必要があることを知りました。
調査にあたって
調査にあたって、いままではBluetooth Explorerを利用していましたが、前回の実は飛んでいたデータなどを考慮し、BlueJellyを利用したデバッガを作成しましたので自由に活用ください。(iOSを除くChromeで動作)
Port Information Requestを投げる
それでは早速、Portの詳細について調べていきましょう。Port Information Requestのメッセージタイプは0x21で、Common Message Header(CMH)以降は8bitずつ、Port ID, Information Typeの計5byteからなります。今回、Modeに関する情報を知りたいので、Information Typeは0x01になります。
よって、Port 1のMode情報の要求をするために、Writeすべきデータは以下のとおりです。
0500210101
早速、さきほどのデバッガ経由でWriteしてみます。すると、以下のようなメッセージが返ってきました。
0b 00 43 01 01 06 02 03 00 00 00
0x43はPort Informationを示すメッセージタイプで、それにPort ID, Information typeが続きます。今回はPort 1のMode情報のため、01 01となります。
つづく0x06以降、Mode情報の場合はCapabilities(1byte), Total Mode Count(1byte)、Input Modes(2byte)、Output Modes(2byte)が続きます。
0x06 <=> 0b0000110ですので、CapabilitiesはLogical Combinable, デバイスから見ると入力系であることがわかります。また、モードは2つあることが次の0x02からわかります。
続く0x03 00はリトルエンディアンなので0x0003と読み直すと、0b 0000 0000 0000 0011となり、Mode 0とMode 1が Input Portとして利用できることが判明しました。(Outputはナシ)
以下、前回しらべたPort0,1,2,3,6に対するリクエストとその結果です。
Write: 0500210001
0x0b 00 43 00 01 06 02 03 00 00 00
Write: 0500210101
0x0b 00 43 01 01 06 02 03 00 00 00
Write: 0500210201
0x0b 00 43 02 01 02 01 01 00 00 00
Write: 0500210301
0x0b 00 43 03 01 02 04 0f 00 00 00
Write: 0500210601
0x0b 00 43 06 01 02 02 03 00 00 00
以上で、11個の入力系があることがわかりました。(残念ながらOutputはない。マリオを喋らせたかった……)
前回までに作成した表に追記した形でまとめると、以下のとおりです。
続いて、更に各モードに関する情報を調べていきましょう。
Port Mode Information Requestを投げる
早速、Portの各モード情報を取得するためのリクエストを書き込んでいきましょう。書き込むべき値を整理します。 Port Mode Information RequestのMessage Typeは0x22です。以降、Port ID, Mode, Mode Information Typesを1byteごとで指定してあげます。最後のMode Information Typesはドキュメントの表のとおりです。
それぞれがどういう意味なのか、初心者の自分ではDescriptionを読むだけではまだ理解ができていないのですが、Descriptionにある言葉の意味が分かる日を信じて、まずは調査を進めます。
説明文を読む限り、Modeには生データ、パーセンテージ、SI値(mやVなどの単位値?)などの範囲が定義されているようです。勝手な想像ですが、このあたりはサーボモータの回転制御などで厳密に活躍する情報であって、今回のレゴマリオにとってはあまり重要ではないかもしれない……。
まずはModeの名前を取得します。ですので最後は0x00になります。結果、0022000000というバイト列に先頭の長さを加えた06が頭についた
060022000000
が書き込むべき値になります。早速、同様にデバッガに値を書き込んでみます。すると、以下の値が返ってきました。
11 00 44 00 00 00 52 41 57 00 00 00 00 00 00 00 00
早速デコードしていきましょう。まずは17byteの0x44 = Port Mode Informationのメッセージであることを読みます。※Port Mode InformationのUpstreamのメッセージは要求した情報ごとにByte数が決まっています。
CMH以降が、Port ID, Mode, Mode Information Typeであることは要求と同様です。それ以降についてはMode Information Typeに応じて使われ方が決まっています。今回のNAMEの場合は
とあるとおりで、11byteのASCIIコードであることがわかります。細かな注意も書いてありますが、早速デコードします。先頭3文字しか使われていませんが、0x52=R, 0x41=A, 0x57=Wですので、『RAW』という文字列が取り出せました。よって、Port 0のMode 0の名前はRAWであることがわかりました。きっと、生データっぽいものが入るのでしょう!!
名前以外もどんどん取得
RAW(名前と同じだからややこしい)、PCT、SI、SYMBOL、Mapping……と続くMode Informationをどんどん取得していきましょう。何度も言いますが、私自身、まだこの情報の意味を正確には理解していません。動かすうちにわかる日が来ると信じて、とりあえず調べあげます。
リクエストは先程投げたものの、末尾のMode Information Typeをそれぞれ変更するだけなので、
060022000001 = RAW
060022000002 = PCT
060022000003 = SI
060022000004 = SYMBOL
060022000005 = MAPPING
060022000080 = VALUE FORMAT
がPort 0のMode 0に関する情報を取得する各命令になります。以下、結果です。
Write: 060022000001
0x0e 00 44 00 00 01 00 00 00 00 00 00 c8 42
Write: 060022000002
0x0e 00 44 00 00 02 00 00 00 00 00 00 c8 42
Write: 060022000003
0x0e 00 44 00 00 03 00 00 00 00 00 00 c8 42
Write: 060022000004
0x0a 00 44 00 00 04 63 6e 74 00
Write: 060022000005
0x08 00 44 00 00 05 84 00
Write: 060022000080
0x0a 00 44 00 00 80 03 00 03 00
RAW, PCT, SIに関して、4byteの浮動小数点数が2つ、最小・最大の順で並んでいるという点でデコード方式が同じです。今回は全く同じ値が返ってきているのでデコードも簡単です。
0x00 00 00 00はそのまま0になりますのでいいとして、最大値の00 00 c8 42をデコードしましょう。ドキュメントにはFLOATING POINTであることしか書かれていませんが、一般的な単精度浮動小数点数であると仮定します。IEEE形式であることを信じると、符号部1bit、指数部8bit、仮数部23bitでしょうか。とりあえずデコードしてみましょう。まずはわかりやすさのため、バイナリに変換します。例にもれず、リトルエンディアンだと考えると
0100 0010 1100 1000 0000 0000
0, 1000 0101, 100 1000 0000 0000
IEEEの単精度浮動小数点数は(-1)^(符号部) * (1 + 仮数部) * 2^(引数部 - 127)なので、
+,133,0.5625 = (-1)^0 × (1+0.5625) × 2^(133-127) = 1.5625 * 64 = 100
となり、最小値が0、最大値が100であることがわかりました。
基本情報技術者などの試験でも頻出なので、浮動小数点数のデコードはぜひ出来るようになっておきましょう!仮数部は小数点以下の2進数なので左から1bitずつ0.5, 0.25, 0.125, 0.0625, 0.03125...と半分ずつ減る、すなわち、2のマイナスN乗になります。
続いて、0x04 = SYMBOLです。説明によれば、角度ならDEGのような標準的な単位が入るみたいです。ドキュメントを読むと、5文字のASCIIだということなのですが、今回、CMHの先頭を見ると10byteしかなく、最大4文字になりそうです。末尾の00は無視して、63 6e 74 をデコードします。0x61 = a ですから、指折り数えて…「cnt」を取り出せました。cnt...=countであることは間違いないでしょう。これでPort 0のMode 0はRAWのcntっぽい値が入るっぽいというなんともぽいぽいな予測が可能になりました。
MAPPINGもそのまま読んでみます。0x84 00の8bitずつでそれぞれINPUT, OUTPUTを表すそうなので、0b10000100 0000000としてあげて、INPUTのみ「Supports NULL valueとDIS (Discrete [0, 1, 2, 3])」だということです。
Discreteは離散的という意味なのですが、連続的でないので整数であることが担保されるくらいのイメージをもちつつ、とりあえず突き進んでいきます。(こちらもサーボの制御やもっとアナログなセンサの場合は非離散的な値になるのかもしれないです。レゴマリオについてはDIS以外登場しないので詳しくは不明…)
最後にVALUE FORMATを見ます。VALUE FORMATは10byteで必要なのは0x03 00 03 00の4byteかと思います。ドキュメントの表で1バイト目から何を表すか説明してくれています。
先頭の0x03からデータセットが3個であること、次の0x00でそれが8bitの整数(FLOATじゃないってことはそういうことよね…??)であること、その後の0x03がTotal figures、0x00がDecimals if anyということがわかります。後半2つはほとんど何を言ってるのかわかりません。なんの合計なんでしょう…。小数点があれば…ってあれば0x01とかにでもなるんでしょうか?それとも固定小数点の位置? よくわからないので、今はメモだけ残しておいて先に進んでいきます。
全ポートとモードの調査
すべてのポートについて、上記作業を繰り返し、以下の表を得ました。
NAMEから推測するに、Port 0からはジェスチャ系、Port 1からはまず間違いなくタグおよびカラーセンサ、Port 2からはパンツ=衣装、PORT 3からはデバッグやイベントの値などセンサというよりも状態?を取得できそうな気配がようやくしてきました……!(勿論Port 6はVoltage)
レゴマリオを横にすると寝るというギミックから、3軸とかのジャイロセンサーが入っているかと想像していたのですが、GESTというNAMEをみると、もしかするとジェスチャセンサー(光の跳ね返りの変化で動きを検知)が入っているのでしょうか…。このあたりは実際に試してみる他ありません。
次回予告
各Modeとレゴマリオの対応について、調べたいという欲求も出てきましたが、まずは当初の予定通り、カラーセンサを使ってHueをコントロールするという目標に向けて、恐らくPort 1 Mode 1を実際に読み取るという、核心に触れていきたいと思います…!
この記事が気に入ったらサポートをしてみませんか?