ZigBeeモジュール Wireless Engine TWE-Lite DIPを使ってみた

なんか最近発売されて、かなり売れているらしいTWE-Lite DIPを使ってみました。ハマったポイントなどを書いておきます。

TWE-Lite DIPとは

東京コスモス電機が発売しているZigBeeの無線モジュールです。販売は「秋月電子」とか「千石電商」とかで売ってます。

基本的には2つ以上を組み合わせて使います。最小構成は「親機」と「子機」となります。TWE-Lite DIPはデジタルピンやアナログピンを持っており、それぞれが双方向無線通信できるようになっています。

到達距離の確認について

公式ページには見通し1km送受信可能!と書いてあるので、おおっ!と思いますが、実際にどれだけ飛ぶのかテストしますよね。サンプルとして公式にもある「通信距離の測定」をやると思います。

親機のボタンをポチポチすると、子機のLEDが点滅します。わかりやすいです。

しかし、これには1つ罠があります。送信したデータ(この場合HIGHもしくはLOW)は送信先で保持されるため、送信元が変更しない限り変化しません。つまり親機のスイッチを押しっぱなしで、子機をずーっと離していって、たとえ通信が途絶えたとしても、LEDは点灯しっぱなしになりますので、どこまで届いたかはわかりません。到達距離を測るには、親機のボタンをON/OFFし続けて、子機が同時にON/OFFすることを確認しなければなりませんので注意して下さい。これだと送信距離のテストがしづらいので、疎通テスト用に別途作成することにしました(後述)。

Arduinoと組み合わせてみる

TWE-Lite DIP単体では無線通信ができるだけなので、何かしらマイコンなどを接続してデータをやり取りすることになります。上図のようにシリアル(RX, TX)も使えるので、PCにUSBシリアルで接続すればそれでもいいのですが、今回はArduinoを接続して子機側のArduinoにセンサを載せて、親機に送信することを考えます。

Arduinoの選択

TWE-Lite DIPは3.3v駆動です。Arduinoも3.3vのpro miniなどありますが、何かしらのセンサを載せようとすると結局5vと3.3vは混在しそうなので、今回は親機にはArduino Uno、子機にはArduino pro mini 5vを選択しました。子機側がpro miniなのは、ユニバーサル基板上にセンサを配置する関係で広いスペースが欲しかったからです。親機にはセンサは搭載しないので、Arduinoユニバーサル基板を使います。

3.3v <-- --> 5v 双方向レベル変換バッファ

親機・子機ともに必要になるのは、ArduinoとTWE-Lite DIPを接続するための双方向レベル変換バッファです。今回2種類購入しておきました。1つは秋月電子8bit双方向レベル変換モジュールもう1つはサンハヤト2電源8bit双方向レベル変換モジュール。価格は前者の方が安いのですが、I2Cの変換が出来ません。そのために後者も買っておきました。

で・・・最初にハマったのが、前者の秋月電子の双方向レベル変換バッファが使えなかった...orz 後述しますがシリアル通信で速度を落としても文字化けするので、結局使うのを諦めました。←使えるよという人が居たら教えて下さい。

作成した回路図の概略はこんな感じです

f:id:tomo_watanabe:20130804011518p:plain

f:id:tomo_watanabe:20130804011527p:plain

シリアル通信をレベル変換してArduinoと接続する

当初ArduinoとTWE-Lite DIPをシリアルRX, TXで接続してやれば、親機と子機で好きなデータ送受信できるよ、わっほい\(^o^)/とか考えていたのですが、これが甘かったようです。

TWE-Lite DIPは、例えば親機のデジタルイン→子機のデジタルアウトと通信するのですが、これらの変化が実はシリアルのRX,TXを通して双方向でバンバンやり取りされていました。

公式ページから抜粋

:7881150175810000380026C9000C04220000FFFFFFFFFFA7 
:7881150175810000380026FF000C02220000FFFFFFFFFF73 <約1秒おきに受信される
:788115017581000038002743000C03220000FFFFFFFFFF2D
:788115017581000038002785000C05220000FFFFFFFFFFE9
:7881150178810000380027D3000C05230000FFFFFFFFFF97
:788115017881000038002813000C02230000FFFFFFFFFF59
:78811501758100003800284F000C02230000FFFFFFFFFF20
:788115017581000038002899000C04230000FFFFFFFFFFD4
 ^1^2^3^4^5^^^^^^^6^7^^^8^9^^^a^b^c^de1e2e3e4ef^g
 
 1: 送信元の論理ID (0x78 は子機からの通知)
 2: コマンド(0x81: IO状態の通知)
 3: パケット識別子 (アプリケーションIDより生成される)
 4: プロトコルバージョン (0x01 固定)
 5: LQI値、電波強度に応じた値で 0xFF が最大、0x00 が最小
 6: 送信元の個体識別番号
 7: 宛先の論理ID
 8: タイムスタンプ (秒64カウント)
 9: 中継フラグ(中継済みなら1)
 a: 電圧[mV]
 b: 未使用
 c: DI の状態ビット。DI1(0x1) DI2(0x2) DI3(0x4) DI4(0x8)。1がLo。
 d: DI の変更状態ビット。DI1(0x1) DI2(0x2) DI3(0x4) DI4(0x8)。1が変更対象。
 e1~e4: AD1~AD4の変換値。0~2000[mV]のAD値を16で割った値を格納。
 ef: AD1~AD4の補正値 (LSBから順に2ビットずつ補正値、LSB側が AD1, MSB側が AD4)
 g: チェックサム

