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 確認しながら送信すればソフトフロー制御相当か?はっ、自分の実装がクソというオチ!?)

CentOS7 の USB インストール

1. 公式サイトから Minimal の iso をダウンロードしてくる。
2. DD for Windows - Tech Info を使い、1. でダウンロードした iso を USBフラッシュメモリに書き込む
3. USB メモリをつっこんでターゲットを起動する

NetInstall イメージを使うと、ダウンロード先リポジトリの機嫌が悪いのかパッケージメタデータのダウンロードに時間はかかるし、その挙げ句、『ベースリポジトリのセットアップ中にエラー』とかで進めないので Minimal が無駄な時間を過ごさずに済む無難解。

Gradle で依存設定しているローカルjarファイルにはソースjarなどを紐付けできない?

Gradle、ローカルに置いた jar を依存設定するのはいいのだけれども、その jar のソースjarやJavadoc jarを紐付けできないのでちょっと不便。

Gradle というか Eclipse プラグインの Buildship の問題と見るべきかもだけれども…。

Can the Gradle Eclipse Plugin (buildship) attach sources to local jar dependencies using a sources folder (not a sources jar)?


ビルドパスの設定から、自前で同じローカルjarファイルを追加して、それにソースやJavadocを紐づければ、やりたいことはできるのだけれども、やや手間なのと、 Gradle の依存関係解決から外れるのでライブラリを入れ替えた場合などにトラブルになりそう。

シーケンス番号の連続性チェックのやりかた

UDP パケットとかドロップが起き得るデータにシーケンス番号を振っておいて、受け側でドロップがないか検査したりすることはよくあると思いますが、そのよくあるはずの検査アルゴリズムの知識がなかったので、頭をひねった結果をメモ。

int[] seq = new int[]{
        (int) 0xfffffff8L, (int) 0xfffffff9L, (int) 0xfffffffaL, (int) 0xfffffffbL,
        (int) 0xfffffffcL, (int) 0xfffffffdL, (int) 0xfffffffeL, (int) 0xffffffffL,
        0, 3, 4, 6, 7, 8, 9, 10, 13, 19, 20, 21, 22, 24, 27, 42, 43, 44, 45, 46, 47};

for (int i = 0; i < seq.length; i++) {
    if (i == 0) {
        System.out.printf("%2d %2d %08X%n", i, seq[i], seq[i]);
    } else {
        int diff = seq[i] - seq[i-1];
        if (diff == 1) {
            System.out.printf("%2d %2d %08X 連続%n", i, seq[i], seq[i]);
        } else {
            System.out.printf("%2d %2d %08X 脱落 %d 個%n", i, seq[i], seq[i], diff - 1);
        }
    }
}

現シーケンス番号と前のシーケンス番号との差分をみてやれば、符号の有無や、ラップアラウンドに関係なく検知できるはず。
シーケンス番号半周分(Short.MAX_VALUE とか Integer.MAX_VALUE とか)落ちるとかそんなのは無しで。
diff が負の場合は順序の入れ替わりなのでソートして再検査するか破棄するか。

Win32 Disk Imager Error 32

Win32 Disk Imager を使っていて、「Error 32: プロセスはファイルにアクセスできません。別のプロセスが使用中です。」が出たらパスが悪いのかもしれないので、イメージファイルをルートに置いてやり直してみよう。

Listen 0.0.0.0 in Java

Java で Socket Listen するときのアドレスを InetAddress.getByName("0.0.0.0") で与えると、
IPv4 の 0.0.0.0 と IPv6 の [::] の両方を Listen しちゃって、v4v6の両方で接続できちゃう
ようになるような(今更)

eclipse のデフォルト文字コードの変更

eclipse で開いて文字化け、「ふぁっきんms932!」と叫んだときに。

eclipse.ini に

-Dfile.encoding=utf-8

を追加

設定→一般→ワークスペース で変更する手もあるけど、そちらはワークスペース単位なので。

eclipseで開くのは UTF-8 に決まってるだろぉぉぉぉ」って場合は、eclipse そのもののデフォルトを変更する方が幸せだよね(たぶん)。