電気のDIY - PICとBluetoothドングルでPCやスマホからSPP通信
USBやBluetoothのプロトコルを理解していなくても簡単に実現できてしまった。
Arduino用に自作でシールド化するのも難なく応用できそう。
SPPサーバー編としてのまとめ。 (DUALSHOCK3編につづく



Bluetoothといえば、いわゆる技適未認定(電波法の問題)や市販のモジュールは結構いい値段する。

むかし使っていたUSBドングルのBluetooth、PLANEXのBT-MicroEDR1Xが2つ手元にある。
何とか利用できないものかと調べてみると

組込用マイコンなどOSを持たないデバイスでも使えるスタック開発プロジェクトを見つける。
しかもGoogle Codeでソースも公開されている。
 btstack

さらに、このbtstackをUSB v2.0 On-The-GoをもつPIC24Fに移植して
内部オシレーターのみでSPP通信する製品が国産で発売されているのを知った。
 ランニングエレクトロニクス
 インドアエアプレーンワールド

ランニングエレクトロニクスさんが公開されているSBDBT5Vの回路とソースを参考に
ブレッドボードでやってみる。まずマニュアルをダウンロードし仕様をチェック。

商用に流用するときは連絡してほしい。また、btstackの作者Matthias Ringwald氏と
ライセンス契約を締結してると書かれてある。

PIC24FJ64GB004を載せているが、いきなりTQFPと小さいパッケージを使う勇気はないし
ブレッドボードでは.....
ピン数が少ないDIPのPIC24FJ64GB002は同じファミリーでソース修正は少なく
コンパイルも通りやすいだろうと推測。

信号ピンの役割と入出力方向
Rx : 受信データ(IN)
Tx : 送信データ(OUT)
CTS: 送信可(IN)
RTS: 送信リクエスト(OUT)

PIC側の信号ピンは接続ミスに対して入力電圧耐性のピンを割り当る。

D+, D-, LED1, LED2はソースの変更なしでそのまま行けそう。
電源電圧とロジックの電圧
出力方向は相手がTTLだとバッファーかレベルシフト回路で5Vに引き上げる必要がある。

BT-MicroEDR1Xは内部の電圧レギュレータでUSBの5Vを3.3Vにしているらしい。
3.3Vあたりの電圧で電流不足にならなければ動作できるようなので
電源はレギュレーター無しで3.3Vに統一し最小限のパーツで動作確認してみる。
パーツの準備
  • PIC24FJ64GB002 × 1
  • セラコン10uF × 1
  • 抵抗 1kΩ × 2
     10kΩ × 1
  • LED1(赤) × 1
  LED2(橙) × 1
  • USBコネクタ A メス × 1
  • ピンヘッダー 必要に応じて適宜
  • USBドングルのBluetooth
(BT-MicroEDR1X使用したが多くの製品が使えそう)
  • PIC Kit3(ライター)
PIC24FJ64GB002以外はすべて手元にあったので出費は少なくて済んだ。
回路図
オリジナルにあるパスコンとフィルターは全て省略。とてもシンプルなのですぐに挿し終る。
コンパイラとソースの準備
OS環境はWindows7 64bitで作業した。
  • Microchip MPLAB X IDE(v2.05) と XC16 Compiler(v1.2.1)を使用
 IDEとコンパイラはマイクロチップから無料ダウンロード できるので
 環境にあったものをインストールする。
  • ランニングエレクトロニクスさんからソースをダウンロード
 (2014/02/19にSPPファームウェアソースVer.140219公開)

 Ver.140219のZIPはMPLAB Xプロジェクトのアーカイブになっている。
 MicrochipのIDEはファイルパスにスペースや2バイト文字を含んではいけないので
 解凍する場所は注意する。

 プロジェクトにはMicrochipのUSBフレームワークとbtstackから必要なものは
 全て含まれ、そのままコンパイル可能。とても親切なかたちで公開されている。

ソースのカスタマイズ

ターゲットデバイスを変更する
プロジェクトのプロパティで対象デバイスを
PIC24FJ64GB004からPIC24FJ64GB002に変更する。


シンボル"__PIC24FJ64GB004__"をFind in Projectsで検索すると
"main.c"と"HardwareProfile.h"がヒットした。

ターゲットデバイスをPIC24FJ64GB002に変更したので、この2つはコンパイルに影響がある。

直接関係のあるものは "main.c" 修正必要。

"HardwareProfile.h"の該当箇所はLCDなどの周辺デバイス用ピン設定だった。
ここは触らないでコンパイル無効にした。
main.c の編集
コンフィグレーションセクションとBOOL InitializeSystem (void)にある
48行目と64行目あたり2か所の #if プリプロセッサを変更する。

#if defined(__PIC24FJ64GB004__)  →  #if defined(__PIC24FJ64GB002__)

ついでにもうひとつ変更
static void packet_handler内でデバイス名をglobal.hで#defineされた
LOCAL_NAMEだけをペアリング先に返すようにした。
ピンマッピングを変更する
LED1 : RB14 そのまま (ピン25を使用する)
LED2 : RB15 そのまま (ピン26を使用する)

U1RX : RP23 変更 RP7 (ピン16を使用する) 5.5V トレラント
U1TX : RP22 変更 RP8 (ピン17を使用する) 5.5V トレラント
U1CTS: RP24 変更 RP9 (ピン18を使用する) 5.5V トレラント
U1RTS: RC4 変更 RB5 (ピン14を使用する) 5.5V トレラント
STO : RB9 変更 RA4 (ピン12を使用する)

U1CTSにピン18を使用するとSTOが重複してしまう。
STOはマニュアルによるとBluetooth未接続でLow、接続中でHighとなるステータス出力とある。
とりあえずピン12(RA4)に変更した。
global.h の編集
LOCAL_NAME変更
#define LOCAL_NAME "PIC24F"

130行目あたりの//for SBDBT board 以下にピンレイアウト関係の定義があるので
オリジナルの設定をコメントアウトして変更を追加した。
// Configure LED1 - put on pin 14 → pin 25 (RB14 No change)
#define	led1_setup()		(TRISBbits.TRISB14=0)
#define	led1_on()		(LATBbits.LATB14=0)	//ON
#define	led1_off()		(LATBbits.LATB14=1)	//OFF

// Configure LED2 - put on pin 15 → pin 26  (RB15 No change)
#define	led2_setup()		(TRISBbits.TRISB15=0)
#define	led2_on()		(LATBbits.LATB15=0)	//ON
#define	led2_off()		(LATBbits.LATB15=1)	//OFF

/* Configure U1RX - put on pin 3 (RP23)
#define	u1rx_setup()		(RPINR18bits.U1RXR = 23)
// Configure U1TX - put on pin 2 (RP22)
#define u1tx_setup()		(RPOR11bits.RP22R = 3)
// Configure U1CTS - put on pin 4 (RP24)
#define	u1cts_setup()		(RPINR18bits.U1CTSR = 24)
// Configure U1RTS - put on pin 5 (RC9)
// U1RTS has software control
#define	u1rts_setup()		(TRISCbits.TRISC9=0)
#define	u1rts_on()		(LATCbits.LATC9=0)	//ON:rx ready
#define	u1rts_off()		(LATCbits.LATC9=1)	//OFF:rx not ready
*********************** Changed for PIC24FJ64GB002 ************************/
// Configure U1RX - put on pin 16 (RP7 Changed)
#define	u1rx_setup()		(RPINR18bits.U1RXR = 7)

// Configure U1TX - put on pin 17 (RP8 Changed)
#define u1tx_setup()		(RPOR4bits.RP8R = 3)

// Configure U1CTS - put on pin 18 (RP9 Changed)
#define	u1cts_setup()		(RPINR18bits.U1CTSR = 9)

// Configure U1RTS - put on pin 14 (RB5 Changed)
// U1RTS has software control
#define	u1rts_setup()		(TRISBbits.TRISB5=0)
#define	u1rts_on()		(LATBbits.LATB5=0)	//ON:rx ready
#define	u1rts_off()		(LATBbits.LATB5=1)	//OFF:rx not ready
//*************************************************************************
#if STO_SERIAL
// Configure console OUT(U2TX) - put on pin 1 (RP9)
#define	sto_setup()		(RPOR4bits.RP9R = 5)
#define	sto_l()
#define	sto_h()
#else
/* Configure Status OUT - put on pin 1 (RB9)
#define	sto_setup()		(TRISBbits.TRISB9=0)
#define	sto_l()			(LATBbits.LATB9=0)
#define	sto_h()			(LATBbits.LATB9=1)
*********************** Changed for PIC24FJ64GB002 ************************/
// Configure Status OUT - put on pin 12 (RA4 Changed)
#define	sto_setup()		(TRISAbits.TRISA4=0)
#define	sto_l()			(LATAbits.LATA4=0)
#define	sto_h()			(LATAbits.LATA4=1)
//*************************************************************************
#endif

あとはコンパイル。エラーなくComplete! PCとPICkit3、PICを接続。
PICの電源はPICkit3から供給。IDEでプロジェクトプロパティからPICkit3のPowerを開く。
Power target circuit from PICkit3をチェック。Voltage Levelは初期設定のまま3.25V


Make and Program Deviceで書き込み完了。
ドングルが青く点滅し始めた。PICkit3からの3.25Vで動作しているみたいだ。

マニュアルを見るとLED1(赤)消灯、LED2(橙)点灯は接続待ちの状態。
簡単に行き過ぎて拍子抜ける。

なんといっても
元ソースがとてもきれい! 順調に進めたのは、このおかげです。
他のシリーズの基板用ファームも条件コンパイルしているので
一見、複雑そうだがすぐにコードは解釈できる。とても勉強になった。

動作確認

PIC側のドングルはBT-MicroEDR1X

  • ペアリング
 PC―PIC間(PC側のドングルもBT-MicroEDR1X)
  Windows標準のスタック       Toshibaのスタック
  

 スマホ―PIC間
  AQUOS PHONE SH-02E(Android4.0.4)
  

  • SPP通信
 PICとPC1をBluetoothペアリング。
 PIC側の送受信は秋月のUSBシリアル変換モジュールを使いPC2から操作した。


 [PC1(TeraTerm)]←Bluetooth→[PIC]←USBシリアル変換→[PC2(TeraTerm)]


この後、PC1をスマホに変えた。撮影はスマホを使っているので動画にはできない。
スマホには無料ターミナルソフトS2 Terminalをインストールして確認。
PCと同じように問題なく通信できた。

動画は単4エネループ3本だがフル充電から少し使用したもの2本(2.7V弱)でも動作した。
しかし送信距離や受信感度のパフォーマンスはかなり低下。スマホとBT-MicroEDR1Xの距離は
せいぜい1mほどが通信の限界で、それ以上離れるとペアリングは切断された。

各種センサーの信号をA/D変換するくらいのメモリ残量はあると思う。あとは結果をUART1に
書き出せばペアリング相手に送信できるので無線データロガーに使えそう。

ペアリングの相手はAndroidやWindows...etc これらのアプリを作れると応用範囲は広がる。