HOME >> 鉄道模型実験室 > 無線通信モジュール XBee を使う

鉄道模型実験室  無線通信モジュール XBee を使う

■ はじめに

 今回はいよいよ、無線通信の確認である。 やはり当初から覚悟していたややこしそうな設定に四苦八苦した。 やっと目途が付いたので、その要点を記録をして置く事にしよう。 設定のための教科書は、オーム社発行の「XBeeで作るワイヤレスセンサーネットワーク 」  3,200円+税 である。 Robert Faludi 著 水原文訳のやや専門的内容であるが、何とか理解出来た。

  .

 

■ 無線通信モジュール XBee のファームウェアの設定

 使用した無線通信モジュール XBeeは、ワイヤアンテナ型のモジュール(DIGI-XB24-Z7WIT-004 XBee ZB )を2個使用した。 教科書に従って、ファームウェアの更新から始めるが、このためには、XBeeとパソコンを接続する必要がある。 今回は ワイヤレスプロトシールド(ARDUINO-A000064 Arduino)を使用した。 このシールドをArduinoに乗せて、さらに下の写真に示すように孫亀のようにXBeeを重ねた。 この組合せは、便利なようであるが、設定に四苦八苦した場合には、その設定変更のたびに、いちいちモジュールを外す必要があった。 

 まず、XBeeモジュールを設定する時は、USBの接続部であるArduino のスケッチを入れ替えておく必要があった。 これはArduino が勝手な動作をしないようにするためらしい。 下の写真にしめす。 さらにシールドのセレクトスイッチを USB 側にして置く必要がある。

     

 この設定は、一度だけなら問題は無いのであるが、XBeeの設定 ⇔ Arduino での動作確認など、設定を色々変更して動作確認を行う場合には、非常に面倒なのである。もうろくするとこんな単純な操作でも飛ばしてしまって、 “何で動かないの?” とウルウロする場合が多々発生してしまった。

 XBeeの設定には、「X-CTU 」と言うソフトを使用する。 ネットからダウンロードして使用するも、こういったソフトをすぐに使いこなせる技量は当方には劣っているので、暫くはやはり右往左往であった。 説明書通りに操作すれば良いのであるが、まずは、あちこちいじってみて操作を方法を理解するのがベターと思われる。

 XBeeモジュールの設定内容とその作業は、教科書に詳しく記述されているので、ここでは省略するが、2台のXBeeモジュールをコーディネーターとルーターに設定して、まず第一段階はクリアーする。

  .

**********************************

 次に、ルーターとして設定したXBeeモジュールは、センサから得られたデータを親機に送信する機能を持たせるため、その動作命令を覚えさせておく必要がある。 この設定には “ATコマンド” と呼ばれている命令を使用する。 この設定には “Tera Team ”と言うまた別のソフトが必要であった。 このソフトは以前にもお目にかかったような気がしたが、使い方が判らずに放棄した覚えがある。 でもとにかく使う必要があるので、インストールして走らせた。

 最初は、キー入力しても表示されないし、出来たとしても既にある文字の上に表示されるのなど、これも四苦八苦であった。 やっと、このソフトの設定方法が理解出来たのは、何時間も後の事でした。

  .

 忘れないようように、その設定状態を左に示す。 ポイントはローカルエコーにチェックを入れる事と、受信の改行コードは、CR+LF に設定することであった。 たったこれだけのことであるが、何度も “変なソフト” と思ったことか。

 うまく言った時の画面の例とて、右上に示す。 +++を入力するとOKと返事があれば、通信が成立したのである。 その後にATコマンドを打ち込めば良いのである。

 センサ用のXBeeモジュールとしては、

    ATJV1    ⇒ コーディネーターと接続せよ
    ATD12    ⇒ ピンD1をアナログ入力とする
    ATD22    ⇒ ピンD2をアナログ入力とする
    ATIR0A    ⇒ サンプルレートを 10msec とする
    ATWR    ⇒ これらのデータを書き込むこと

の4個の命令を書き込むのである。

 ここで、サンプルレートを 10msec と設定しようとしたが、ダメと言われてしまった。 コマンド集によると、ATIR のパラメータは、 0, 0x32 - 0xFFFF (ms) とある。 ゼロは使用できないとして、最小でも 0x32 即ち50ms なのである。 そこでATIR32 に設定する。

  右上の画面例は、サンプルレートを100ms から50ms に変更した場合であるが、ATWR を送信する事を忘れて、設定内容の修正が出来ず、Arduino での作動確認で 「おかしい?」 と言う状態に何度も遭遇したことか・・・・・・・・・・・・・。

 

