USB Host Shield 2.0 for ArduinoでのSPP通信実験
せっかくなのでワイヤレスでの機体状態の確認とか遠隔制御とかに使えるのでSPPプロトコルでの通信ができるかを確認しました。 「MultiWiiConf_2_0」から接続して機体状態を表示出来ればいいかなと思っていたのですが、なんだかんだで問題出まくりだったのです。
前回同様の構成で、検証に使ったのは「USB Host Shield 2.0 for Arduino」+「USB Host Library for Arduino」を使用。そして、接続先のMultiWii相当としたArdunioNanoをあててテストをしました。
- PC⇔Arduino間のSPP接続に関しては接続は接続可能
- ただし、Windows標準のBluetoothスタックを使った場合にのみ。 ※:iba、Motorolaスタックを使用した場合にはサービス検索に失敗して接続できません。Broadcomスタックは未確認)
■PCとのSPP接続の流れ
注意:プロトコルスタックはMicrosoft製の純正スタック
- Arduino側でスケッチ「SPP.ino」をアップロードしてドンブルをセット
- PC側よりBluetoothデバイスを検索⇒PINコードを入力して接続 ※:XP/7で接続確認を行いました。
★接続完了画面
まあ、ここまででもなんだかんだで結構かかっていますけれども…。スタック周りのトラブルでなかなか接続できなかったりとか、ドライバが2重に入ってしまって正常に動かかなくなってしまったりとか大変でした。 ようやく接続できた後ですが、そこからはこれまで以上に茨の道だったりしました。
通常、シリアルデータの受け渡しをするだけであればコードは非常に簡単です。 ※:以下コードはMega系列の644P/1284P/1280/2560限定です。なぜなら、ハードウェアシリアルを2系統以上持っていないと使用できないためです。 今回、Mega系列を使用したい理由はその辺りにあります。ソフトウエアシリアルを使えばほかホストとのUART通信は可能ですがど速度が出ない&リソースを食うので…。 さらに、644/1284は実装面積が1280/2560の半分程度になります。そのため、その中で最大容量の1284Pが最有力候補となっているのです。RAMサイズも最大ですしね。
■テストコード1(旧)
[sourcecode]
void setup() {
// initialize both serial ports:
Serial.begin(115200);
Serial1.begin(115200);
}
void loop() {
// read from port 1, send to port 0:
if (Serial1.available()) {
int inByte = Serial1.read();
Serial.write(inByte); }
// read from port 0, send to port 1:
if (Serial.available()) {
int inByte = Serial.read();
Serial1.write(inByte); }
}
[/sourcecode]
■テストコード2(新)
[sourcecode]
int inByte_TxRx = 0; // incoming serial byte
int inByte_RxTx = 0; // incoming serial byte
boolean stringComplete_TxRx = false; // whether the string is complete
boolean stringComplete_RxTx = false; // whether the string is complete
void setup() {
Serial.begin(115200);
Serial1.begin(115200); }
void serialEvent() {
inByte_TxRx = Serial.read();
stringComplete_TxRx = true; }
void serialEvent1(){
inByte_RxTx = Serial1.read();
stringComplete_RxTx = true; }
void loop() {
if (stringComplete_RxTx) {
Serial.write(inByte_RxTx);
stringComplete_RxTx = false;
}
if (stringComplete_TxRx) {
Serial1.write(inByte_TxRx);
stringComplete_RxTx = false;
}
}
[/sourcecode]
普通だったら、上記コードの受け渡し先ポートをハードウエアからBluetoothに変更してあげればうまくいくはずなのですが、全くうまくいかない状態になりました。 色々と悩んだ結果わかったことはやはりソフトウェア制御のシリアルなのでデータの入出力の割り込みが多すぎて処理できないまま止まっている…。おそらくバッファエラー…。Orz そこから色々とテストした結果ですが、受信データのバッファ内容を一括で配列に格納してから送信してあげる事で解決しました。
■SPPテストコード
[sourcecode]
#include <
SPP.h>
USB Usb;
BTD Btd(&Usb);
SPP SerialBT(&Btd, "Arduino_Mega","0000");
void setup() {
Serial.begin(115200);
Serial1.begin(115200);
if (Usb.Init() == -1) {
Serial.print(F("\r\nOSC did not start"));
while(1); //halt
}
Serial.print(F("\r\nSPP Bluetooth Library Started")); }
void loop() {
Usb.Task();
if(SerialBT.connected) {
uint8_t length = SerialBT.available();
uint8_t str_box[length-1];
for(uint8_t i = 0; i < length; i++){
str_box[i]=SerialBT.read();
}
Serial1.write(str_box,length);
}
}
void serialEvent1() {
uint8_t length = Serial1.available();
uint8_t str_box[length-1];
if(SerialBT.connected) {
for(uint8_t i = 0; i < length; i++){
str_box[i]=Serial1.read();
}
SerialBT.print(str_box,length);
}
}
[/sourcecode]
やはり、無線ですし処理速度が足りないようなので速度はそれほど出ません。 厳密なリアルタイムではないですが、リアルタイムデータに近いものは取得できそうです。
processingとかをPC側のフロントエンドにすれば比較的簡単にPCからの遠隔操縦が可能になると思われます。その際にはClass1のBTドングルを双方で使用すれば距離100mまで操作可能となります。 そこまでやるとカメラを搭載しないとダメですね。でも、そんなに軽いカメラとか存在するのでしょうか?(アメリカに1gのNTSC出力のカメラが有るみたいですけども、日本では使用できない) 次回は、電源周り(バッテリー周り)の回路のテストをしてみたいと思います。あとは、Atmega1284Pを実機には積みたいので1284Pでの接続検証ですね。 検証がうまく行ったら、専用基板を作って実機飛行できるようにしていきたいと思います。基板は4層かな?
★参考情報
せっかくなので、ハードウェアシリアルでも高速通信させるとバッファから溢れてデータが断片化することがあるようなので対策コードを、上記テスト版の変形です。
■ATMega高速シリアル通信用テストコード
[sourcecode]
void setup() {Serial.begin(115200);
Serial1.begin(115200);
}void loop() {
uint8_t length = Serial.available();
uint8_t str_box[length-1];for(uint8_t i = 0; i < length; i++){
str_box[i]=Serial.read();
}
Serial1.write(str_box,length); }void serialEvent1() {
uint8_t length = Serial1.available();
uint8_t str_box[length-1];for(uint8_t i = 0; i < length; i++){
str_box[i]=Serial1.read();
}
Serial.write(str_box,length);
}
[/sourcecode]
コメントはまだありません。