zigbee無線で距離を測った。
moxaの無線は出力を変える事ができる。これを利用して、サンプルプログラムの中にあった距離が近づいたらLEDが点灯する奴を改造し、
・複数nodeをID識別
・距離の計測の高速化
を行った。
1つのanchorと複数のnodeとの間の距離を取る。たくさんプログラムを書きこむ羽目になるのでUSBハブが無いと大変。

■しくみ
徐々に電波強度を上げていくと、「最も弱い出力で受信できた時」を距離とする事ができる。
電波強度は、無線通信のデータ本文に数値として含めておいて、受信側で文字列をparseして読み出す。
moxaはマイコン上でECMAScriptが使えるので、Stringを分解したり、Object型インスタンスに何でも突っ込んだり、配列に溜めたりするのが楽に出来るので通信プロトコルを作るのが楽だった。
■nodeのプログラム
徐々に電波強度を上げながらanchorに無線を送り続ける
node/source.js
var radio = new Object();
radio.id = 2; // id:2以降がnode
radio.group = 7;
var time = 1;
var power_borders = new Array();
power_borders = [1,2,3,4,11,12,13,30,31]; // 距離の境目リスト
function loop() {
dist_send();
}
function dist_send(){
for(p in power_borders){ // power
radioInit(0xDEAD, radio.id, radio.group, p);
message = "power:"+p+",time:"+time;
radioSend(0xFFFF, message);
sleep(1);
}
time++;
}
function sleep(count){
for(var i = 0; i < count*10; i++){
}
}
while(true){
loop();
}
■プロトコル
powerを1から徐々に上げながら送信する。
“power:2,time:15”
“power:3,time:15”
“power:4,time:15”
という風にtimeという変数も合わせて送る事で、1セット分の無線送信試行を表している。
■距離の境目
実際にはpowerと無線の飛距離は正比例していなくて、簡単に調べた所
・power 4ぐらい → 4メートル以内ぐらい
・power 10前後 → 5~15メートルぐらい
・power 20前後 → 15~30メートルぐらい
・power 30前後 → それ以上
となっていた。なので、その境目あたりを重点的に送信するために
power_borders = [1,2,3,4,11,12,13,30,31]; // 距離の境目リスト
を使った。こうすると1から最大31まで全powerを試す必要が無くなり、3倍ぐらい速くなっても精度はあまり落ちない。
■anchorのプログラム
nodeからの最低出力で受信できた時のpowerを本文から取り出し、nodeのID毎に配列に保存しておく。
anchor/source.js
var radio = new Object();
radio.id = 1; // nodeはid:2以降
radio.group = 7;
var dist = new Object();
dist.lastTime = 0;
dist.lastPower = 0;
nodes = new Array(16);
nodes_init(nodes);
serialInit(9600);
radioInit(0xDEAD, radio.id, radio.group, 31);
function loop(){
}
function onRadioReceive(seq,id,pan,data,rss) {
if(id < 2) return; // nodeからではない時
commands = data.split(",");
for(c in commands){
tmp = c.split(":");
if(tmp[0] == "power") distance = tmp[1];
if(tmp[0] == "time") time = tmp[1];
}
if(nodes[id].lastTime != time){ // 新しいデータの時
nodes[id].distance = distance;
// nodeのidと距離を出力
serialSend("id:"+id+",distance:"+distance+",time:"+time+"¥r¥n");
}
nodes[id].lastTime = time;
}
function nodes_init(nodes){
for(i = 1; i < nodes.length; i++){
var node = new Object();
node.lastTime = 0;
node.distance = 0;
node.id = i;
nodes[i] = node;
}
}
function sleep(count){
for(var i = 0; i < count*10; i++){
}
}
while(true){
loop();
}
■無線データの受信と解析
onRadioReceive(seq,id,pan,data,rss) という関数を宣言すると無線を受信できる。
こういうデータが来るので
“power:3,time:15”
splitで : と , を分けて、nodeオブジェクトに保存する。
commands = data.split(",");
for(c in commands){
tmp = c.split(":");
if(tmp[0] == "power") distance = tmp[1];
if(tmp[0] == "time") time = tmp[1];
}
また、引数 id に送信元のIDが入っているので、あわせて保存しておく。
■シリアルポートに出力
今回はanchorからパソコンにシリアル通信で出力した。
id:2,distance:10,time:18\r\n
id:6,distance:3,time:11\r\n
id:7,distance:13,time:7\r\n
こんな感じの文字列がきて、anchorとnodeの間の距離、IDがわかる。

ちなみに、node側でさらにボタンの押下状態なんかも付けられる。
felicalibとC#用ラッパーを使ってFelicaのIDを読んだ。
参考:felicalib C#での利用方法

MNPして使わなくなった(財布機能1回も使ってない)auのお財布ケータイW51Sを乗せたところ。
普段使ってるSuicaを読むと違うIDが出てきた。
■作ったもの
080811_Felica.zip (VisualStudio2008 / C#3.0)
.NET Framework3.5が必要
■準備
RC-S320を使った。付属のCDからドライバだけインストールしておく。
売り上げランキング: 99

あれば便利かもしれないが、無くても困らない製品
便利アイテムです
便利です。
飛行機に乗れなくてもマイルが貯まる
edyを常用してる人ならお勧めfelicalibをダウンロードしてくる。中にC#用ラッパー(FelicaLib.cs)も入っているので自分のプロジェクトに追加。
felicalib.dllは「参照の追加」から使うのではなく、bin/Debug, bin/Releaseなどにファイルを直接コピペして置く。実行時にFelicaLib.csからP/Invokeで読み込まれる。
■コード
ラッパーを読み込んで
using FelicaLib;
IDmを読むとbyte配列が来るので、Stringに直す。
try
{
using (Felica felica = new Felica())
{
felica.Polling(0xFFFF);
byte[] data = felica.IDm();
String id = "";
for (int i = 0; i < data.Length; i++)
{
id += data[i].ToString("X2");
}
Console.WriteLine(id); // ID出力
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
基本はUSB給電だが、内部にレギュレータがあるので9V電池をそのまま接続するだけで使えるようになる。

■電源ケーブルを付け直す
上の写真にもある赤いケーブルが、PCのUSB端子からの5V給電をmoxaのレギュレータに送る役目をしている。
(上の写真では既に付け直した後だが)最初は基盤裏側に付けてあるのだけど、今回は下方向にピンヘッダを付けたかったので基盤表側につけなおした
基盤裏のピンヘッダ。赤い電源ケーブルははんだごてを当てながら抜けば簡単に外せる

表側に付け直した。

この状態で、まずは一回moxa基盤そのものがパソコンから認識できるかどうか確かめたりしておいた方が良い。電源まわりはバグの元なので。
■9V電池を接続する
図のように接続する。9Vのプラスとマイナスを間違えないように注意。

外部にセンサーなどを接続する時は、右の3.3V出力を利用する。左側のUSBからの5V出力は当然動いていないので使えない。
あと、左側にもGNDがあるのでうまく利用すると良いかも。
今回作った基盤は裏から見るとこうなっている。電池からの給電をON/OFFするスイッチを、電池+→VIN間に付けた。