■ XBeeモジュールの通信の確認

 二つのXBeeモジュールの個別設定が出来たので、実際の無線通信を確認することにした。

 センサー側にルーターとして設定したXBeeモジュールは、測定車両に搭載すべくコンパクトな基板に載せる必要がある。 このため、スイッチサイエンス社製のピッチ変換基板(SSCI-KIT-XBSOCKET XBee)を使用した。 XBeeモジュールの足のピッチが 2mm と特殊であるので、一般の2.54mm ピッチのユニバーサル基板に接続するために入手したが、スペース上、ユニバーサル基板を使わずに、配線する事にした。 その状態を下に示す。

  .

 ブレッドボードにオペアンプ回路を構成し、電源として単4を2本使用する。 そしてその二つの出力をXBeeモジュールのアナログ入力端子に接続する。 親局のコーディネーターとして設定したXBeeモジュールをArduino に乗せて実験を開始する。 右の写真。 オペアンプの入力電圧として、電源は安定化電源を使用して電圧を付与している。

******* XBee_Test_1 ***********

int analogValue;
int analogHigh;
int analogLow;

void setup(){
  Serial.begin(9600);
}

void loop(){
  if (Serial.available() > 21) {
    if (Serial.read() == 0x7E) {
      for (int i = 0; i < 18; i++) {
        byte discard = Serial.read();
      }
      analogHigh = Serial.read();
      analogLow =  Serial.read();
      analogValue = analogLow +
 (analogHigh * 256);     }     Serial.println(analogValue);   } }

 スケッチの内容は、教科書の内容を参考にして左の様に記述した。

 オペアンプの入力電圧を変えながら送信結果を表示するシリアルモニタをみていると、どうもデータが変なのである。 一定電圧をかけているのに、データ値はバラバラなのである。

 電圧を変化させると値も変化しているので、無線通信は実施しているようである。 どうもデータのやり取りがおかしいようである。 ここから、また、大きな壁にぶつかってしまったのである。

******************** しばし休憩 ****************************

*********  XBee_Test_12  ***************
int data1;
int data2;
  ……… この間は省略
int data12;

void setup(){
  Serial.begin(9600);
}

void loop(){
  if (Serial.available() > 21) {
    if (Serial.read() == 0x7E) {
      for (int i = 0; i < 12; i++) {
        byte discard = Serial.read();
      }
      data1 = Serial.read();
      data2 = Serial.read();
       ……… この間は省略
      data12 = Serial.read();
    }     String buf = String(data1)+","
+String(data2)+","
    ……… この間は省略 ……… 
+String(data12)+",E";     Serial.println(buf);   } }

 どの様なデータが送信されているのか、表示出来るようにスケッチを工夫することにした。 しかし、、そのたびに Arduino に乗っているXBee モジュールを取り外して、スケッチを書き込む必要があった。 あまりに面倒なので、XBeeシールドをArduino から取り外し、必要なポートだけをリード線でつなぐようにした。 リード線はたったの4本だけでよく、外す線も D0 とD1 のTX線とRX線の2本だけで良いことに気が付いた。 しかし、無線モジュールの設定変更の場合は、モジュールの取り外しはやはり必要な作業であった。

  .

 こうして、通信データの構造をみるスケッチを作った。 それを右に示す。 スマートとは言い難いが、とにかく通信内容のデータをみる事が出来るようになった。

 その時のシリアルモニターのスクリーンプリントを左に示す。 このデータから皆さんは何を読み取ることが出来ると思いますか?

 このデータをテキストファイルにコピーして、XECELから開くと下し示す表として表示できる。

 

 

 

 

 

 

 送信されてきたデータは規則正しいが、そのうちの3個のデータが変な値を示している事が判る。 そしてそれは周期的に発生している。 この原因は、XBeeモジュールのデジタル変換に時間がかかっているのではないかと想定した。 

 そこで、モジュールのサンプルレートを 100msec に変更してみたがやはり状況は一緒であった。 もっと時間を延ばしてもよいが、それでは今回の目的に合わなくなるので、今度は、アナログ入力をひとつに絞って実験を実施した。

 

 

 

 その結果を右に示す。 100ms ではOKだったで、欲張って50ms でも実験してみたが、右の通りバッチリである。

     大成功!

 ここで学習したことは、短い間隔でデータ送信する場合には、アナログ入力は避けよ。 もし実施するなら、ひとつに絞るのが良い。 そして、サンプルレートは 50msec 以下には出来ない事を学んだ。

 そして、上記の「XBee_Test_1」のスケッチを使って、データを表示させると、綺麗なデータがシリアルモニタにスクロールされていた。

 ひとまず壁を乗り越えたと考え、気分転換としてデータ処理をするユニットの工作に取り掛かった。 完成品を下に示す。

   .

 

 

 その工作内容は次回の報告で実施するとして、以後の実験は、このユニットを使用して実施した。 最初に実施したのは、電圧測定の校正である。 その実験装置を下に示す。

  .

 安定化電源を使用してセンサの端子に接続し、電圧もテスターで測定する。 そして、無線モジュールを使ってパソコンに取り込むのである。

 

 シリアルモニタに表示された値とテスターの値をプロットしてグラフ化したデータを左にしめす。 そしてこのプロット点を直線近似させた近似式が電圧値を計算する演算式となるのである。 デジタル値が1023以上はA/D変換の限界値であることも了解である。

 さて、ここまでたどり着いたので後は、処理プログラムとしてどう取り込むかを検討する必要があるが、ここからもまた壁にぶつかってしまったのである。

