先日、Arduinoを搭載したロボットを、XBee ZigBee機器からワイヤレス制御したいという要望をいただきました。
そういった用途に向け、ワイヤレス部分の基本サンプル・プログラムを作成しましたので紹介いたします。
ボタンが3つまでの場合のサンプルについては、当方のウェブサイトや書籍で紹介しています。今回の要望は、ボタン5つでした。
下図の左は、XBee子機です。無線リモコン側を模擬したものです。ボード上の3つのボタンがDIO 1~3に接続されています。
また、小さなブレッドボードには、 DIO 4(XBee_pin 11)と DIO 11(XBee_pin 7)に接続されています。
これら合計5つのボタンの情報を、瞬時に右側のArduino搭載の親機に送信します。
左:XBee子機(リモコン側を模擬)
ZigBee RouterまたはEnd Device
右:Arduinoを搭載したXBee親機(ロボット側を模擬)
Arduino + LCD + ZigBee Coordinator
目次
サンプルスケッチ
サンプル・プログラムは以下の通りです。
緑文字の部分は、ライブラリ関数xbee_gpio_initに相当します。これだと3つまでしか対応できませんでした。
赤文字の部分が今回のポート4とポート11の対応部分です。
紫文字の部分は状態変化通知のための自動送信の設定です。
#include <xbee.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
byte dev[8];void setup() {
lcd.begin(16, 2);
lcd.clear();
lcd.print("Example 38 SW_R'");
xbee_init( 0 );
lcd.setCursor(0, 1);
lcd.print("Waiting for XBee");
lcd.setCursor(0, 1);
if(xbee_atnj(30) != 0){
lcd.print("Found a Device ");
xbee_from( dev );
xbee_ratnj(dev,0);xbee_ratd_myaddress( dev );
xbee_rat(dev,"ATD103");
xbee_rat(dev,"ATD203");
xbee_rat(dev,"ATD303");
xbee_rat(dev,"ATD403");
xbee_rat(dev,"ATP103");
xbee_rat(dev,"ATIC081E");
}else lcd.print("no Devices ");
}void loop() {
XBEE_RESULT xbee_result;xbee_rx_call( &xbee_result );
if( xbee_result.MODE == MODE_GPIN){
lcd.clear();
lcd.print(xbee_result.GPI.PORT.D1); // 子機XBeeのポート1の状態を表示する
lcd.print(xbee_result.GPI.PORT.D2); // 子機XBeeのポート2の状態を表示する
lcd.print(xbee_result.GPI.PORT.D3); // 子機XBeeのポート3の状態を表示する
lcd.print(xbee_result.GPI.PORT.D4); // 子機XBeeのポート4の状態を表示する
lcd.print(xbee_result.GPI.PORT.D11); // 子機XBeeのポート11の状態を表示する
}
}
左側の子機のボタンを押すと、「xbee_result.GPI.PORT.D1~4と11」に0または1が代入されます。それぞれの値に応じてモータを動かせば、Arduino搭載のワイヤレスロボットを手軽に製作することが出来ます。書籍をお持ちの方は、P.194のExapmle 38と合わせて、ご覧ください。
なお、上記の色つきの部分を一つのライブラリ関数またはパラメータ入力での対応の要望がありましたら、検討いたしますが、当面は、本サンプルのようにATコマンドで実現してください。
標準回路図(一部、読み替えが必要)
下図は、子機の回路図です。ADC Port1~3や、LED Port 4、11は不要です。
DIO4と、DIO11には、スイッチを接続してください。
乾電池で、何か月、数年といった年月にわたって動作させたい場合
子機の消費電力を抑えて、長期間にわたって動作させたい場合は、下記を参考にしてください。
通信エラー対策
(各種のノイズなどの影響により)、子機のボタン状態と、親機側の状態とが、まれに一致しなくなることがあります。それを防ぐには、定期的に親機から子機へ状態を問い合わせます。以下は、書籍P.197のExample 39と組み合わせたサンプルです。本書と合わせてお読みいただければ理解が深まるでしょう。
#include <xbee.h>
#include <LiquidCrystal.h>
#define FORCE_INTERVAL 100
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
byte dev[8];
byte trig=0xFF;void setup() {
lcd.begin(16, 2);
lcd.clear();
lcd.print("Example 38 SW_R'");
xbee_init( 0 );
lcd.setCursor(0, 1);
lcd.print("Waiting for XBee");
lcd.setCursor(0, 1);
if(xbee_atnj(30) != 0){
lcd.print("Found a Device ");
xbee_from( dev );
xbee_ratnj(dev,0);
xbee_ratd_myaddress( dev );
xbee_rat(dev,"ATD103");
xbee_rat(dev,"ATD203");
xbee_rat(dev,"ATD303");
xbee_rat(dev,"ATD403");
xbee_rat(dev,"ATP103"
;);
xbee_rat(dev,"ATIC081E");
}else lcd.print("no Devices ");
}void loop() {
XBEE_RESULT xbee_result;
if( trig == 0){
xbee_force( dev );
trig = FORCE_INTERVAL;
}
trig–;xbee_rx_call( &xbee_result );
if( xbee_result.MODE == MODE_GPIN || xbee_result.MODE == MODE_RESP){
lcd.clear();
lcd.print(xbee_result.GPI.PORT.D1); // 子機XBeeのポート1の状態を表示する
lcd.print(xbee_result.GPI.PORT.D2); // 子機XBeeのポート2の状態を表示する
lcd.print(xbee_result.GPI.PORT.D3); // 子機XBeeのポート3の状態を表示する
lcd.print(xbee_result.GPI.PORT.D4); // 子機XBeeのポート4の状態を表示する
lcd.print(xbee_result.GPI.PORT.D11); // 子機XBeeのポート11の状態を表示する
}
}
XBee用ライブラリ
なお、初めて利用される場合は、xbee用の管理ライブラリのインストールが必要です。ライブラリのインストール方法については、当方の書籍、もしくは、下記を参照してください。
by ボクにもわかるXBee用センサネットワーク