「数年入手をためらっていた」RTL-SDRを遅ればせながらようやく入手、別シリーズにてインストールからFMラジオ受信まで行ってみました。やってみれば簡単じゃん。ということでRTL-SDRのIQ信号を取り出してみること。使用するのは pyrtlsdr です。PythonからRTL-SDR内部のIQ信号を取り出せるもの。
※「手習ひデジタル信号処理」投稿順 Indexはこちら
入手したRTL-SDRのドングルの写真を再掲します。一応「純正品」のつもりで購入させていただいたもの。以前は銀色の筐体だったらしですが、2023年初めの出荷から黒色のケースに変わったらしいです。SMAコネクタの先に接続するケーブルとロッドアンテナ付きのパッケージで購入。アンテナはFM放送が受信できるような長さに調整して窓際に設置済です。
pyrtlsdrとlibrtlsdrのインストール
pyrtlsdrは、PythonからRTL-SDRを制御するためのパッケージです。pypiの以下のページから各方面にリンクが張られています。
今回は以下のpyrtlsdrのPDFドキュメント掲載のサンプルをチョイ変で動作させてみました。
なお、pyrtlsdrを使う場合にも、RTL-SDRのUSBドライバは設定されていなければなりません。当方Windows11環境なので、Windowsの場合、Zadigによる設定が必須です(別件記事はこちら)
pyrtlsdrそのものは、pypiでサポートされているとおり、pipでフツーにインストールが可能です。こんな感じ。
ただし、pyrtlsdr自体は、以下のGithubページでサポートされているlibrtlsdrというライブラリが必要みたいです。以下のページから適切なlibrtlsdrをダウンロードし(当方 Windows11なので、Windows用の64ビット版のDLLが含まれているもの選択)、解凍後のディレクトリにPathを向けておく必要がありました。
ドキュメンテーションのサンプルプログラムを動かしてみる
今回上の方のリンクからダウンロードした以下のPDFファイルを参照させていただいております。
pyrtlsdr Documentation Release 0.2.93
上記のドキュメントの中、最初の方にあるUsageeの中のExampleの最初のサンプルプログラムとして以下のようなコード例があります(以下は、Tokyo FM受信用にcenter_freq変更済)
from rtlsdr import RtlSdr sdr = RtlSdr() sdr.sample_rate = 2.048e6 sdr.center_freq = 80e6 sdr.freq_correction = 60 sdr.gain = 'auto' print(sdr.read_samples(512))
ここでターゲットとする放送波(キャリア周波数)はsdr.center_freq、実際に取得されるIQ信号のサンプリング周波数がsdr.sample_rateということみたいです。知らんけど。なお、最初、sdr.freq_correctionの値を0にしてみたのですが、そうすると落ちました。なんでだろ~。PDFファイルのサンプルコードに書かれていた通りの、
sdr.freq_correction = 60
とすると問題なく動作しました(単位はppmらしいっス。)
動作結果は以下のようです。受信したIQ信号が複素表示されております。
後は、煮るなり焼くなりどうとでもせよ、という感じっす。
PDFには第2のサンプルプログラムとして、受信した信号のPSD(パワースペクトル密度)プロットを行うものが挙げられています。ただし、オリジナルは
pylab
というモジュールを使ってプロットするようになってました。pylabはmatplotlibやnumpyに一皮かぶせるものみたいです。調べたら 最近は pylab 使わない方向みたいだったので、直接 matplotlib を呼び出す方法に勝手変更したものが以下に。なお、周波数やゲインは Tokyo FM受信用にこれまた勝手変更済です。
import matplotlib.pyplot as plt from rtlsdr import RtlSdr sdr = RtlSdr() sdr.sample_rate = 2.048e6 sdr.center_freq = 80e6 sdr.freq_correction = 60 sdr.gain = 'auto' samples = sdr.read_samples(256*1024) sdr.close() plt.psd(samples, NFFT=1024, Fs=sdr.sample_rate/1e6, Fc=sdr.center_freq/1e6) plt.xlabel('Frequency [MHz]') plt.ylabel('Relative power [dB]') plt.show()
比較のため、別シリーズでインストール済のSDR#ソフトウエアで観察した、似た範囲のスペクトラムが以下に。
PythonでRF信号を捕まえられてるみたい。夢が広がっちゃうです。何年も前からあったのだからもっと早くやってればよかった。