スケッチとはArduinoで動かすプログラムのことです。Arduinoのプログラマーはアーチストという位置づけで、アーチストが作成するのはソースコードのような複雑で専門的なものではなく、物事の本質を描くという意味がこめられているものと思います。
まずは、簡単なサンプルスケッチを見てみましょう。「さぁ準備を始めよう」の章でサンプルスケッチの呼び出し方を説明しましたとおり、 Arduino IDEの「ファイル」メニューから「スケッチの例」「XBee_Coord」を選ぶと、サンプルスケッチが表示されます。今回は「sample0_test」を選んでください。
呼び出したスケッチは下記のようになります。このスケッチにはコメントも併記しているので、見ていただくだけで、だいたい何をやっているのかが分かると思います。「だいたい」ではなく、ほぼ理解できるかもしれません。本XBeeライブラリには豊富なサンプルスケッチを用意していますので、スケッチを描くための基礎勉強は、なるべく省略して、サンプルを動かしながら学んで欲しいと考えています。そういった意味では、このページは、あまり読まなくて良いのですが、一つくらいは細かな流れを知っておいた方が、他のサンプルを早く読み進めることが出来ると思って、作成しました。
#include <xbee.h> #include <LiquidCrystal.h> LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // ↓お手持ちのXBeeモジュール子機のIEEEアドレスに変更する byte dev_gpio[] = {0x00,0x13,0xA2,0x00,0x40,0x30,0xC1,0x6F}; void setup(){ lcd.begin( 16, 2 ); // キャラクタ液晶の初期化 lcd.clear(); // 液晶表示をクリア(消去) lcd.print("Sample 0 TEST"); // タイトル表示 xbee_init( 0x00 ); // XBee用COMポートの初期化 xbee_gpio_init( dev_gpio ); // デバイスdev_gpioにIO設定を行うための送信 delay( 1000 ); // 1秒間の待ち } void loop(){ int gpi = xbee_gpi( dev_gpio , 1 ); // GPIポート1からデジタル入力 int adc = xbee_adc( dev_gpio , 2 ); // ADCポート2からアナログ入力 xbee_gpo( dev_gpio , 11 , gpi ); // GPOutポート11をin値へ xbee_gpo( dev_gpio , 12 , 1 ); // GPOutポート12をHレベルへ lcd.clear(); // 液晶表示をクリア(消去) lcd.print("GPI(1) = "); lcd.print( gpi ); // inの値を表示 lcd.setCursor( 0 , 1 ); // 液晶の2行目にカーソルを移動 lcd.print("ADC(2) = "); lcd.print( adc ); // inの値を表示 delay( 1000 ); // 1秒間の待ち xbee_gpo( dev_gpio , 12 , 0 ); // GPOutポート12をLレベルへ delay( 1000 ); // 1秒間の待ち } |
スケッチはvoid setup()とvoid loop()に分かれているのが分かると思います。setup()はArduinoの起動時に一度だけ実行する初期化処理が記述されています。loop()には、起動後に繰り返し実行する定常処理が記述されています。
void setup()とvoid loop()の外に書かれているincludeなどは、あまり意味を知らなくても大丈夫です。おまじないと思っておいてください。変更しなければならない内容は各サンプルスケッチに記述してあります。この例では「byte dev_gpio」の部分に「子機のIEEEアドレスに変更する」と書いてありますので、お手持ちの「子機」のXBeeモジュールのアドレスに書き換えてください。IEEEアドレスはXBeeモジュールの裏側に「0013A200」と「XXXXXXXX(8文字の英数字)」の2行で書かれています。
ここでは、分かりやすいようにXBeeモジュールを「親機」と「子機」に分けて記載していますが、どちらも同じXBee Series 2(S2やS2B)です。Arduinoに接続する方を「親機」、センサーを「子機」としています。一つのXBeeネットワークの中に「親機」は1台しか存在できません。「親機」のXBeeには「COORDINATOR API」のファームウェアを書いておきます。「子機」は初期状態の「ROUTER AT」のままでかまいません。この先、Arduinoが「子機」として動作する話や、子機に接続される「孫機」も出てきて、ややこしくなりますが、今はArduinoに接続されているのが「親機」で、それ以外は「子機」です。
xbee_initはArduinoに親機XBeeモジュールの初期化コマンドです。括弧内の0x00は無視してください。サンプルスケッチのsetup内で「lcd.〜」が3行ほど続いた後にxbee_initが記述されています。
「lcd.〜」は液晶へ表示するコマンド群です。例えば「lcd.print」の一塊で、括弧内の「Sample 0 TEST」の文字を液晶に表示することが出来ます。文字は「"(ダブルコーテーション)」で囲んでおく必要があります。囲まなかった場合は「変数」と呼ばれる数字や文字が収納された「代表名」を記述します。
ここまでの記述で、「液晶にタイトルを表示して、親機XBeeを初期化する」という処理が行われます。なお、Arduinoが親機XBeeとのシリアル通信に失敗するとxbee_initの部分で止まったままとなります。
親機XBeeの初期化後に子機XBeeの設定を行うコマンドがxbee_gpio_initです。括弧内の「dev_gpio」には子機のIEEEアドレスが代入されています。
xbee_gpio_initを実行すると、親機XBeeが子機XBeeと通信を開始し、子機のGPIOポート1〜3をデジタル入力に設定します。実は、今回のサンプルではxbee_gpio_initコマンドは不要です。繰り返し処理を開始する前に子機XBeeとの通信をしてみたという程度のものです。
さらに、似たようなコマンドに「xbee_gpio_config」があります。こちらは任意のポートを設定することが出来ます。「xbee_gpio_config( dev_gpio , 1 , DIN )」のように記述すると、子機「dev_gpio」のポート「1」を「DIN(デジタル入力)」に設定します。3項めを「AIN」にするとアナログ入力になります。
setup処理の最後のdelayは時間待ちコマンドです。単位はms(ミリ秒)で、ここでは1000msすなわち1秒間の待ち時間を入れています。
ここからloop処理の説明です。「int」は整数の変数を「作成する」命令です。後に続く「gpi」という変数を作成しています。続く「=」は変数への代入を意味します。後に続く「xbee_gpi」コマンドの結果を変数「gpi」に代入します。
xbee_gpiは親機XBeeが子機XBeeと通信を行って子機XBeeのGPIOからデジタル信号を入力するコマンドです。結果としてデジタル信号のHighレベル(1)かLowレベル(0)かを得ます。もしGPIOが出力やアナログ入力(AIN)に設定されていた場合はデジタル入力(DIN)に切り替えてから取得します。括弧内では、子機のIEEEアドレス「dev_gpio」と子機XBeeのポート番号「1」を指定しています。
なお、このコマンドでデジタル入力に切り替えるということは、前節のxbee_gpio_initは不要だということもお分かりいただけたと思います。
「xbee_adc」は子機XBeeのGPIOポートからアナログ値を入力するコマンドです。ここでは整数の「adc」変数を作成して、「xbee_adc」の結果を代入しています。
「xbee_adc」の括弧内では、子機のIEEEアドレス「dev_gpio」と子機XBeeのポート番号「2」を指定しています。もし、ポートがアナログ入力(AIN)に設定されていなかった場合は、アナログ入力に設定してから取得します。
「xbee_gpo」は子機XBeeのGPIOポートにデジタル値を出力するコマンドです。「xbee_gpo」の括弧内では、子機のIEEEアドレス「dev_gpio」と子機XBeeのポート番号「11」、そして出力値として変数「gpi」を指定しています。変数「gpi」には2行前の「xbee_gpi」で取得したデジタル入力値が代入されていますので、ポート1の入力値と同じ値を別のポート11に出力しています。
以上でサンプルスケッチの説明は終了です。スケッチではXBeeによる通信が行われている部分がコマンドに集約されているので、まるでマイコン本体のGPIOをアクセスしているかのような記述にも見えますが、XBeeライブラリがちゃんと通信を実行して実現してくれているのです。
サンプルスケッチの意味が分かったところで、XBeeのGPIOポートについて説明します。本XBeeライブラリでは、XBeeのポート1〜4と11〜12の6ポートをサポートしています。このうちアナログ入力に使用できるのはポート1〜3の3ポートです。下表はポート番号と、XBeeモジュールのピン番号、主な用途についてまとめた子機XBeeのポート一覧表です。
ポート番号 | XBee IO名 | XBeeピン番号 | DIN | AIN | 出力 | 主な用途
0
| DIO0
| XBee_pin 20 (Cms)
| −
| −
| −
| Commission コミッショニングボタン
| 1
| DIO1
| XBee_pin 19 (AD1)
| ○
| ○
| ○
| 汎用入力用(DIN or AIN)
| 2
| DIO2
| XBee_pin 18 (AD2)
| ○
| ○
| ○
| 汎用入力用(DIN or AIN)
| 3
| DIO3
| XBee_pin 17 (AD3)
| ○
| ○
| ○
| 汎用入力用(DIN or AIN)
| 4
| DIO4
| XBee_pin 16 (RTS)
| ○
| ×
| ○
| 汎用入出力用
| 5
| DIO5
| XBee_pin 15 (Ass)
| −
| −
| −
| ASSOSIATE indication
| 10
| DIO10
| XBee_pin 6 (RSSI)
| −
| −
| −
| RSSI indication (PWM)
| 11
| DIO11
| XBee_pin 7
| ○
| ×
| ○
| 汎用入出力用
| 12
| DIO12
| XBee_pin 4
| ○
| ×
| ○
| 汎用入出力用
| |
表中の「DIN」はデジタル入力、「AIN」はアナログ入力、「出力」はデジタル出力です。ポート0、5、10はXBeeネットワーク接続用の機能が割り当てられています。ポート0のCommissionはペアリングを行うためのコミッショニングボタン用です。ポート5はネットワーク参加状態を示すLED用です。ポート10は電波強度をアナログ出力(PWM出力)する端子です。
前節の表からポート1にスイッチを、ポート2にアナログ入力を、ポート11と12にLEDを接続するハードウェアをブレッドボード上に製作します。
黄色のスイッチはコミッションボタンです。黄色のワイヤーでXBeeの20番ピンに接続されています。また、緑色のボタンは入力用として緑色のワイヤーでポート1(XBee 19番ピン)に接続されています。青色の可変抵抗はアナログ入力用としてポート2(XBee 18番ピン)に青色のワイヤで接続されています。
ポート2の入力値はポート11(XBee 7番ピン)に出力されます。このポートは1kΩの抵抗を経由して緑のボタンの横の緑色のLEDへ出力しています。
赤色のLEDは1秒毎に点灯と消灯を繰り返すLEDです。ポート12(XBee 4番ピン)に接続されています。
親機XBeeを接続したArduinoにスケッチを書き込んむと動作します。一番初めはXBeeのペアリングが必要です。このスケッチではペアリングの制限をしていませんので、何もしなくてもペアリングが実行されて動作します。しかし、一度、他の親機とペアリングしてしまった子機XBeeやペアリングを許可しない設定にしている親機を使用している場合は、コミッショニングボタンによるペアリングが必要です。子機はコミッショニングボタンを4回連続で押下すると過去のペアリング情報が削除されます。親機はコミッショニングボタンを2回連続で押下すると参加の待ち受けを開始します。その間に子機のコミッショニングボタンを1回だけ押すとペアリングが完了します。
ペアリングが完了したら、Arduinoをリセットしてスケッチを再起動すると動作するようになるはずです。場合によっては、親機XBeeや子機XBeeの電源を一度、切ってから再起動しなければつながらない場合もあります。
子機XBeeのポート2(XBee_pin 18)にアナログ出力のセンサーを接続すると、Arduino親機XBeeで、その値を読み取れることがわかると思います。XBeeのアナログ入力は0V〜1.2Vの範囲です。電源電圧の3Vを入力すると正しく動作しなくなってしまいますので必要に応じて分圧して入力します。
アナログ入力はXBee内のADコンバータという機能で実現していますが、ADコンバータは、一般的に抵抗などで分圧した電圧を入力すると値が不安定になります。そういった場合はボルテージフロアと呼ばれるオペアンプを使ったインピーダンス変換回路を挿入します。あまり回路を追加したくない場合は、分圧する抵抗値を下げたり、XBeeの入力端子にコンデンサを追加したり、複数回の読み取りを行うなどをして実力的に使える妥協点を探します。例えば、5回、連続で読みとって、最初の2回のデータは捨てて、残る3回のデータを平均するなどといった手法は良く使われます。
当方のサイトで紹介している回路は、複数回の読み取りには頼らずに、実力的に動作しています。しかし、XBeeモジュールのバラつきやセンサーのインピーダンスのバラつきなどで、安定しない場合も出てくるかもしれませんので、そういった場合は色々と試して改善してください。
ここで紹介したサンプルスケッチ「0(ゼロ)」では子機XBeeへデータを取りに行っています。しかし、子機XBeeは、すぐにデータを応答するとは限りません。例えば、省電力モードで動作している子機は、アクティブ状態(動作)とスリープ状態(停止)を繰り返しています。当然、省エネにすればするほど、スリープ時間が長くなり、データの応答に時間がかかるようになり、結果を親機で受け取ることが出来なくなります。
そこで、XBeeライブラリでは応答値を得るためのコマンドを用意しています。このコマンドは定期的に呼び出します。普段は何も得られない、空呼び出しのコマンドです。しかし、何らかのデータが得られるとMODE値が変化しますので、得られたデータを取り出すことが出来ます。
子機XBeeセンサーなどに対しては、xbee_forceコマンドで子機へ測定開始を指示し、その結果をxbee_rx_callで受信します。XBeeライブラリのサンプルスケッチ2以降は、全て、このような手順でセンサーからの情報を収集しています。詳しくは各サンプルスケッチを見ながら学習してください。
XBeeライブラリには多くの機能が満載されていますが、中にはATコマンドやリモートATコマンドを、直接、使いたい場合もあるかもしれません。そういった場合、親機XBeeに対するローカルATコマンド用にはxbee_atを、子機XBeeに対するリモートATコマンドにはxbee_ratを使用します。例えば、「xbee_at("ATDL0000FFFF");」の記述でローカルの親機XBeeにATコマンドを送ることが出来ます。リモートATコマンドについては、「xbee_at( dev_gpio , "ATDL0000FFFF");」のように子機のアドレス入力が必要です。
XBeeライブラリ用のリファレンスマニュアルも「最新版ダウンロードページ」の中で公開しています。とはいえ、一通りを読んでからスケッチを作成すると、どうしても習得に時間がかかってしまいます。まずは、XBeeライブラリに含まれているサンプルスケッチを改造して作成するのが良いでしょう。どちらかといえば、リファレンスマニュアルは、より複雑な機能を実現したい場合に使っていただくためのものです。
XBeeライブラリは多機能ゆえにメモリー(RAMおよびROMの両方)を多く消費してしまいます。このため、ライブラリの機能を削減できるようにしています。xbee.cppおよびxbee.hで宣言している「#define」の「LITE」、「EASY_GPI」、「EASY_ADC」で機能を削減してメモリの消費を少しだけ軽減することが出来ます。
しかし、子機XBeeの数が10個を超えるような規模のネットワークになるとArduinoでは困難になると思います。そういった場合は子機が孫機を管理する分散処理による対策や、PC用のライブラリを使って親機をパソコンにするなどで対策します。
以上でスケッチの描き方の説明を終了しますが、難しかったと感じられた貴方にだけ、お願いがあります。ぜひとも理解できなかった部分を掲示板やメールで教えていただけないでしょうか。よろしく、お願いいたします。XBeeライブラリを作成したボクがXBeeライブラリを使うことが簡単なのは当然なので、ボク以外の人に使ってもらうのに、どこが難しいのかを捉えることが、なかなか出来ないのです。今のところ、図や表も少ないので、こういった図が欲しいとかでもありがたいです。
← 2.ブレッドボードで作るセンサー 3.絵っ!スケッチを描こう 4.家中どこでも情報表示 →