このように親機と子機、双方が約1秒おきに送信しあう仕様になっています。したがって、シリアル通信を自分の好きなように使うことができません...orz 公式ページにありますが、制約されたプロトコルにしたがってシリアルに載せないとデータのやり取りができません。使う時はここに注意が必要です。

TWE-Lite DIPのシリアル通信

上記のように、好きなようにシリアル通信を行うことができないことがわかりましたが、このシリアル通信を見ていてわかったことを書いておきます。設定は親機:連続モード、子機:連続モードです。TWE-Lite DIPが独自のシリアル送信を行う条件は

  • アナログ・デジタルのどれかのピンに変化が起きた時
  • タイムスタンプが変化したとき(内部タイマ割り込みだと思う)

のいずれかです。そのため未使用のアナログの入力ピンはHIGHにしておく(VCC)必要があります。オープンにしておくと、アナログ入力が変化してしまうので、バンバン送信してしまいます。解説書にもHIGHにしておけ。と書いてあります(ちなみに単に動作させるという意味では必須ではありません)そうすると、内部タイマ割り込みにより、約1秒毎に送信を行うようになります。

シリアル通信の設定

TWE-Lite DIPは外部マイコンとのシリアル通信の設定にデフォルトでは115200, もしくは38400が選択可能となっています。ArduinoデバッグシリアルとしてPCとのシリアル通信も必要になるので、Arduinoとは2pin, 3pinを使ってソフトウェアシリアルでTWE-Lite DIPと接続します。Arduinoのシリアル通信の上限が115200なので、データの取りこぼしを考えてTWE-Lite DIPとの通信は38400としました。

そこで前述の双方向レベル変換バッファを使用するのですが、秋月電子の8bit双方向レベル変換バッファは、ArduinoからPCへのデバッグシリアルで文字化けしてしまいました。TWE-Lite DIPの通信速度を設定変更モードを使って9600まで落としてもダメでした。

というわけで、サンハヤトの双方向レベル変換バッファに変更してみたら、1発で通信データが読めるようになりました。そのためこちらを採用しました。

秋月電子の8bit双方レベル変換バッファが使えないのは理由がわかりません。本当は使えるのかも。誰か教えてください(^^;

疎通テスト

ここまで出来ると、やっと疎通テストができるようになります。親機・子機のハードウェアシリアルをPCに接続してデバッグウィンドウを眺めると、通信データが見られるようになります。今回、どれだけの距離を送受信できるか確認したかったので、DIPスイッチで起動時切り替えを行い、特定のIDの場合、親機から子機へDO → DIのデータ送信を行い、1秒起きに子機の接続したLEDを点滅させます。同時に親機のArduino Unoに接続したLEDも点滅させます。子機をモバイルバッテリかなにかでUSB給電し状態で徐々に距離を離していって、送受信できなくなると子機のLEDが点滅せず、消灯、もしくは点灯に固定されるので、送受信が途絶えたことが判定できます。(左が親機、右が子機)

f:id:tomo_watanabe:20130803224636j:plain

自宅で試してみたところ(鉄筋コンクリートマンション)壁などの障害物があっても端から端までは問題なく届いたので、家屋内でも10mくらいは大丈夫そうです。アンテナは上下の感度は殆ど無いとのことなので、2階と1階とかは難しいかもしれません(未検証)

実際に有用なプログラムを組む場合はこのデータを順次読みだして「捨てる」もしくは「処理する」判断ルーチンが必須です。(特に変化無い場合でも送受信が行われるので...)その他にも送信データは文字列ですが、センサー値などの取得は数値なので、送信時にsprintfなどを使って文字列化する必要もあります。その前にチェックサムの作成も必要ですね。

というわけで、思いの外面倒な感じになりそうです...シリアル通信が自由に使えれば楽だったのですが(^^;

今回作成したプログラムは公開しようと思いますが、一旦整理してからにしたいと思います。