Arduino Mega ADKでAndroid端末に向けて、float型のデータを送信。
Android端末で、float型のデータを受信。
結果はlogcatで見ただけ。
Android端末はXoom(android 3.2)です。
■困ったこと
Arduino側とAndroid端末側でエンディアンが違う。
Arduinoはリトルエンディアン、Android端末はビッグエンディアン。
Android端末側で受信したbyte配列をそのままfloatに変換すると、変な値になる。
■解決策
ByteBufferクラスを使って、エンディアンを変換する。
以下にコードを示しますが、実際にエンディアンの変更を行なっているのはAndroid端末側ソースの"byteBuffer.order(ByteOrder.LITTLE_ENDIAN);"の部分になります。
以下、コードになります(部分的に抜き出し:手を抜いてスイマセン…)。
Arduino側スケッチ
Android端末側ソース
■結果
無事、値を読めました。
■ムダ話
最初はacc.write()がbyte配列しか送れないと勘違いしていて、Arduino側でfloatをbyte配列にしてから送信しようとしていた。
たしかこんな感じ。
float f = 0.0; byte msg[4]; msg[0] = f >> 24; msg[1] = (f >> 16) & 0xff; msg[2] = (f >> 8) & 0xff ; msg[3] = f & 0xff; acc.write(msg,4);
でも、これだとコンパイルが通らない。。。
floatとかはシフト演算子が使えない(共用体でやる方法が有るらしい:未検証)。
AndroidAccessory.hみたら、write(void *buff, int len);って宣言されてたから、floatでもそのまま送れるじゃん!
適当に通信したら、エンディアンの問題でおかしな値に…
以前にもC言語で書かれたソフトに対して、Javaで書いたソフトを使って通信をした時にも、エンディアンの違いに悩まされた事を思い出した!
ByteBuffer便利やー
ByteBufferクラスは結構癖があって、すぐに例外吐いたりしますが、getInt()とかgetFloat()とかプリミティブな型の値を順番に読み込めるので大変便利です。特にバイナリの塊を順番に解析していくときなんかは良いと思います。
0 件のコメント:
コメントを投稿