以下の文書はドラフト以前の殴り書きです。まじめに読まないようにしてください。
stioroid
stioroidはstm32を使って普通のAndoroid携帯にI/Oを付け足すための仕様です
実装はこれから
Bluetooth 2.x+EDRを使用
使用可能性が高い2製品
Bluetooth無線モジュール BlueMaster
http://www.robotsfx.com/robot/BlueMaster.html
460800bps
Parani-ESD100V2
http://intersolutionmarketing.jp/products/parani_esd.html
シリアル通信速度:1200bps ~ 921.6Kbps
とあるのでUARTの接続速度はこの速度にする
事実上のデフォルトUSB-UARTコンバータであるFT232も設定によっては460kで通信できるようなのでPCからのデバッグの際もこの速度にする
Bluetoothによって無線通信できる実効速度とUARTレベルの通信速度は別に考える
仕様上の最大速度
対称型通信時
1306.9kbps
実効速度は2分の1程度のようだが保守的に考えて3分の1とする
435kbps
いや
http://japan.zdnet.com/release/10179684/
こういう記事もあることなので
spp
では
300kbpsぐらいになると想定する
UARTを使うので1バイトあたりの送信ビット数は10ビット
300kbitpersecond
は
30kbytepersecond
となる
そうすると
パケットあたりのメッセージ長が30バイトまでなら1秒間のパケット送信数を
1000Hz
とできる
メッセージ長が300バイトまでなら
100Hzとなる
誤り検出についてどの程度の実装が必要かはBluetooth仕様によって変わってくる
ここのBluetooth仕様がちょっとわかりにくいので整理する
今回利用するBluetoothのプロファイルはSPP(Serial Port Profile)である。
SPP自身は誤り訂正機能を有していない。SPPが持っているフローコントロールは、下位のRFCOMMプロトコルのものである。
SPPではRFCOMMプロトコルを使用してデータの送受信を行う。RFCOMMが有しているフローコントロールはこのプロトコルの利用者に提供されるRTS/CTSによるフローコントロールである。
RFCOMMプロトコルはL2CAP(Locila Link Control and Adaptation Protocol)を利用してデータを転送する。
L2CAPのデフォルトモードであるBasic L2CAP modeはフローコントロール機能を有していないが、Flow control modeはフローコントロール機能を有している。RFCOMMプロトコルがどちらのモードを利用しているのかは仕様書を見る限りでは分からなかった。Google先生に聞いても不明。ただし仕様書には”L2CAP relies on the flow control mechanism provided by the Link Manager
layer in the baseband.”とあるので、L2CAP自身にフローコントロール機能がないことを前提している、つまり使っていないと読める。そこでここではRFCOMMはL2CAPのBasic L2CAP modeを使用していると仮定する。
L2CAPはベースバンド層において確立されるACLリンクを使用して接続する。ACLリンクはCRCによる誤り訂正・再送機能を有している。ベースバンド層において利用されるもう一つのリンク形式であるSCOリンクは誤り訂正機能を有していない。
ACLリンクにおいて使用されるACLパケットは可変長であるが、その中に2バイト固定のCRC用のフィールドを持っている。
誤り訂正は、
2/3 rate FEC
ARQ SCHEME(automatic repeat request scheme)
によって行われる。
要は16ビットの符号による誤り検出だと考えてよく、CRCなので16ビット以下の誤り検出も行えると考えてよい。
そうなると通信経路において何らかの誤りが発生し、それを検出できない可能性は65536分の1である。
これはあくまでBluetoothモジュール間のものであるので、STM32マイコンやAndroid側のチップセットとのエラー発生は別に考えないといけない。ただし極近距離(100mm以下)の460kbps程度の通信であるので、ここでの誤りは発生しないと仮定する。
以上の情報から誤り訂正の実装の必要性を検討するには、誤りの発生頻度がどの程度なのかという情報が必要。
「70dBm信号入力レベルで信号の誤り率が0.1%以下」
http://www.kozupon.com/bluetooth/bluetooth3.html
とのことである。
しかし、実際の誤りの発生量は不明。ビット単位で0.1%の確率で誤りが発生するとすると、1000ビットで誤りが発生するので、65536000ビット→約8Mバイトのデータ送信時点で訂正できなかった誤りデータを受信することになる。
8Mバイトで誤り発生というのは微妙だが、無視できる発生率ではない。
緩やかな誤り検出があるのが望ましいのではないか。
遅延の発生
Bluetooth仕様ではどこまでデータの転送遅延が許されるかについては規定が無い
ちょうど今回使用しようとしているモジュールの開発元であるSENAから遅延に関するレポートが出ていた。
http://www.sena.com/download/tutorial/whitepaper_latency_throughput_v1.0.1_for_bt.pdf
この資料によると
メッセージフォーマットはスケーラブルな仕様にしたいので可変長としたい
一定の制御周期を定めるかどうかは仕様を利用する側のアプリケーションに任せる
スタート地点を認識させるビットパターンは必要か
シリアル通信ではメッセージの始点を認識させるための特定のビットパターンを送信することがある
しかし、
・余分なデータが増えて送信量が増える(パケット中データに使える部分が減る)
・実際のデータと区別がしにくい
・判定処理が入る
・BluetoothやUARTは信頼性が高いので余分なデータが入っていると想定する必要性は低い
ので、いきなり実データが始まる仕様としたい
しかし、
・いったんデータを取りこぼすと延々と復帰ができない
パケットフォーマット
ヘッダ 2バイト
abcdef
メッセージ長 1バイト(0-255) 0バイトにする意味はないが
メッセージ 0-255バイト
サム 1バイト メッセージ本体部分をXORをとった値とする
メッセージ長のフィールドは必要か
これがない場合には時間的な間隙の有無でメッセージの終了を判断する
UARTで十分な受信バッファがある・受信側に十分な処理能力があるのであればこの実装も可能
しかしBluetoothの場合は無線である以上突然どこかで通信が中断するリスクを否定できない
なのでメッセージ長のフィールドは必要とする
データ再送信のサポート
あり得るパターンは
1
送信データ チェックサム無し + ACK無し
受信データに全幅の信頼を置く
受信側はデータの正当性を確認する手段が無い
バイト数が合わないときだけ再送信を別途要求するか
しかし途中で遅延する可能性があるのでバイト数が合わないことの確認は難しい
2
送信データ チェックサム無し + ACK有り
受信されたことだけ確認する
受信側はデータの正当性を確認する手段が無い
バイト数が合わないときだけNAKを返すか
しかし途中で遅延する可能性があるのでバイト数が合わないことの確認は難しい
ACKが無ければ再送する
3
送信データ チェックサム有り + ACK無し
受信した側でチェックサムが一致しなければ無視するか別途再送要求
4
送信データ チェックサム有り + ACK有り
受信した側でチェックサムが一致しなければNAKを返す
ACKを実装すると信頼性は上がる
しかし
Bluetoothベースバンド層でフロー制御がなされているのでACKをさらに実装するのは冗長
ACKを実装するとACKが返されるまでは次の送信を待つということになるが、処理負荷増加、遅延発生の原因になる
Bluetoothの特性上ある程度はデータの正当性を信頼していい
信頼するか信頼しないかは上位のアプリケーションに任せる
パターン1
と
パターン3
を実装
パターン3の再送要求
を実装する場合
送信側が過去に送信済みのデータを保持していないといけない
送信データバッファとして1データあたり
仕様上サポートはする
ヘッダーが
edac
だと、ACKを要求する need ack
ecac
だとACKは不要 reject ack
受信側は
aced
とさっき受信したメッセージのチェックサム値を返す
チェックサムが合わないときに
・再送要求
・単に無視
メッセージの送信途中で中断が生じた場合の取扱
iodroidってなんですか?
AndroidにIOをつけるための環境です。
どうしてAndroidにIOをつけたいの?
ネットとリアルをつなげたいからです。Gainerと発想が似てます。
じゃあGainerでいいじゃないですか。
ポータブルじゃないでしょ。
IOがついている開発ボードを使ったらいいじゃないですか。
そりゃそうなんですが、普通の人は持ってないでしょ。それにその類のボードはモバイルでネットにつなぐのは大変ですし。
どうしてBluetoothをつかうの。
つかわずに済めばそれでよかったんですが、仕方なくです。出回っている普通のAndroid携帯についている外部出力は、Bluetooth、無線LAN、赤外線、USBぐらいでしょう。しいて言うとディスプレイとオーディオがありますがこれをIOとして使うのはウルトラCなのでまず除外。USBはホストポートがついていない、クライアントポートを使うのは大変なので除外。赤外線は国産ガラケー的端末にしかついていないので除外。無線LANは消費電力が大きい(長距離は必要ないのに)、モジュールが少ない・高い、勉強することが多いので除外。と消去法的にBluetoothになりました。有線でできたらそれでよかったんですが、方法がない以上は仕方ないのでこれを使います。
無線になるとパフォーマンスが落ちますよね。
そうです。でも有線でできないので仕方ありません。パフォーマンスを重視する方は正攻法(開発ボードを使う)。
どうしてSENAのモジュールなの。
TELECを通っていて、2.54mmピッチだからです。
TELECの付いてない安いモジュールでいいじゃん。
仕様的に同じものがマークのあるなしで合法違法が変わるということについては、疑問が無いではないですが、ある程度の合理性はある制度だと考えてます。あと、私の本業的にコンプライアンスを無視できないので。
どうしてSTM32なの。
要求仕様的にはSTM32じゃないといけない理由は無いです。端的にいえば、私が本を書いているので、開発に慣れているというのが一番の理由でしょう。あとマイコンのことがわからない、ライターを持っていないという人でも、USB経由で簡単にフラッシュの書き換えができるので、結果的に、人口の多い、普通のAndroid開発者もターゲットにできるはずと期待しているということもあります。
iPhoneでやらないの。
持ってないのでできません。Objective-Cを学ぶ根性も今のところないので。
ネーミングは
わかりやすく
STとIOとAndroidの組み合わせで
stiodroid
stioroid
stioid
この3パターンぐらいが間がエラ得るけれども、stioidはわかりにくいのと、アカウント名で同じ単語列を使っている人がいるので却下
呼びやすいのはstioroid(スティオロイド)かな スティオドロイドよりはいい感じ
ということでstioroidに決定