« 2011年3月6日 - 2011年3月12日 | トップページ | 2011年3月27日 - 2011年4月2日 »

2011年3月20日 - 2011年3月26日の1件の記事

2011年3月25日 (金)

Xbee ZB APIモードにはまる

 モーター制御のついでに、以前試したことのあるXbeeを使って簡単なラジコンを作ろうとXbeeを新しく買ってきたのは良かったが、ラジコンそっちのけで、Xbeeにはまってしまった。

 そもそもは、Xbeeの遠方の子機にコマンドを送る機能(リモートATコマンド)を使って子機のデジタルI/Oを動かしそれでラジコンカーのモーター制御をするつもりだった。Xbeeはシリアルの無線通信の替わりに使うだけなら至極簡単で楽なのだが、少しネットワークっぽくやろうとか、センサー機能をAPIモードで使ってやろうなどと考えると、途端にとんでもなく難しくなる。このAPIモードというのが曲者(くせもの)である。今度も気楽に始めたが、泥沼に足をとられて収拾がつかなくなってしまった。

大きな勘違いをしていた(3/10/2011)
 秋月から買ってきた新しいXbee(ZB)2つをあやうくお釈迦にしてしまうところを、何とかDigi Internationalさんの支援で元へ戻し、不勉強を反省してXbeeをあらためてウェブで真剣に調べ始めた。2年前に較べるとウェブ上にもたくさんXbeeの話題が載っている。読んでいくうち自分が大きな勘違いをしていたことに気がつく。

