これまで使用してきたセンサと同様、XBeeモジュールをArduinoに接続して使用するためのライブラリをインストールします。ライブラリを使用すると、自分で1からXBeeモジュールとの通信をプログラムするよりも簡単に通信を行えます。
Arduino IDEを開き、ライブラリマネージャでXBeeライブラリをインストールします。メニューバー上の、「スケッチ」>「ライブラリをインクルード」>「ライブラリを管理」をクリックするとライブラリマネージャが起動します。検索欄に「XBee」と入力し、「by Andrew Rapp」となっているライブラリを見つけてインストールします。
ライブラリをインストールしたらArduino IDEを再起動し、XBeeモジュールからデータを読み込むスケッチを書いていきます。
このライブラリには、XBeeモジュールとの間でデータを送受信するための一般的なXBeeデータパケットのクラスが用意されています。ここでは、IOサンプルクラスを使用します。
まず、データパケットを読み取るために必要な設定を行います。XBeeとソフトウェア・シリアルのライブラリをインクルードします。
#include <XBee.h> #include <SoftwareSerial.h>
続いて、XBeeモジュールとの通信に使用するピンを定義します。
先述の通り、D0ピン・D1ピンはPCとの接続にも使用するピンです。動作確認用の出力デバイスとしてシリアルモニタを使用したいので、別のピンを割り当てます。
ここでは、受信(Rx)にD2ピン、送信(Tx)にD3ピンを使用することにしました。ピンを定義したら、ソフトウェア・シリアル・ライブラリを初期化します。D2ピンとD3ピンを使って、XBeeモジュールと通信を行うことになります。
uint8_t recv = 2; uint8_t trans = 3; SoftwareSerial soft_serial(recv,trans);
次に、XBeeライブラリとヘルパークラスのインスタンスを生成します。
XBee xbee = XBee(); ZBRxIoSampleResponse ioSample = ZBRxIoSampleResponse();
以上で、スケッチを作成する準備ができました。
続いて、Arduinoが起動した際に一度だけ実行する、「setup」メソッドを作ります。
ソフトウェア・シリアル・ライブラリを起動し、XBeeライブラリに渡してXBeeモジュールとの通信に使用できるようにします。
また、(ソフトウェア・シリアルではない)通常のシリアルクラスを初期化して、print()文を使用して受信したデータをPC上で表示できるようにします。
void setup(){ Serial.begin(9600); while(!Serial); soft_serial.begin(115200); xbee.setSerial(soft_serial); }
3行目のwhileループは、Arduino Leonardoでスケッチを実行した際にXBeeモジュールが動作しなくなる場合があるため入れてあります。
今度は、受信したパケットからデータを読み取るためのメソッドをスケッチ上で作成してみましょう。
XBeeモジュールからパケットを読み取る方法は後ほど紹介します。まず、データパケットのソースアドレスを取得する方法を見てみましょう。
void get_address(ZBRxIoSampleResponse *ioSample){ Serial.print("Received I/O Sample from: "); Serial.print(ioSample->getRemoteAddress64().getMsb(), HEX); Serial.print(ioSample->getRemoteAddress64().getLsb(), HEX); Serial.println(""); }
ioSampleクラスのインスタンスを使用して、getRemoteAddress64()メソッドとgetMsb()メソッドを呼び出しています。これはRemoteAddress64というサブクラスとそのメソッドであるgetMsb()を呼び出しています。これらにより、64ビットアドレスの上位32ビットを取得できます。
同様に、getRemoteAddress64()メソッドとgetLsb()メソッドを呼び出すことで下位32ビットについても同様に処理を行います。
これらの読みだした値を16進数表記でPC(Arduino IDEのシリアルモニタ)上に表示します。複数のXBeeノードからデータを読み取る場合には、アドレスに応じで「bed room」や「living room」、「kitchen」など名前を付けると便利でしょう。詳しく紹介しませんが、各自工夫してみてください。
次に、データのペイロードを読み取ります。XBeeコーディネーターはXBeeセンサノードが作成した温度データを受信し、XBeeモジュールでセンサを読み取る:センサノードの設定と測定の例と同様に、XBeeモジュールのAD変換値からセンサが出力したミリボルト単位の電圧、読み取った温度に変換します。まず摂氏単位の温度に変換し、さらに華氏単位にも変換します。
void get_temperature(ZBRxIoSampleResponse *ioSample){ float adc_data = ioSample-> getAnalog(3); Serial.print("Temperature : "); float temperatureC = ((adc_data * 1250.0 / 1023.0) - 500.0) / 10.0; Serial.print(temperatureC); Serial.print("C, "); float temperatureF = ((temperatureC * 9.0)/5.0) + 32.0; Serial.print(temperatureF); Serial.println("F"); }
最後に、データパケットから電源電圧を読み取ります。
残念ながら、XBeeライブラリにはIOサンプルパケットから直接電源電圧を取得できるようになっていません。そこで、ライブラリが保存したIOサンプルパケットの「生のデータ」からデータを取り出すサブクラスを活用します。
電源電圧はAD変換で読み取ったデータの後、チェックサムの手前で送信されており、この例では受信したデータの18バイト目と19バイト目に保存されています。
温度データと同様に、XBeeモジュールでセンサを読み取る:センサノードの設定と測定の例と同様に、読み取った値をボルト単位の電源電圧に変換します。
void get_supply_voltage(){ Serial.print("Supply Voltage : "); int ref = xbee.getResponse().getFrameData()[17] << 8; ref += xbee.getResponse().getFrameData()[18]; float volts = (float(ref)*float(1200.0/1024.0))/1000.0; Serial.print(volts); Serial.println("volts."); }
先ほど、電源電圧として読み取るべきデータは「18バイト目と19バイト目」としました。
Arduino IDEで使用している言語の仕様で、データは「配列」というデータのまとまりとして保存されていて、先頭を「0番目」としてカウントするため、結果「17」「18」という数字が出てきます。また、2つの8ビットデータを結合して1つの16ビットデータとするために、上位のデータを8回左にビットシフトしています。
これらのメソッドを実装したら、XBeeモジュールからデータを読み取るメソッドをloop()メソッドに配置し、作成したメソッドを呼び出してデータを解読し、シリアルモニタに出力します。
void loop(){ xbee.readPacket(); if(xbee.getResponse().isAvailable()){ if(xbee.getResponse().getApiId() == ZB_IO_SAMPLE_RESPONSE){ xbee.getResponse().getZBRxIoSampleResponse(ioSample); get_address(&ioSample); get_temperature(&ioSample); get_supply_voltage(); }else{ Serial.print("Expected I/O Sample, but got "); Serial.print(xbee.getResponse().getApiId(),HEX); } }else if(xbee.getResponse().isError()){ Serial.print("Packet Read Error. Error Code : "); Serial.println(xbee.getResponse().getErrorCode()); } }
loop()メソッドは繰り返し実行されるので、XBeeクラスのメソッドを使ってパケットを読み込み、そのパケットがIOサンプルパケットかどうかを判断します。
IOサンプルパケットであればパケットから各データを読み込みます。そうでなかった場合にArduinoが停止してしまわないよう、簡単なエラー処理を追加しました。
受信したパケットが利用可能であれば読み込みを行います。そのパケットが正しいフレームタイプ(ここではIOサンプルパケット:ZB_IO_SAMPLE_RESPONSE)であれば、ここまでで作成したメソッドにデータを渡し、シリアルモニタ上にデータを表示します。
パケットの読み取りにエラーがあった場合には、エラーの内容をシリアルモニタに表示します。
これで必要なメソッドが揃いましたので、Arduinoで実行するために1つのスケッチにまとめます。完成したスケッチを以下に示します。
#include <XBee.h> #include <SoftwareSerial.h> //XBeeシールド用の設定 uint8_t recv = 2; uint8_t trans = 3; SoftwareSerial soft_serial(recv,trans); //XBeeライブラリのインスタンスを生成 XBee xbee = XBee(); //IOサンプルクラスのインスタンス化 ZBRxIoSampleResponse ioSample = ZBRxIoSampleResponse(); void setup(){ Serial.begin(9600); while(!Serial); //Arduino Leonardoのフリーズ対策 soft_serial.begin(115200); xbee.setSerial(soft_serial); } //XBeeモジュールのアドレスを表示する void get_address(ZBRxIoSampleResponse *ioSample){ Serial.print("Received I/O Sample from: "); Serial.print(ioSample->getRemoteAddress64().getMsb(), HEX); Serial.print(ioSample->getRemoteAddress64().getLsb(), HEX); Serial.println(""); } //温度を取得して表示する void get_temperature(ZBRxIoSampleResponse *ioSample){ float adc_data = ioSample-> getAnalog(3); Serial.print("Temperature : "); float temperatureC = ((adc_data * 1250.0 / 1023.0) - 500.0) / 10.0; Serial.print(temperatureC); Serial.print("C, "); float temperatureF = ((temperatureC * 9.0)/5.0) + 32.0; Serial.print(temperatureF); Serial.println("F"); } //電源電圧を取得して表示する void get_supply_voltage(){ Serial.print("Supply Voltage : "); int ref = xbee.getResponse().getFrameData()[19] << 8; ref += xbee.getResponse().getFrameData()[20]; float volts = (float(ref)*float(1200.0/1024.0))/1000.0; Serial.print(volts); Serial.println("volts."); } void loop(){ xbee.readPacket(); //パケット読み込み if(xbee.getResponse().isAvailable()){ //パケットを受信していた if(xbee.getResponse().getApiId() == ZB_IO_SAMPLE_RESPONSE){ //パケット取得 xbee.getResponse().getZBRxIoSampleResponse(ioSample); //データの読み込みと表示 get_address(&ioSample); get_temperature(&ioSample); get_supply_voltage(); }else{ Serial.print("Expected I/O Sample, but got "); Serial.print(xbee.getResponse().getApiId(),HEX); } }else if(xbee.getResponse().isError()){ Serial.print("Packet Read Error. Error Code : "); Serial.println(xbee.getResponse().getErrorCode()); } }
動作テスト
スケッチが書き込めたら動作テストを行います。
まず、Arduino(XBeeコーディネーター側)を起動し、続いてセンサノード(XBeeルーター側)を起動します。
Arduino IDEのシリアルモニタを開きます。XBeeセンサノードとコーディネーターとなるXBeeモジュールとでネットワークが繋がり通信が始まりしばらくすると、シリアルモニタにデータが表示されます。同時に、XBeeブレイクアウトボード上の通信確認用のLEDが点滅する様子も確認できるでしょう。
■シリアルモニタ出力の例
Received I/O Sample from: 13A20041C199CA Temperature : 15.78C, 60.40F Supply Voltage : 3.85volts. Received I/O Sample from: 13A20041C199CA Temperature : 15.65C, 60.18F Supply Voltage : 3.85volts. Received I/O Sample from: 13A20041C199CA Temperature : 15.78C, 60.40F Supply Voltage : 3.85volts. Received I/O Sample from: 13A20041C199CA Temperature : 15.78C, 60.40F Supply Voltage : 3.85volts. Received I/O Sample from: 13A20041C199CA Temperature : 16.02C, 60.84F Supply Voltage : 3.85volts. Received I/O Sample from: 13A20041C199CA Temperature : 15.90C, 60.62F Supply Voltage : 3.85volts. Received I/O Sample from: 13A20041C199CA Temperature : 15.78C, 60.40F Supply Voltage : 3.85volts.
うまくいったでしょうか?
これで、センサノードと、Arduinoを活用したセンサデータアグリゲータを構築する最初の一歩が踏み出せました。
シリアルモニタに出力が表示されない場合は、ArduinoとXBeeモジュールが正しく接続されているか(すべてのXBeeシールドがD2ピン・D3ピンを使用しているとは限りません)、それぞれのXBeeモジュールのファームウェアが間違っていないか確認しましょう。XBeeモジュールでセンサを読み取る:センサノードの設定と測定に一度立ち返り、センサノードが正常に動作するか確認すると良いでしょう。
また、Arduinoとセンサノードの両方とも一度電源を切り、先にArduino、続いて10秒ほどたってからセンサノードの電源を入れてみてください。時折、ネットワークの構築がうまくいかない場合があり、この手順で電源を入れなおすと構築をはじめからやり直すことができます。
さらにステップアップ
センサノードを2つ、3つと増やし、Arduinoのスケッチを工夫して各センサノードがどこに置いてあるかを送信してみましょう。
例えば、「kitchen」「living room」など、センサノードに名前を付け、Arduinoスケッチからシリアルモニタに表示する際にセンサデータとセンサの名前を表示すると実現できます。
使用したパーツのリスト
最後に、このセクションで紹介したチュートリアルを実行するために必要な電子部品を表1にリストアップします。
項目 | 製品例 | 参考価格 | 必要数 | |
ブレッドボード | https://www.switch-science.com/catalog/313/ | ¥275- | 1 | |
ジャンプワイヤー | https://www.switch-science.com/catalog/620/ | ¥440- | 1 | |
DHT22 もしくはDHT11 | https://www.sengoku.co.jp/ | ¥1,782- | 1 | |
抵抗器4.7kΩ | https://www.switch-science.com/catalog/1084/ | ¥1,073- | 1* | |
温度センサTMP36 | https://www.marutsu.co.jp/pc/i/171271/ | ¥160- | 1 | |
Arduino XBeeシールド | https://www.switch-science.com/catalog/1972/ | ¥2,203- | 1 | |
XBee-ZBシリーズ2/2.5/3 | https://www.switch-science.com/catalog/5311/ | ¥2,546- | 2 | |
XBee Explorer ドングル | https://www.switch-science.com/catalog/1790/ | ¥3,243- | 1 ** | |
XBee Explorer USB | https://www.switch-science.com/catalog/1791/ | ¥3,243- | 1 ** | |
Arduino UNO | https://www.switch-science.com/catalog/789/ | ¥3,300- | 1 | |
* 必要なのは4.7kΩ1本だけですが、1セット持っておくと何かと役に立ちます。他サイトやショップでは同じ値の抵抗器100本や、1本単位でも販売されています。
** いずれか1つ使用します。
コメントを残す