*********  XBee_Test_14  ***************

#define Button 7

unsigned long analogValue;
unsigned long analogValueT;
int analogHigh;
int analogLow;
int n;

void setup(){
  pinMode(Button,INPUT);
  Serial.begin(9600);
}

void loop(){
//  int input_Button = HIGH;
//  while (input_Button == HIGH ) {
//    input_Button = digitalRead(Button);
//  } 
//  Serial.flush();
//  delay(20);  
  analogValueT = 0 ;
  for ( n=0; n <10; n++){
    if (Serial.available() > 21) {
      if (Serial.read() == 0x7E) {
        for (int i = 0; i < 18; i++) {
          byte discard = Serial.read() ;
        }
        analogHigh = Serial.read();
        analogLow =  Serial.read();
        analogValue = analogLow + (analogHigh
 * 256);         analogValueT = analogValueT 
+ analogValue;       }       delay(10);     }     }   String buf = String(analogValueT) + ','
+ String(n) ;   Serial.println(buf);   delay(1000); }

 

■ 処理プログラムの検討

  .

 まず左のデータを見てください。 これはシリアルモニタのデータを記録しておくためメモ帳にコピペしたものです。 何故かデータがバラバラで有ることに自分は失望してしまった。 どの様なスケッチを描いたかを右に示す。 要点は電圧データを10回読み取ってその合計を送信しようとするものなのですが・・・・・・・・・。

 インプットボタンの使用を止めたり、delay を入れたり、あるいはバッファのクリアを入れたりしましたが、状況は改善しませんでした。

 原因が良くわからないままに、ここで諦める訳には行かないので、しつこく試してみました。

**************************

 推定する原因として、バッファに貯まっているデータを取りこむときにおかしくなっていると想定している。 データの切り出し判断を “ 0x7E ” としているが、アナログデータで、偶然にもその値と一致すると、そこからデータを切り出しでしまうのではないかと考えたが、その頻度はあまりないであろうと思われる。 やはり違うのか? 連続的にデータを受信処理すると、データの切り出しはうまく行くが、データが変に貯まってしまうと、切り出しがクシャクシャになるのでは?

 このように考えて、単純なスケッチで実験してみた。

******* XBee_Test_40 ***********

int analogValue;
int analogHigh;
int analogLow;

void setup(){
  Serial.begin(9600);
}

void loop(){
  if (Serial.available() > 21) {
    if (Serial.read() == 0x7E) {
      for (int i = 0; i < 18; i++) {
        byte discard = Serial.read();
      }
      analogHigh = Serial.read();
      analogLow =  Serial.read();
      analogValue = analogLow + (analogHigh * 256);
      Serial.println(analogValue);
    }
  }
  delay(5000);
}

 ループの途中に delay を入れただけの単純なものであるが、この delay の値を変える事によって、面白い事実を発見した。

 その例を下に示す。

 NG の場合は、50、45、40、35msで、OKの倍は10、30ms

