MotionProcessorの高速シリアルポートでの受信

自分は
 1.ゲームコントローラをスイッチとして利用し
 2.ATmega32よりコマンドを送信
 3.MotionProcessorの高速シリアルポートでパケット受信
 4.MotionProcessorのスクリプトで判定
という流れでロボを操縦しています。

ただ、初めて自分でプログラムを書き、マイコンを使用して
いるのでATmega32に書き込んでいるプログラムが正しいか、
効率が良いかは分かりません。。

ですが問題なく動いているので多分合ってるんでしょう。。

そこで偉そうにもちょっと解説を書いてみましたのでご興味
のある方は読んでみてください。

例えばMotionProcessorを使えば9個のアナログスイッチを使
用して9軸完全マスタースレーブ何ていうことも可能ですし、
72個のスイッチを使用した72鍵盤コントローラー何ていうの
も簡単に実現出来ちゃいます。
*******************************************************

今回取り上げるのはMotionProcessorの「高速シリアルポート
でのパケット受信」です。

「高速シリアルポートでの1バイトコマンド受信」ではありま
せんのでご注意ください。

では早速いってみましょう!

説明書の37ページを見ると、リアルタイムに固定変数に値を
格納させることが出来るフォーマットが書いてあります。

  #001122334455667788

  ※注意!!
   説明書には
   #00112233445566778899
   と書いてありますが間違いです。
   9個の固定変数にしか値を渡せないので上記ですと10個
   になってしまう為「00」もしくは「99」の2桁多いです。

なんだかよく分かりません。。
ですがココでめげてはダメです。
読み進めましょう。

  上記「00」等が1バイト分で、1桁30Hから3FHのキャラク
  タコードを2バイト組み合わせて送信します。
  ※都合00からFFまで

???
実を言うとバイトとかコードとか全く知らなかったのでこの
文章は難解でした。今もあまり理解できていないかも・・・。

これを噛み砕くと

「00」の10の位の「0」と、1の位の「0」それぞれに、16進数
で「30」から「3H」迄のキャラクタコードをセットしろ。
※扱える値の範囲は16進数で「0~FF」、10進数で「0~255」
 まで!でも値がたとえ1桁でもきちんと2桁でセットしてね!

ってことになります。
ココで疑問が。
キャラクタコードって何?
これはASCⅡ表に答えがありました。


ASC2hyou.jpg


上記赤文字の部分が「30」から「3H」迄のキャラクタコードに
なります。
ですので値を表現する時に読み替えてあげないといけません。
変換は以下の通り。

0123456789ABCDEF
    ↓
0123456789:;<=>?

ここまでくるとすこーし何をしないといけないかおぼろげに見
えてきます。

例1.
「00」に10進数で「1」、16進数でも「1」を表現するには「01」
と表現する。

例2.
「00」に10進数で「16」、16進数で「F」を表現するには「0?」
と表現する。

例3.
「00」に10進数で「31」、16進数で「1F」を表現するには「1?」
と表現する。

ふむふむ。
なるほど。
でもどーやって16進数で「F」を「?」に変換するんでしょう?

えっ!?

それは・・・。

ぴゅー。

実はこれが一番厄介だったんです・・・。
さぁうまく説明できるかどうかわかりませんがいってみましょう。

16進数で「F」を、キャラクタコードで「?」、すなわち
16進数で「3F」に変換する。

ここで「おっ!」と思った方は凄い!

ではここでもう1個の例を
16進数で「C」を、キャラクタコードで「<」、すなわち
16進数で「3C」に変換する。

さぁ分かったでしょうか!
自分はこれを聞いた時(あ、すいません自分は教えてもらいまし
た。)体が震えました。

そう。

そうです。

元の数に16進数で「30」を足してあげるだけでキャラクタコード
になっちゃうんです!

マイコンに記述する時は、16進数を表す時「0x」を先頭につけれ
ば良いので

0x0F + 0x30

0x0C + 0x30

で良いんですよ!ラッキー。

さぁゴールは見えてきました!
残る問題は後1つ!
それは何か!?

例えば10進数で「207」、16進数で「CF」等の2桁の値を1桁づつど
ーやってキャラクタコードに変換するか。

16で割ったら小数点以下切捨てで「C」になって、
その値を16倍したら「C0」になるから「CF」から引いたら「F」に
なるじゃん!

という手もありますが(実際に自分はそうやっていましたが。。)
もっとカッコ良い方法があります。

それは、左側の桁を取り出すビットシフトと、右側の桁を取り出す
ビットマスクというヤツです。
2進数で考えるとムチャクチャシンプルです。
※2進数の「0」や「1」といった1桁がビットといわれる単位

例えば10進数で「207」、16進数で「CF」を2進数で表すと

11001111

となります。
左側4桁「1100」が「C」で、右側4桁「1111」が「F」です。
軽く書きましたがこれって凄くないですか?

16進数で「CF」の「C」だけを取り出したいとき、2進数の右側4桁を
取っちゃえば良いんですよ!

また反対に「F」だけ取り出したいときは、2進数の左側4桁を取っち
ゃえば良いんです!

ではまず左側の桁「C」の取り出し方。

(0xCF >> 4)

です。
これはビットを4個右にずらしましたということで

11001111

を右に1個ずらすと

01100111

となり、もう1個右にずらすと(2個ずらし)

00110011

となり、もう1個右にずらすと(3個ずらし)

00011001

となり、もう1個右にずらすと(4個ずらし)

00001100

となり「0x0C」の完成です。
ブラボー。


では続きまして右側の桁「F」の取り出し方。

(0xCF & 0x0F)

です。
これは「0xCF」と「0x0F」の両方1の所だけ1にしますという
ことで

11001111
00001111
 ↓
00001111

となり「0x0F」の完成です。
ブブブブブラボー!

以上のことをふまえ、10進数で「207」、16進数で「CF」の
桁それぞれをキャラクタコードに変換するには

(0xCF >> 4) + 0x30
(0xCF & 0x0F) + 0x30

となります。
ATmega32に記述する場合、送信の部分だけを書くと

rs_printf (
"#%c%c1122334455667788\r\n",
(0xCF >> 4) + 0x30, (0xCF & 0x0F) + 0x30
);

となり、MotionProcessorに送った場合、V14には「207」と
いう値が格納されているはずです。

それでは自分が使用しているATmega32のソースをリンクして
おきます。(すいませんまだ出来ていません。。)

ポートAの0~3にアナログスティック
ポートB、Cにスイッチを使用しています。

あくまでも参考ということで宜しくお願いしまっす。

あ、ちなみにMotionProcessor側は以下の様なスクリプトで
判定させています。


JUMPIF(V22,=,254,LU)
JUMPIF(V22,=,253,LR)
JUMPIF(V22,=,251,LD)
JUMPIF(V22,=,247,LL)
JUMPIF(V22,=,239,R1)
JUMPIF(V22,=,223,R2)
JUMPIF(V22,=,191,L1)
JUMPIF(V22,=,127,L2)

コメント

旭さん、おはようございます。

お忙しいのに、わざわざ解説してくださって
どうもありがとうございました。
参考にさせていただきます。

モーションプロセッサのパケット通信は、
本当に分かりにくいので、こうして情報を上げていただけると、助かります。
どうもありがとうございました。

それでは~!
非公開コメント