SDR で ETC の電波を受信しよう (フィールドワーク編)

[さくらインターネット Advent Calendar 2020](https://qiita.com/advent-calendar/2020/sakura) 22 日目の記事です。
当記事は [@chibiegg](https://qiita.com/chibiegg) さんとの合作で、さくらインターネット社内サークル「インフラ研究会」の支援の下執筆されています。

後編（デコード編）は[こちら](https://qiita.com/chibiegg/items/35f60ee8d4551905f603#_reference-a2161f8c4cf99fae745b)です。

# 概要

- [ETC (高速道路電子料金収受システム) ](https://ja.wikipedia.org/wiki/ETC) の通信に用いられる規格は、5.8GHz 帯の電波を用いた [ARIB STD-T75 DSRC (狭域通信) システム](https://www.arib.or.jp/kikaku/kikaku_tushin/std-t75.html) として、一般に仕様が公開されているものです。

- 市販のソフトウェア無線機 [HackRF One](https://greatscottgadgets.com/hackrf/) を設置した自動車でゲートを通過し、車載器と地上局との間で行われる通信を受信してみます。その際のテクニックを測定環境づくり（フィールドワーク編）とデータ解析（デコード編）２編に分けてご紹介します。

- 【注意事項】当記事は公開されている無線方式や規格を学習しやすくするための解説、および測定に用いられる機材の取り扱いノウハウを記述するものであり、検証に伴って取得された通信の内容そのものは含めません。ETC システムは通常 [ETCシステム利用規程](https://www.go-etc.jp/kitei/saisoku.html) に従って ETC カードの貸与を受けて利用するものであり、その通信はシステムの構成要素同士での内部的な通信と思われます。よって、その通信に含まれる情報を利用者が無断で公開したり、その情報を窃用し何らかの便益を得ることは違法となる可能性があるためです（[Wikipedia - 傍受](https://ja.wikipedia.org/wiki/%E5%82%8D%E5%8F%97)）。

# ソフトウェア無線機とそのセットアップ

## 必要な測定環境

ETC システムは日本の高速道路料金所のゲートに設置されており、利用者は自動車に設置された ETC 車載機に ETC カードをあらかじめ挿入してゲートを通過するだけで、ノンストップで料金の支払いが完了する便利なシステムです。これはゲートに設置されたアンテナ（地上局）とETC 車載機（移動局）の間で、5.8GHz 帯の無線通信が瞬時に行われることによって動作します。この無線通信は [ARIB STD-T75 DSRC (狭域通信) システム](https://www.arib.or.jp/kikaku/kikaku_tushin/std-t75.html) として、一般に仕様が公開されているものです。特に英語版は無料で誰でもダウンロードすることができます。

ETC 地上局では他の無線局との混信を防ぐために指向性の高いアンテナが使われており、その指向性は [専用測定機材(Micronix ME9200)の測定例](http://www.micronix-jp.com/products/etc/me9200.html#Example) などによれば、料金所での進行方向約 5m の範囲を外れると30dB - 40dB 程度減衰するほどです。この通信を観測するとなれば、一般利用者としてはゲートを通過する自動車内に受信機を設置して通過の瞬間を捕らえる他なさそうです。

無線通信に用いられる周波数は、 ETC では下り方向（地上局から移動局）5795MHz および 5805MHz、上り方向 5835MHz および 5845 MHz です。また、基本的なプロファイルとなる ASK 方式においては 1024kbps スプリットフェーズ符号（いわゆるマンチェスタ符号）によって変調されており、占有する帯域幅は 4MHz 程度になります。

よって、5.8GHz 帯に中心周波数を合わせられるもののうち、上り下りを合わせて60MHz の範囲を一気に観測できる受信機(60Msamples/s 以上）1台で一気に観測を行うか、5MHz程度の範囲を観測できる受信機を上り下り両チャネルに合わせて別々に観測するか、そのどちらかが望ましいでしょう。

## HackRF One の使用

市販されているソフトウエア無線機（Software Defined Radio）で 5GHz 帯を受信できる機材は限られていますし、その中でもサンプリングレートが高速なものはさらに入手困難となります。その中でも入手が比較的容易なものとして [HackRF One](https://greatscottgadgets.com/hackrf/one/) があり、20Msamples/s の性能を持っていることから、最大で 20MHz の範囲を一度に観測することができます。そこで、これを 2 台用意し、上り用と下り用に割り当てることで、双方向の通信を別々にキャプチャすることとしました。

量子化ビット数は I/Q チャネルそれぞれ 8 bit 256 階調あり、RF 入力に内蔵されたアンプ(LNA)のゲインを0dB ～ 40dB の範囲で調整することができるものです。

## 5G 帯を受信するときの工夫

- ETC 車載機用アンテナの使用

ETC 地上局からの電波は反射波の影響を抑え直接波を強調して受信できるよう、右旋円偏波での送信が行われています。円偏波には直線偏波成分を含むわけですから、HackRF One とよく組み合わされるロッドアンテナを使用しても受信自体は行えるはずですが、折角なのでできるだけ本物の環境に近づけます。

![patch_antenna.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216085/3a65a5d7-c982-a1fe-4062-26683266aaea.jpeg)

筆者の環境では、ジャンクパーツのETC 車載機からパッチアンテナを取り出して使用しました。機種によって異なると思われますが、筆者の環境で入手したものは同軸ケーブルの芯線とシールド（GND)の間が数センチ角のプリント基板上のパターンで接続された構造でした。これを HackRF One の SMA ジャックと適合させるため、SMA プラグに適宜はんだ付けで固定しました。

なお、ETC 車載機アンテナによっては動作を示すランプとしてアンテナに LED と電流制限抵抗が装着されていることがあるようです。例えば筆者の環境では芯線に 3.3V を印加することでこれが光りました。特にアンテナとしての動作に必要ではなさそうですが、導通確認として使うこともできるでしょう。

- ノイズ対策の実施

HackRF One に ETC アンテナを付けただけの状態では、帯域全てに大きなノイズが乗り、地上局から数十メートル離れた位置でも下図のようなノイズが観測されてしまいます。ゲートから十分に離れるとこのノイズは観測されなくなりますので、マルチパスした反射波などが原因と推測しています。

![noise.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216085/dc6279a7-a8e0-788c-745d-ab562cebe516.png)

この時 HackRF One の LNA は 40dB に設定されており、このノイズの大きさはもし正しく信号が検出されたとしてもそのデコードに影響を与えそうです。後に出てきますが、信号検出には 40dB の LNA 設定だけでは足りず、外付けの RF アンプを併用していますので、できるだけノイズを抑えたいところです。

![hackrf.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216085/b8abd7cd-3608-6e9b-781f-3ba07162a58f.jpeg)

今回、HackRF One 本体をアルミホイルで巻き、5.8 GHz 帯だけを通過させるバンドパスフィルタを挿入することによってノイズの有意な低減が得られました。恐らくは、筐体がプラスチック製でシールドされていないことから、内部基板の金属部分などがアンテナとして働きノイズを受信したのではないかと考えています。アルミホイルで機材を巻く際は、十分に端を巻き込んでシールド効果を高めるようにするとよいようです。

また、5.8 GHz 帯電波は競技用ドローンなどの無線通信にも使われる電波のようで、今回必要な周波数帯をカバーするインライン型のフィルタが比較的廉価に入手できました。但し、コネクタが RP-SMA のため、SMA コネクタとの接続には変換アダプタが必要です。

![filter.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216085/eb8c418b-9ddc-ceb6-d941-4fa8b56e2703.jpeg)

製品仕様 : [https://www.taoglas.com/product/airvu-bpf-58-5-8ghz-band-pass-filter/](https://www.taoglas.com/product/airvu-bpf-58-5-8ghz-band-pass-filter/)

- アンプの使用

HackRF One は5GHz など高周波数帯において得られるゲインが低く、同様の機材である PlutoSDR の方が同条件でもかなり高い受信感度を持つようです。（参考：[https://twitter.com/0xC5E3/status/901086300241088512](https://twitter.com/0xC5E3/status/901086300241088512) ）一方、本来 PlutoSDR は 3.8GHz までの動作であり、一部の初期ロットで AD9364 チップがコアに使用されているものだけが 6GHz までの範囲を使用できるとの事であり、初期ロットを選んで入手することは現実的とは言えません。( 参考 : [https://wiki.analog.com/university/tools/pluto/users/customizing#updating_to_the_ad9364](https://wiki.analog.com/university/tools/pluto/users/customizing#updating_to_the_ad9364) )

低周波数帯において同様の性能を持っていながら、高周波数帯のみで受信性能が変わる原因は不明ですが、内蔵の LNA が高周波数帯においてゲインが低かったり、何らか高周波数帯を減衰させてしまう構造上の制約があると仮定しました。その場合、場当たり的な対処ですが外部に RF アンプを置いて増幅することで信号レベル向上を得ることができるでしょう。

今回使ったRF アンプは [Qorvo SBB5089Z](https://www.mouser.jp/datasheet/2/412/SBB5089Z_Data_Sheet-1499104.pdf) を使用したもので、6000MHz における典型値として 15.5dB のゲインを持っていることがデータシートに記されています。実際に 5GHz 帯のWifi を測定したところ、概ねスペック通りの増幅が得られました。

![amplifier.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216085/e9042e2c-32b0-ff84-aa27-17439cdaff35.jpeg)

- アンテナ設置

ETC 車載機のパッチアンテナは、乗用車フロントウインドウの上部にフロントガラスの傾斜に合わせて設置されているものを良く見ます。これは自動車フロントガラスに設置することを許可された装置であるためです。（参考：[フロントガラスに取り付けてよいもの - 平成29年6月22日改正](https://life-support24h.com/glass-replacement/windshield-business-trip-exchange/amendments)）

今回の測定用アンテナはダッシュボードなどの上に角度をフロントガラス同様の角度をつけ、運転席からの視野を遮ることのないように設置するのがよいでしょう。（参考：[道路運送車両の保安基準 21 条](https://www.mlit.go.jp/jidosha/jidosha_fr7_000007.html)）

地上局からの下り通信方向と移動局からの上り通信方向ではアンテナからの距離・送信出力が異なります。外付けアンプの使用有無、HackRF One 内蔵の LNA の調節は上り下りで別々に行う必要があるでしょう。

## 受信ソフトウェア

- 性能について

デコード編で詳細記載予定ですが、現状 10Msamples/s やそれを超える速度でのデータをリアルタイムデコードすることは個人レベルで手に入る PC 機材では困難と思われます。（現在、10Msps チャンネルの1秒分のデータをデコードするのに AMD Ryzen 5 3600 デスクトップの環境で 20 秒程度を要します）

そこで、車上では一旦生データの記録のみを行い、後でオフライン解析という方式をとります。一方、ここで問題になるのはデータの生成速度です。今回記録に使用したソフトウェア GNU Radio の保存形式は I/Q チャネルそれぞれ Float32 の形式ですので、1 サンプルあたり8バイトのデータが生成されます。これが 20Msamples/s で駆動する場合、少なくとも160MBytes/sの書き込みが発生し、これに耐える処理性能とストレージの性能、空き容量が必要となります。

筆者の環境（Core i5-2540M 2.6GHz / SATA SSD 240G (１スレッドの Sequential Write 172MBytes/s 程度)) の環境においては、20Msamples/s の場合は大量に、10Msamples/s に速度を落とした場合でも数秒ごとに数回程度のバッファオーバーフローを起こしていることが観測されました。オーバーフローが発生している場合、GNU Radio のコンソールには "O" （大文字のオー）が断続的に出力されます。

このことから、ノートPCを使う場合でも可能ならゲーム等のプレイに用いられるような高性能のものを利用するのがよさそうです。特に保存用のディスクドライブは NVMe SSD 等の特に高速なものを使用するのが良いでしょう。

- GNU Radio の使用

測定時には測定対象の信号が適切な振幅で記録されるよう、効率的に予備測定を行いゲインを調節したい所です。また、前述のように生データの解析には非常に時間を要しますので、観測時に「開始より何サンプル程度付近でゲートを通過した（ので、そのサンプル数付近に感があるはず）」を別途手掛かりとして記録できると便利です。

そこで、ソフトウェア無線機の制御やそのデータ処理を行える GNU Radio を用い、以下のような記録用デザインを作成しました。下記例では GNU Radio Compagnion バージョン 3.7.13.4 を使用しています。

![rec_design.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216085/4a58f9db-dca1-ce2b-dcc1-d6e34ca091b1.png)

この例では、osmocom Source ブロックを用いて HackRF One の中心周波数を 5800 MHz、内蔵 LNA Gain を40 db （最大値）、サンプリングレート 20Msps に設定し、File Sink ブロックで取得データをファイルに保存しています。

平行して QT GUI Waterfall Sink を用いて受信スペクトル全体を表示することで、5795MHz と 5805MHz のどちらに信号受信があったか、また時間軸方向にどの程度通信が発生したかを知ることができます。一方、QT GUI Waterfall Sink はあくまでディスプレイのリフレッシュ周期（variable update\_period で設定）で受信スペクトルを更新していくため、ETC の短いパケットの存在を取りこぼすことがあります。

そこで、全体をつかむスペクトル表示に加えて、元信号をコピーし、それぞれ -5MHz および +5MHz の正弦波と重畳することで5795 MHz と5805 MHz に周波数変換を掛けた信号を生成（Signal Source とMultiply ブロック）し、それを時間波形表示ブロック（QT GUi Time Sink ）を用いて表示することとしました。時間波形表示ブロックには信号強度によるトリガを設定することで、トリガを超える強度の信号受信時のスナップショットを取得できるため、瞬間的に通過するパケットの存在を捉えることができます。この波形を見ながら予備測定を繰り返し、適切な受信パワーとなるように osmocom Source ブロックの LNA Gain を調節します。

sample\_counter モジュールは embedded python block を用いて作成したオリジナルのブロックで、下記のプログラムを記述してあります。プログラム内では概ね 1 秒相当のサンプル数ごとに処理済みサンプル数の数をコンソールに出力しています。これを用い、測定中にアンテナ直下を通過した時の処理済みサンプル数をメモしておきます。解析時には当該サンプル数付近までデータを読み飛ばしてから解析を始めることで、効率的な分析を行うことが可能です。

```python:sample_counter.py
import numpy as np
from gnuradio import gr

class blk(gr.sync_block):  # other base classes are basic_block, decim_block, interp_block

    def __init__(self, squawk_interval=20000000):  # only default arguments here
        gr.sync_block.__init__(
            self,
            name='Sample Counter',
            in_sig=[np.complex64],
            out_sig=None
        )
        self.squawk_interval = squawk_interval
        self.tick_count = 0
        self.prev_squawk_count = 0

    def work(self, input_items, output_items):
        self.tick_count += len(input_items[0])
        if int(self.tick_count / self.squawk_interval) != self.prev_squawk_count:
            print("sample counter : %d samples processed" % self.tick_count)
            self.prev_squawk_count = int(self.tick_count / self.squawk_interval)
        return len(input_items[0])
```

# 実際の測定模様

では、いざ機材を車載し、測定をしてみましょう。当構成では長時間の記録は困難なので、高速道を走っている間連続記録ということはできません。よって、運転手担当と機材操作担当を分け、安全に配慮した上でゲート通過前後のみの測定を行いました。

![rec_wave.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216085/420c20da-4f3b-80e2-d00c-3db1c2dc6b26.png)

上図はある高速道路料金所を通過した時の、下り方向通信の測定結果です。受信スペクトルを表示した freq\_at\_a\_glance の項目を見ると、5795 MHz を中心に 2～4MHz 程度の幅を持った信号が散発的に発生していることが読み取れます。

また、5795MHz への中心周波数変換を掛けたあとの時間波形を表示している ch0\_at\_a\_glance 項目を見ると、マンチェスター符号によって強度変調された信号をくっきりと見ることができました！

[後編（デコード編）](https://qiita.com/chibiegg/items/35f60ee8d4551905f603#_reference-a2161f8c4cf99fae745b) ではこのデータの解析を試みます。是非ご覧ください。