であった。 即ち、35ms以上のdelay を入れるとデータがクシャクシャになってしまうのである。

 

 

 

 

 

 

  結論としては、連続して走らせよと言うことと解釈する。

 しかし、どうやってこの処理プログラムを生かすのか、これまた迷ってしまった。 Serial.println を入れなければ良いような気もするし・・・・・・・・。 受信用と送信用のバッファは別だとも聞いていたし・・・・・・・。

 この悪戦苦闘をしている時の実験装置を下にしめす。 新しいスケッチを書き込む時の手順は、

  1. シールドをつなぐ黄色と緑線をはずす。
  2. スケッチを書き込む。
  3. 外した線をつなぐ。
  4. 送信側のスイッチを入れてしばらく待つ。

の繰り返しであった。 受信が始まると、シールドのTXとRXのLEDがパカパカと点灯し、シリアルモニタにデータが表示される。 送信側のスイッチを切るとこれらの作動は停止する。

 

*********  XBee_Test_50  ***************

#define Button 7

int analogHigh;
int analogLow;
int input_Button ;
int i;
int n;
int analogValue ;
int data[15];

void setup(){
  pinMode(Button,INPUT);
  Serial.begin(9600);
}

void loop(){
  input_Button = digitalRead(Button); 
  while (input_Button == HIGH ) {
    if (Serial.available() > 21) {
      if (Serial.read() == 0x7E) {
        for (int i = 0; i < 18; i++) {
          byte discard = Serial.read();
        }
        analogHigh = Serial.read();
        analogLow =  Serial.read();
        analogValue = analogLow + (analogHigh
 * 256);         data[n] = analogValue;         n = n + 1;         if (n > 10) {           n = 0;         }       }     }     input_Button = digitalRead(Button);   }   String buf = String(data[0])+","+
   ……… この間は省略 ………
+String(data[9])+",";   Serial.println(buf);   delay(2000); }

■ データの処理方法を試す

 お風呂の中で、新しいアイディアが浮かんだ。 送信されてきた電圧データを常に読み込んでおき、バッファをクリアーな状態にしておく。 そして、必要になった時点で読み込んでおいたデータを取り出すのである。

 さて、データをためておく方法はどうするか? その対応方法として、データを格納する配列をつくっておき、そこに入れておくのである。 配列の大きさは10個程度にし、配列番号を順繰りに大きくし、10以上になるとまたゼロに戻すのである。 すると、この10個の配列の中には、常に最新のデータが10個入っていることになる。 順番は問わないのである。

 スケッチの内容を右に示す。 ボタンが押されたらその時の配列データの値をシリアル通信でおくってくることにする。

 

 この時のシリアルモニタの画面は左の様であった。

大成功である!    

 

 ボタンを押すたびに、クリアーなデータを表示するので嬉しくなったしまった。

 電圧値を変化させてもデータをそれなりに送信してくれる。

 左に示す画面には、ひとつだけ異常データが有るがおわかりだろうか?

 このデータをパソコン側で受取り、EXCEL で処理する事を考えている。 10個の平均はXECELで計算させればよいし、上記様な異常データを見つけた場合には、データを整理する時にそのデータを消せば良いのである。

 さらに嬉しい事には、ボタンの代わりに速度センサーのゲートイン信号を利用すれば、ゲート通過中の処理には悪影響を及ぼさない事である。 10個のデータ、即ち 0.5秒前のデータなので、測定としては同時測定とみなされると考えている。

 

■ モータの端子電圧を測定してみる

 何とか処理方法を見つけたので、実際のモータを動かして、その時の電圧を測定してみる事にした。 電源として安定化電源を使用しているので、電圧変動は少ないと思われるが、モータのノイズなどが影響しているのではないかと考えられる。

  .

 上記のXBee_Test_50 のスケッチを使用し、得られたデータは、見やすいように加工した状態で右に示す。

 ここで、異常値と判断されるデータには黄色の印を付けているが、パラパラと散見される。

 使用するデータ数が少ないので、この様な値を使って平均値を取るにはすこし躊躇されるので、やはりEXCEL上で選別するのが正解のようである。

 

 

 

 

■ まとめ

 およそ1週間も掛って無線モジュールに悪戦苦闘してきたが、出口が見えたのでほっとしている。 今回、ここで学習したことをまとめておこう。

 次回はもうひとつの赤外線通信の実際を詰めることにしている。