Xbeezb_2

 最初に買った無印のXbeeはいわゆるOEM仕様といわれるハードウエア規格だけのIEEE802.15.4仕様というチップで、Zigbee規格というのは、ライセンスを支払ってこの上に載せるソフトウエアプロダクトだと思っていた。ところが、今度買ってきたXbeeは、そのZigbee規格を既にファームで持っているシリーズ2だという(このあたりは、次のブログが詳しい。http://todotani.cocolog-nifty.com/blog/2010/12/xbee-f604.html PS3とLinux、電子工作も

 これまでの理解とは大分違う。今度買ってきたシリーズ2のZBはあのZigBeeそのものなのだ。無印のXbeeは、ソフトで、Zigbeeになれるが(正確にはZnet2.5という独自規格らしい)、シリーズ2のXbee ZBは始めからそうなのだ。

 道理で、XbeeユーティリティのX-CTUで、MyAddressが設定できないわけだ。そもそもZBではコーディネーターと、ルーターと、エンドディバイスのファームが違うので、動作中に役割を変えることが出来ない。しかもATモード(透過モード)とAPIモードとでは、ファームウエアからして違うので、ATコマンドで簡単にAPIモードになれない。アドレスも自由に設定できないし、この前設定した16ビットアドレスも存在しない。これは前(無印Xbee)のチップと、同じような形、同一無線規格で、同じユーティリティ(X-CTU)を使っていても全く違うディバイスのようだ。

 つまりシリーズ2のZBは、これまでソフトで実現していたネットワーク的な機能、自律的(ソフトの助けなしに)にネットワークを作り、勝手に省電力する機能がファームウエアに実装されている。要するに賢くなっているのだ。

 しかし、こちらとしてはあまり嬉しくない事態である。単純なラジコンにするには返って面倒になった。でも、調べているうち、親機をCoordinator、子機をEnd deviceにし、送信相手アドレス(64ビットで始めから決まっている)を決めうちしてしまえば、前と同じようなユニキャストの1対1の関係で通信が出来そうだ。ほっと胸をなでおろす。

もうひとつの変換基板(3/12/2011)
 先に2ミリピッチの変換基板に汎用基板をくっつけてXbee基板を作ったが、別のやり方でもうひとつ作った。素直に市販のピッチ変換基板を使えばよいものを、私と同じようなことを考える人は他にもいるとみえて、秋月で売っている2ミリ汎用基板を利用して、Xbeeの変換基板を作った人がいた。( ここはXbeeそのものについても詳しい)

P3123732

 以前、Xbeeのような2ミリピッチのパーツを2.54ミリピッチの汎用基板にそのまま固定することを考えたことがある。汎用基板のピッチと2ミリのピン配列をつらつら眺めていて、10ピンを固定するのは、1ミリのドリル穴を余分に2つ開けるだけで、他はすべて穴を少し広げるだけで固定できそうなことに気づいた(汎用ピッチの4つめは、10.16ミリ、2ミリピッチの5つめ10ミリと0.16ミリずれているだけ)。 実際に図面まで引いて、工作を始める直前、もう一方のXbeeのピン列の間隔が、22ミリと、mil規格と大きくずれることに気がつき、作るのを諦めた。

P3123734_2

 今度の方法はこれのバリエーションだ。2.54ミリピッチのL型ヘッダーピンをうまく利用して2ミリピッチ基板にハンダ付けしている。ただ、もう少し綺麗に出来るような気がしてきた。ウェブの工作法では隣接したランドにまずL型ヘッダーピンを固定してから所定のピンに配線しているが、空いたランドは全く利用せず、L型ヘッダーピンをペンチで細かく曲げて直接2ミリピッチに合せれば、もっとすっきり出来そうだ。早速試してみることにする。

P3123735

 意外にうまくいった。小さなブレッドボードにとりつけてみる。半田付けの部分は少ないが、10箇所で固定されたハンダ付けというものは意外に丈夫で、少し動かしたくらいではびくともしない。これをミニブレッドボードに差して子機とし、一方の変換基板は大き目のブレッドボードに使い、Xbee ZBのテスト基盤は整った。これでループバックテストが開始できる。

ループバック成功(3/13/2011)
 ブロードキャストでのループバックテストはとても遅いと聞いていたので、決めうちアドレスの設定をX-CTUでした。前に書いたように、X-CTUで送り先のXbeeのアドレス64ビットをDH(Destination High Address)とDL(Destination Low Address)で設定する。

 ファームウエアタイプは、一方をCoordinator AT、もう一方をEnd device AT(テストなのでATコマンドモードのまま)に設定すれば、一対一になる。

 ループバックテストの開始。よーし、アドレスを指定しないブロードキャストでテストしたときは飛び飛びだった受信が完全にきれいに返ってくる。2階の踊り場まで持っていく。ふむ、急にエラーが起きる。

P3253740

 今度はエラーが出ると立て続けにエラーになり、また突然復帰する。無印(IEEE802.15.2)のときのようなポチポチエラーが出るのと大分様子が違う。スペック上は、無印Xbeeより、XbeeZBの方が少し到達範囲が広いはずなのだが(30m->40m)、送信範囲は前と同じくらいなようだ。

 とりあえずは、これでループバックもOKとなった。透過(ATコマンド)モードでは、前の状態と同じになった。いよいよこれからAPIフレームの送信である。これまでAPIフレームの受信はセンサーデータの受信で経験済みだが、送信、特にコマンド送出は始めてである。ブレッドボードを片付けて、マイコンのスペースを作る。

APIフレームの送信モニターの制作(3/18/2011)
 やりたいことは、APIモード上のリモートATコマンドの送出だけなのだが、丁度良い機会なので、任意のローカルATコマンドや、メッセージなども送れるXbeeのAPIモニターみたいなものを作ろうと思っている。ウェブ上にはArduinoシールドの商用製品があるようだが、自作例が見当たらない。これを完成させてソースでも公開すれば喜ばれるかもしれない。

 ターゲットは、AVR Mega168を選ぶ。このまえのXbeeロガーはSDカードアクセスがあったのでMega128にしたが、今度はこれほどのチップは要らないだろう。それにMega128は旧製品だ(最近はMega1284が後継らしい。秋月でも売っている)。2年前に作ったXbee電力ロガーのソースを引っ張り出して思い出しながらソースを作っていく。

 開発の途中で思い出した。この前はAPIフレームを最初のうち構造体で定義して開発したがどうしてもうまく動かず、あきらめて配列の番号でデータをアクセスした経緯がある。受信データフレームは一種類なので、これでも余り問題はなかったが、今度の送信フレームはローカルとリモートで違うし、コマンド送出と、データ送出でも違う。構造体を使わないと複雑になって後が大変だ。

 この前の構造体での不具合はその後原因がわかっている。APIフレームがアラインメントを無視している(奇数バイトオフセットに2バイトバイナリのデータが定義されているなど)ので、まともに構造体を定義すると、実際のメモリ上の位置と構造体の定義がずれてしまうためである。

 所長はアセンブラー育ちなのでDSECT(ダミーセクション、物差しのようなもの)を使ったアセンブラーの構造体的プログラミングはいやというほどやった(というより、OSはそれの固まり)が、Cの構造体には、余り慣れていない。しかし少し規模の大きいソフトを開発する時は、この考え方は必須である。是非Cでもマスターしておきたい。しかも今度は複数のフォーマットを持つ構造体だ。腕が鳴る。

 前回の失敗を踏まえて構造体の中の変数はすべて1バイト変数にして定義する。リモートとローカルで大きさの違うところは、久しぶりに教則本を勉強して、共用体(union)をstructにいれて定義する。

 さらに、このフレームはチェックサムが必要なので、あらかじめ大きめの配列を定義しておいて、構造体のポインターをこの配列アドレスに指定しようとした。これでこの構造体は、配列番号でもアクセスが出来るはずだ。しかしこれがどうしてもうまくいかない。2重に定義しているとコンパイラーに怒られる。アセンブラー育ちには、このCのポインターのキャストが今ひとつ理解できていない。

 結局、ウェブを調べまわった結果、staticでは、2重に定義することは不可能とわかる。考えてみたら確かに同じ実体メモリに重複した変数を定義されることをコンパイラーが許すわけがない。mallocを使っても良いがそこまでやることもない。強引にunionで、同じstructの上に配列を定義すれば良いが、これも大げさすぎる。というのでポインターの加減算でやることにした。

 これが、最後までたたった。所定のデータが出来てから計算するチェックサムがどうしても正しく入らない。考えあぐねたあげく、アドレスから中味まですべての変数をprintfして始めて原因がわかった。

uint8_t *adr;   //1バイトづつ動かすポインターの定義
APID    api_d;  //構造体の定義

adr = &api_d + 3;    //3バイト先に進んだつもりだが

これは、構造体api_d の長さ分を3つ加えたことになる!! &が付くので、構造体ではなく、単なるアドレスデータになると考えるのが普通だが、Cでは、&がついても構造体の性格がなくならない。正しくは、

adr = (uint8_t *) &api_d;
adr = adr + 3;

でないといけないと書いて、このあと気がついた。これはC言語の仕様で、&演算子と+の演算子の優先順位の勘違いに過ぎないだけのことだ。+の方が、&より優先順位が高いので、

adr = &api_d + 3; は、adr = &(api_d + 3); になるのだ(前も同じことをやったか)。

さっきのように2行にしなくても

adr = (uint8_t *) &(api_d) + 3;

で、警告も出ずに何事もなく動いた。いくらブランクで空けていても思いはコンパイラーには通じない。やれやれC言語も難しいものだ。

気難しいX-CTUをあやしてAPIモードの設定(3/18/2011) 
 ソフトが出来た。次はXbeeをATモード(透過モード)からAPIモードにする手順だ。ところが、X-CTUが気難しくて、簡単にAPIモードのファームが書けない。色々なところでエラーが出て先に進まない。ウェブにも、「根性で」とか「活入れしながら」という言葉が出るほど、動作が不安定である。当研究所のPCのOSは今となっては古いXPだが一番安定していると考えられるOSでもこんな状況である。

 リセットボタンを長めに何回か押すとうまくいったり、そうかと思うと画面上のエラーアイテムをクリックするだけでX-CTUが異常終了したりする。下手をするとOSを再起動しないとX-CTUも動かなくなる。しかも、異常終了したときに設定していたXbeeは大抵動かなくなるので、例のファーム復活の手順を繰り返す羽目におちいる。

 根気良く、何度もXbeeのファームの復活手順をやらされながら、だましだましX-CTUを動かして、何とか2枚のXbeeの設定を終えた。余り自信はないが、ポイントらしいものが見つかったので、以下にまとめておく。

(0)成功を祈って斎戒沐浴する(冗談である)。

(1)設定の終わったXbeeを違うファームウエアにそのまま書き直すのは止めたほうが良い。大抵エラーが起きて先に進めなくなる。なるべくファームウエア復活の手順から始める。このとき、DTR、RTS、CTSはUARTと接続し、垂れ流しのUARTにはしない(無印はそれでも動くがZBは駄目)

(2)復活のときはModem Configurationタブ で、Always update firmwareのチェックを必ず入れること。しかし、復活手順後は必ずはずしておくこと(ここがポイントか)

(3)また、その前のPC Settingsタブで、Enable APIのチェックも外しておくことを忘れずに。なおPCチェックの通信テストで、XbeeZBがXbee24-Bと出るのはバグである。

(4)さらに回線速度は、9600bpsが一番エラーが少ない、というよりこのあとの手順はこの速度でないとエラーが起きる確率が格段に高い。

(5)Modemの欄に「XB24-ZB」(秋月で買ったXBeeなら)を選び、Function SetからXXXXXX APIなどを選んでWriteを押す。このときXbeeの電源は入れてはいけない。

(6)リセットしろという画面が出るが無視して、Xbeeの電源を入れる。するとリセット要求画面は自然に消えて、勝手にファームを書き込み始める。

(7)No Errorで各設定が出てきたら、必ず、Always update firmwareのチェックをはずし、必要なパラメーターを設定し、Writeボタンを押して書き込む。リセットしろという画面が何度か出るので、今度はリセットボタンを押して先に進む。

(8)これでNo Errorで帰って来て、パラメータが表示されたら、おめでとう。Xbeeは成功裡に設定された。そうでないときは難儀である。エラーを修正してwriteし直しても、うまく行くときもあるが、改善されないことが多い。また、エラーが出ていても読んでみると直っているときもある。最初の(2)に戻ってファームを書き直したほうが精神衛生上安心である。

(9)一旦、XbeeがAPIモードになったら、PCセッティングタブで、APIをenableにしないとエラーになる。Modem Configurationタブでのパラメーター読み書きもこれが必要(ただし、ファーム復活の時は入れてはならない。このあたりも注意)。

(10)パラメーターの書き込み(Write)の前に、一度リセットしてから書き込むとエラーが少ない。いずれにしても、PC SettingタブのCOMテストも何回か押して突然動いたり、エラーが出ても繰り返すとOKになるときがあるので、それこそ「根気」と「根性」を要求される。

なんとかAPIフレームでコマンドが送れたが(3/22/2011)
 両方のXbeeをAPIモードのCoordinatorとEnd deviceにして、出来上がったソースでテストを開始する。ISPケーブルを使ったChaNさんのUARTはISPアダプターを有効にしたまま(書き込みモード)でないと動かないことを忘れていて、最初あせった(気持ち良く忘れていた)が、無事、オープニングメッセージが出た。おおお、Xbeeからデータが送られてきたぞ。うーむ、ヘルスチェックのフレームのようだ。受信側はOKなようだ。いよいよコマンドから送信のテストだ。

Xbeeapi

 まず、ローカルコマンドを打つ。よーし、レスポンスが返ってきた。ふむふむ、ちゃんとしたデータが返っている。良いぞ。まだ16進コードの羅列にすぎないが、間違いなくさっき送ったATコマンドのレスポンスだ。

 次はいよいよ問題のリモートコマンドだ。簡単なATコマンドを送る。返事がない。やった、暫くしてコマンドが返ってきた。残念。「送ったが受け取っていない」という親側のメッセージだった。

Ws000000

 アソシエーションLEDの点滅に変化があるので、親から子へコマンドを送っていることは間違いなさそうだが、まだデータフォーマットなどがおかしいのかもしれない。ただ、APIモードでのループバックテストが動かないのが気になっている。

 このあと、X-CTUでリモートコンフィギュレーションが可能になった。Xbeeのハードやファームは問題なく動いているようだ。ローカルのATコマンドの方は、APIモードで殆ど確実に送れるようになった。しかし、リモートコマンドはがんとして送信失敗のエラーコードで先に進まない。メッセージ送信も出来ない。先が長そうなので、とりあえずはこのあたりでブログに報告することにする。

| | コメント (3) | トラックバック (0)

« 2011年3月6日 - 2011年3月12日 | トップページ | 2011年3月27日 - 2011年4月2日 »