Arduino + XBeeシールド + XBee で勝手にリセット

Arduino + XBee ZB S2C で遊んでて、時々勝手に Arduino がリセットするので何故だ、ということで。

結論を先に書くと、XBee のハードフロー制御動作と XBee シールドの回路の影響で、フロー制御がかかるとリセットしますよというお話。


環境は

状況としては、こちら(XBeeのリセットとXBee shieldの回路について - Arduinoを使い倒すページ)と似てるけれども、 XBee のリセットにつられて Arduino が落ちるのではなく、データをガンガン送信してる最中に突然 Arduino が再起動するという感じ。

先人の話があるので、シールドの回路図(DFR0015)を調べると、XBee 12番ピンの DIO7/~CTSトランジスタを介して Arduino 側のリセット信号線に繋がっている状態。

となると、 DIO7/~CTS がなにかのはずみで HIGH になっている模様。
XBee のピン設定で DIO7 がどうなっていたかを確認すると、「CTS flow control [1]」になっている状態 (XBee AT D7 コマンド参照。ちなみにデフォルト値)。

つまり、起きている事象としては

  1. ArduinoXBee にがんがん送る
  2. XBee の送信バッファがいっぱい
  3. XBee はフロー制御をかけようと CTS 信号を落とす
  4. 負論理なので12番ピンがHIGHに
  5. Arduino にリセット信号どーん。再起動〜

ということな模様。なるほど、「R3 外せ」ってそういうことね。
スイッチかジャンパピンになっていればいいのにねーとか思いつつ。

XBee はハードフロー制御しか対応していないので、真面目に対応しようと思うと、

  • R3 外す
  • XBee 12番ピンを Arduino の適当な Din に繋ぐ
  • Arduino のソフト側でその Din が Low なのを確認しつつ送信するように対応する

という改造が必要そう。


秋月電子で扱っているもう一つのXBeeシールドArduino公式版)のほうは、回路図を見る分にはCTSArduino側に繋がっていないのでこの問題は起きないはず。
DFRobotのシールドでも、XBeeの設定を変更して DIO7 を Disable か Low 固定にすれば大丈夫かと。

ただし、フロー制御が一切無いのでがんがん送ったときに何がおきるか、という危険性はありますが。
(いや、ちゃんと 0x8B Transmit Status 確認しながら送信すればソフトフロー制御相当か?はっ、自分の実装がクソというオチ!?)

XBeeの通信チャンネルの指定の仕方

2016/9/12 修正 当初 S2C で ch 26 が使えないとしてましたが対応しているようです。
元記事

XBee ついでなので、XBee ZB S2C が使う通信チャンネルの指定の仕方。

直感的には AT CH コマンドがあるから、これで指定できそうに見えるのだけれども、AT CH は無慈悲にも「read-only」。
どうすんだよ!と言うと、コーディネータで AT SC コマンドを使い、スキャンするチャンネル=選択可能なチャンネルを制限してしまう。
例えばチャンネル12を使いたい場合は SC に 0x0002 を与えて、そこしか選べないようにする。

ch11 0x0001
ch12 0x0002
ch13 0x0004
ch14 0x0008
...
ch25 0x4000
ch26 0x8000

という感じ。
チャネル26相当の 0x8000 も設定できてしまうけれど、XBee ZB S2C はチャンネル26に対応していないから通信できなくなる。(2016/9/12 修正)

また、ルータとエンドデバイスでは、この方法でチャンネル指定しないほうがよい。
ルータとエンドデバイスは、スタートアップ時にコーディネータにぶら下がる形になっているので、どのみちコーディネータが使っているチャネルになるし、コーディネータのチャンネルと違うチャンネルに制限してしまうとjoinできなくなってしまう。

XBee 送信ステータス 0x26 の意味

XBee でブロードキャスト送信していると、その送信ステータスで 0x26 が返ることがあるんですよ。

公式リファレンス によると、

0x26 = Broadcast source failed to hear a neighbor relay the message

ということで、ご近所がリレーしたメッセージが聞こえなかった(直訳)ということらしい。

ZigBee のブロードキャスト送信がどうなっているのかというと、知らないブロードキャストメッセージを受信したら再送信。という仕組みになっているらしい(Zigbee Network Layer Tutorial - Part 3: Broadcasts and Neighbors)。

したがって、「ブロードキャストメッセージを投げたものの、ご近所が再送信するはずメッセージが聞こえなかった。何かおかしい!」と言う意味になります。

試しに、コーディネータだけ動かしておいて、ブロードキャスト送信すると、周りに再送信するノードが誰もいないので、送信後 1 秒ほどで 0x26 が返ってきます。
それに対して、ルータが 1 台でもいると、 0x00 が返ります。

つまりは ぼっち、寂しいよね。