Arduino + XBeeシールド + XBee で勝手にリセット
Arduino + XBee ZB S2C で遊んでて、時々勝手に Arduino がリセットするので何故だ、ということで。
結論を先に書くと、XBee のハードフロー制御動作と XBee シールドの回路の影響で、フロー制御がかかるとリセットしますよというお話。
環境は
- Arduino Uno R3 (秋月電子通商)
- DFRobot印XBee シールド (秋月電子通商)
- XBee ZB S2C (秋月電子通商)
- XBee 操作ライブラリ (デファクト?) API mode 2
状況としては、こちら(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 コマンド参照。ちなみにデフォルト値)。
つまり、起きている事象としては
- Arduino が XBee にがんがん送る
- XBee の送信バッファがいっぱい
- XBee はフロー制御をかけようと CTS 信号を落とす
- 負論理なので12番ピンがHIGHに
- Arduino にリセット信号どーん。再起動〜
ということな模様。なるほど、「R3 外せ」ってそういうことね。
スイッチかジャンパピンになっていればいいのにねーとか思いつつ。
XBee はハードフロー制御しか対応していないので、真面目に対応しようと思うと、
という改造が必要そう。
秋月電子で扱っているもう一つのXBeeシールド(Arduino公式版)のほうは、回路図を見る分にはCTSはArduino側に繋がっていないのでこの問題は起きないはず。
DFRobotのシールドでも、XBeeの設定を変更して DIO7 を Disable か Low 固定にすれば大丈夫かと。
ただし、フロー制御が一切無いのでがんがん送ったときに何がおきるか、という危険性はありますが。
(いや、ちゃんと 0x8B Transmit Status 確認しながら送信すればソフトフロー制御相当か?はっ、自分の実装がクソというオチ!?)