GPSの現在位置をLoRaで送信して距離を測ってみた (Arduino MKR WAN 1310)

TL;DR

LoRa は最大数kmの長距離でセンサデータ等の通信ができるとされている通信方式です。
実際にGPSで取得した現在位置を送信するノードをArduino MKR WAN 1310を使って作成し、都市部(東京23区内)でこれを持ち歩いた時にどのくらいの距離まで通信できるのかを調べてみました。
通信距離はアンテナ設置状況で大きく変わるものです。今回はビルの窓にアンテナを貼り付けた程度の非常に簡易的なセットアップでしたが、それでも800m程度離れた場所でもデータを送信できることを確認できました。
f:id:NeoCat:20220409173351j:plain

LoRa / LoRaWANについて

LoRaは、LPWA(低消費電力・長距離)通信のための方式の1つです。日本では免許不要の920〜928MHz帯を利用して、バッテリーで長時間、センサデータ等の小さいデータを都市部で数km(開けた場所なら数十kmというデータも)の範囲で送信することができるとされています。
LoRaWANという単語の方が有名かもしれませんが、これはLoRaを利用して相互にデータを交換するためのプロトコル(L2)までを規定したものです。LoRaWANを利用した通信網を提供する商用サービスや、コミュニティで運営されているThe Things Network (TTN)もあります。他方、自分のデバイスゲートウェイ間で通信するだけであれば、LoRaWANを用いずに任意のプロトコルで通信することもでき、これはプライベートLoRaと呼ばれます。

参考解説記事: いまさら聞けないLoRaWAN入門:産業用ネットワーク技術解説(1/4 ページ) - MONOist


現実的に都市部でどれくらいの範囲で通信できるのかに興味があったため、GPSの現在位置をLoRaで送信するデバイスを作って試してみることにしました。
実験した場所は残念ながらTTNの圏外だったこともあり、今回はプライベートLoRaを利用しています。

LoRaの通信速度

LoRaでは通信速度や帯域に関して複数のパラメータを選ぶことができ、大きなデータを高速・近距離で通信するか/小さなデータを低速・遠距離で通信するかを調整できます。
日本で使用する場合は電波法・ARIBの規定に従う必要があるので、許可された範囲内で設定する必要があります。

参考: LoRaWANと920MHzのルール - Qiita, LPWAについて考える-標準規格ARIB STD-T108に対する適合性

通信速度の設定は、帯域とSF (Spreading Factor、拡散率)というパラメータで行います。1ch内で通信する場合、使用する帯域は 125kHz です(さらに狭くもできますが遅くなります)。SFは5〜12が設定でき、数値が大きいほどデータを「ゆっくり」送信することになります。SFが大きいほど遠くまで通信できます。LoRaWAN等ではよくSF=10が使われているようです。SEMTECH社のLoRa Calculatorというツールで計算してみると、12byteのデータを送信するのにかかる時間は、SFによって以下のように変わります。*1

SF 5 6 7 8 9 10 11 12
帯域125kHzでの送信時間(ms) 13 23 45 80 160 280 561 1,122

ARIBでは1回の送信時間を最大4秒( ch24〜38、キャリアセンス 5ms ) または 400ms ( ch33〜61、キャリアセンス 128μs、休止時間 送信時間の10倍以上 ) と定めています。SF=10で400msに収める場合、送信可能なデータサイズは 22byte です。チャンネルによっては休止時間もおく必要があり、省電力利用も考えるとこの程度のサイズを1分に1回未満といった送信頻度で送るというのがLoRaの現実的な使い方と思います。(もちろん至近距離で高速通信もできますが、それならBluetoothWiFi等の方が普及していますし *2 )

LoRaで現在位置を送信するGPSモジュールを作ってみた

ハードウェア構成

LoRaを搭載したボードとして、Arduino MKR WAN 1310 を使用しました。Arduinoが公式サポートしているため開発も簡単です。CPUアーキテクチャはARM Cortex-M0です。
www.switch-science.com
対応した下記アンテナとセットで技適も取得されています。
GSM用ダイポールアンテナ(Arduino MKR WAN 1310用) - スイッチサイエンス

これを2セット購入しました。一方はGPSを繋いでバッテリー動作の可搬送信ノードとし、もう一方は固定してゲートウェイとして使います。
ノードからはGPSのデータを30秒に1度送信し、ゲートウェイ側はで受信成功したらACKを返すようにします。*3

ノード側のハードウェア構成はこんな感じです。
f:id:NeoCat:20220409164551p:plain:w750
8.5 × 6 × 4cmのケースに入れてこんな外観。
f:id:NeoCat:20220409174820j:plain:w300


Arduino以外のパーツはこの辺りです:
M5Stack用GPSユニット
I2C OLEDディスプレイモジュール
タカチ電機工業 SW型プラスチックケース SW-85B

