秋月などにも売っている CLEALINK の E220-900T22S(JP) という LoRa モジュールを透過(≒ ケーブル接続)ではなく固定(相手を選んで通信)モードで試す機会がありましたので書き留めておこうかな、と。
そもそも大量のデータを送る規格ではありませんので用途は限定されるハズ。 私は 1:n とか n:1 とかで物理量や状態をやりとりすることが目的なのでアドレスやチャネルを指定できる固定モードで使うことになりますが、当該モジュールの記事はちょくちょく見かけますけど透過モードで届いたの届かないだのという記事しか私には見つけられませんでした。
しょうがないのでマニュアル見ながら try & error で試してみました、というのが今回の内容です。
以下続く、…
ここまで書いた後で E220 の新しい取説が出ていることに気づいて落として読んでみましたらば …
初版と全く違ってて私が知りたかったけどよく分からないので実際にちょちょこやってみる羽目になったあれこれがとても丁寧に網羅されてまして、…
これ読めば分かるじゃん
ということになりました。 皆さま、新しい取説を お読みください。 以上。
何もないのも あんまりですので今回の私の事例の具体的なハナシだけ少し紹介しておきます。
要件: センサや電圧などを計測した 12 or 16 bit の A/D 出力データを 11 項目バイナリのまま送る
トポロジは 1:n で、E220 の設定は
/*
送信側の設定
項目として (xxx/www/vvv/... 計測データ 11 項目) を
各々 2bytes とし 22 bytes、に target addrss/ch/byte count の 4 bytes を
加えた 26 bytes が 全 data になる。 ので 400ms 以内で送れてかつ感度も
稼げる bw/sf = 125kHz/9 と 送信よりも早く書き込めそうな uart bps = 9600 を
設定する。
*/
byte newSettingTx[11] = {0xC0, 0x00, 0x08,
0x00, 0x0B, // my address = 11(dec) からの通し、送受混合
0x70, // data rate 011xxxxx: 9600|xxx10000: 1758bps/9/125kHz
0x81, // parcel=64: 10x---xx|noise=off: xx0---xx|txpow=13: xxx---01
0x0B, // my channel = 11(dec) で送信側は統一
0x43, // apnd rssi=no: 0xx---xxx|tx=fix: x1---xxx|wor=xx---011(de)
0x00, 0x00}; // encrypt=00(de)
/*
受信側の設定
送信側と異なるところは 自機アドレスが 11 + n になっていることと
自機チャネルが送信側に合わせて 16 .. 37 からの選択になっていること、
受信 rssi を パケットの最後尾に付加すること。
ただし、データ受信解析プログラム実行中に動的には変更できないので
受信側ドングルは RS232C テストツール等で修正が必要。
*/
byte newSettingRx[11] = {0xC0, 0x00, 0x08,
0x00, 0x0c, // my address = 11(dec) からの通し、送受混合
0x70, // data rate 011xxxxx: 9600|xxx10000: 1758bps/9/125kHz
0x81, // parcel=64: 10x---xx|noise=off: xx0---xx|txpow=13: xxx---01
0x11, // channel #: 16..37(dec) を適宜、その ch に送信
0xc3, // apnd rssi=yes: 1xx---xxx|tx=fix: x1---xxx|wor=xx---011(de)
0x00, 0x00}; // encrypt=00(de)
という感じ。 これで E220 をモード 3 にして設定を書き込んでおきます。
たぶん、一番分かりづらいのがここ、かと思いますので補足しておくと、
・ LoRa は送信データ量に強い制限がある
・ チャネルというのは自機が受信するときのもの
・ 送信側は自機のチャネル設定とは無関係なチャネルで送信する
・ 自機アドレスは一意(電波が届く範囲で)
・ チャネルは送信側の台数やペイロードで大体絞られる
というあたりを注意すればいい、かと思いますので先ずはトポロジや送受の台数やデータ量を書き出すと判断しやすい、かと。
CLEALINK のサイトに条件に関する表が何枚か置いてあり、それらを同時に見なくてはなりませんが数字の意味を考えれば何となく「この範囲なら」が見えてくる(まで資料を読めば何とかなる)でしょう。
この設定が決まれば後はそれに添ってプログラムを書くだけです。
最終的に送り出すデータ配列と計測データの配列は次のように宣言しました。
#define bSize 64
char txBuf[bSize]; // opposite.addr(2) +ch(1) +bytecount(1) +terminator (1)
#define iNum 11
union payloadU {
uint16_t item[iNum]; // terminator(1)
char buffer[2 * iNum];
} payload;
バイナリデータなので +terminator の 1 バイトは意味がないんですが習慣で。 ww
さて、アドレスやチャネルなどのプリアンブル部分は固定ですから setup() の中で
// 無線側 preamble の設定
txBuf[0] = 0xff; // destination address : $FFFF は broadcast
txBuf[1] = 0xff;
txBuf[2] = 0x11; // 放送チャネルは 0x11(#17)
というふうに書いておきます。
構造体の中にプリアンブル配列と計測データの共用体を書けばソフトウェア的には すっきりするかもですけれどコンパイラが境界を正しく処理しない可能性があるので止めたほうがいいです。
さて loop() の中で、一連の計測をしてデータを配列に書き込んだら
// 結果を送信する
uint8_t bcc = 0; // 成り行きで書いてしまったけど残してある(ww
int n;
int i = 0;
int j = 3; // tBuf[0..1]: opposite addr, tBuf[2]: dest. channel
txBuf[j++] = n; // tBuf[3]: bytecount
while (0 < n){
if (i == 0){
bcc = payload.buffer[i]; else bcc = bcc ^ payload.buffer[i];
}
txBuf[j++] = payload.buffer[i++];
n--;
}
Serial1.write(txBuf, j); // これが e220 への送信依頼
Serial1.flush();
で okay です。 ザッとですけれどこんな感じで使えてます。
今回はこのくらいで。