LoRaの通信波形をSDRで見てみた

前の記事で作成したGPSノードの通信の波形を、SDR (Software Defined Radio)で捉えて可視化してみました。
neocat.hatenablog.com


SDRの受信にはRTL2832Uなどのチップを積んだ安価なUSB TVチューナーなどが使えます。

が、今回は HackRF One を使用しました。
HackRF One + Portapack H2

受信ソフトウェアはMacで簡単に使える gqrx を使います。

まずインストールは Homebrew

brew install gqrx

でOK。アプリケーションフォルダに通常のアプリケーションとしてインストールされます。HackRF One を接続した状態で起動すると、デバイスにHackRF Oneが現れるので、選択して起動します。キャプチャのサンプルレートが選べますが、16000000 (16MHz) にしておきました。

起動したら、今回使用した周波数である923MHzを入力してチューニングします。下図ではピッタリに合わせていますが、このままだと真ん中に強いピークが出てしまうので、右のReceiver Optionsの方に1000 kHzくらいを入力してハードウェア周波数を922MHzなどにずらした方が良さそうです。

この状態で通信をすると、上図のようにFFTのところに赤いピークが現れます。が、このままだと荒すぎて波形は見れません。そこで、データを書き出して別のソフトで可視化を行なってみます。
メニューから Tools > I/Q recorder を開き、適当なディレクトリを指定して、通信の直前に Rec を押し、通信後に止めます。これで生データがファイル出力されます。数秒の Rec で数100MBから1GB程度のファイルが出力されるので注意してください。

可視化には inspectrum を使います。同じく brew でインストールし、コマンドラインから起動します。

brew install inspectrum
inspectrum

ウィンドウが開くので、 Sample rate を今回使用した 16000000 を入力し、 Open file で gqrx で出力したファイルを指定します。
すると、巨大な画像が表示されますので、横軸(秒)と周波数(今回だと 1000 kHz ずらして撮っているのでその付近)を参考に、スクロールしていくと、波形が見つかるはずです。Zoomや色付けするPowerを調整してやると、こんな感じでLoRaの通信波形が描画できました。

LoRaの通信波形

左側がGPSノードからのデータ送信、右側がゲートウェイからのACK送信です。(ゲートウェイの至近でキャプチャしたため、ゲートウェイ側の信号が強くて描画が荒れてしまっていますが…)

LoRa変調ではCSS(Chirp Spread Spectrum)、チャープスペクトラム拡散と呼ばれる方式を利用しています。使う帯域(今回は125kHz)分の周波数にわたって低い方から高い方に連続的に周波数をスイープさせているのが見てとれますね。これにより途中でノイズや受信できない周波数などがあっても影響を受けにくくなっています。
ノードからの送信では、最初に最低→最高までのスイープの繰り返しが10回あり、最高→最低に反転して2回繰り返しています。1つの繰り返しが1つのシンボルになります。ここまでの部分はプリアンプルで、受信側と同期を取るためにあります。
そこから先に少し複雑なパターンが現れますが、これはデータの数ビット分に応じて、シンボルのスイープの開始位置をずらすという符号化を行なっているものです。
例えば2bit、4通りの値を1シンボルで送るとすると、以下の4つのいずれかを送ることで 0, 1, 2, 3を表すことになります。
(Signals 2022より引用)

前の記事で SF によって送信速度/感度を調整できると書きましたが、この SF が1シンボルで送るbit数に相当します。SF=10であれば、1024通りのパターンを送るということになります。加えて、SFが1増えるごとに、1シンボルにかける時間を2倍にします。後者の方が通信時間に対する影響が大きいため、SFが1上がると概ねビットレートは半分ということになります*1。ゆっくり送信した場合の方が情報あたりの合計電力が上がりノイズ耐性が改善しますので、SFを上げることで通信距離が広げられるというわけですね。

ゲートウェイからの送信時は、スイープの方向が逆転しています。これはスケッチ中にあった

  LoRa.enableInvertIQ();                // active invert I and Q signals

という指定の効果で、ノードはゲートウェイからの通信のみを受信、ゲートウェイはノードからの通信のみを受信するために区別をつけるための機能です。

*1:例えばSF 9→10の場合、同一のデータ部分の送信にかかる時間は単純計算で 2*9/10 = 1.8倍 になります。プリアンプルなどデータの乗らない部分はそのまま2倍長くなるのでさらに2倍に近づきます。