ソフトウェア構成

ソフトウェアは、 Arduino IDE で書いていきます。PCに Arduino MKR WAN 1310 をUSB接続してIDEを起動すると、自動的に認識してMKR WAN用のパッケージを追加してくださいという表示が出るので、これに従って追加します。
f:id:NeoCat:20220409164522p:plain:w500

Arduino用に LoRa というライブラリがあるので、これをライブラリマネージャで導入します。
f:id:NeoCat:20220409164952p:plain:w400
スケッチ例に追加される LoRaSimpleNode というサンプルコードがあるので、これをベースにして作っていきます。
サンプルでは海外用の周波数が指定されているので、忘れずに国内の周波数を設定します。今回は 923.0MHz (ch.36) を利用しました。 ( E というのは指数表記です。 923e6 の方が馴染み深い? )

const long frequency = 923E6;  // LoRa Frequency
...
  LoRa.begin(frequency);

GPSユニットはシリアルでNMEA形式でデータを出力してくるので、1310のGPIO 13/14 (RX/TX) で受けます。これらのピンはArduinoのコード上では Serial1 と書けば利用できます。なお普通の Serial はUSBシリアルを指します。
GPS用のライブラリには TinyGPSPlus をライブラリマネージャから導入して使用しました。シリアルで受け取ったデータをそのままライブラリに渡すだけで、簡単に時刻や現在位置、捕捉している衛星数を取り出したりできます。

現在地を送出したら、後述するACK受信を1秒だけ待って、ArduinoLowPowerライブラリを使って30秒間スリープさせます。(今回GPSをうまくスリープに入れられず動かしっぱなしですが…)
送信するデータサイズは 11 バイト (緯度4byte, 経度4byte, 測位衛星数 1byte, 暗号IVの一部 2byte)で、送信所要時間はSF=10で280msでした。

また、LoRaWANでは暗号化方式も含まれていますが、素の LoRa では暗号化などは一切されないので、一応暗号化もしておきます。MKR WAN 1310にはセキュアエレメントも乗っているので、これを使って公開鍵暗号を掛けることもできます。が、それだとペイロードが大きくなってしまうので、今回はストリーム暗号であるChaChaを使用しました。これもライブラリ Arduino Crypto を使えば簡単です。ただし、これは覗き見防止程度の意味であり、送信元の保証やデータ改変への耐性はありません。別途 ArduinoECCX08 ライブラリも利用しています*4

ついでにOLEDディスプレイにも送信状況を表示します。


ゲートウェイ側のハードウェアはシンプルで、もう一台のMKR WAN 1310をPCにUSB接続してアンテナを繋ぐだけです。サンプルスケッチ LoRaSimpleGateway をベースに、受信したデータを復号してシリアルに出力するようにします。また受信したRSSIを含めてACKを送信します。


今回使ったコードのサンプルは下記にあります。 ※ 細かいMKR WAN 1310の機能等については別記事にします。
https://gist.github.com/NeoCat/3c77ecdb19b9479228f6b2a09c64bb1e

到達距離は?

ゲートウェイのアンテナを東京23区内の某ビルの10階くらいの高さの窓に貼り付け、ノードを持って街中の道を歩き回って通信可能な距離を測ってみました。
結果ですが、最大 800m 離れた地点で正常に現在地を送信できました(ただしこの時ACKは受け取れず)。入り組んだ路地のため、アンテナ同士は直接見通せない状況でしたが、間の建物などを迂回して到達できたようです。ただし場所によってかなりバラつき、距離的には300m程度でも通信できない場所もありました。LoRaでは16bitのCRCをつけるかを選べますが、CRC無効にしていると距離が離れるに従って一部のbitが化けたパケットを受け取ることもありました。

やはりアンテナの設置場所の見通しに非常に大きく依存して変わる印象です。互いの間の空間が広く空いているところなら距離はかなり伸びますし、少しくらいなら建物の影に入っても屋根なり壁なりを迂回して到達するようですが、間に建物ががっつり挟まると距離が一気に短くなるようでした。

今回は簡単なセットアップでどのくらい到達できるのか?に興味があったので、敢えて最大距離を追い求めることはしていませんが、一つの目安になる数値は得られたかなと思います。

*1:ヘッダなし、CRCあり、CodeRate 4/5の場合。なおLoRaWANではさらにプロトコルのヘッダ等がつく分通信時間も長くなります

*2:一方でさらに広域だと費用はかかるものの4G/5Gの利用になるのでピッタリはまるアプリケーションが狭いのがLoRaが注目されにくい所以かなという気がします

*3:ACKは相互通信してみたかったのと単に受信されたかをノード側でも見られるようにするためのおまけ要素です。

*4: ivを毎回変えるためだけにセキュアエレメントの乱数生成器を使っています。詳しくは別記事で説明しています