手習ひデジタル信号処理(88) pyrtlsdr、PythonでRTL-SDRの信号を処理

Joseph Halfmoon

「数年入手をためらっていた」RTL-SDRを遅ればせながらようやく入手、別シリーズにてインストールからFMラジオ受信まで行ってみました。やってみれば簡単じゃん。ということでRTL-SDRのIQ信号を取り出してみること。使用するのは pyrtlsdr です。PythonからRTL-SDR内部のIQ信号を取り出せるもの。

※「手習ひデジタル信号処理」投稿順 Indexはこちら

入手したRTL-SDRのドングルの写真を再掲します。一応「純正品」のつもりで購入させていただいたもの。以前は銀色の筐体だったらしですが、2023年初めの出荷から黒色のケースに変わったらしいです。SMAコネクタの先に接続するケーブルとロッドアンテナ付きのパッケージで購入。アンテナはFM放送が受信できるような長さに調整して窓際に設置済です。RTL_SDR_V3a

 

pyrtlsdrとlibrtlsdrのインストール

pyrtlsdrは、PythonからRTL-SDRを制御するためのパッケージです。pypiの以下のページから各方面にリンクが張られています。

pyrtlsdr

今回は以下のpyrtlsdrのPDFドキュメント掲載のサンプルをチョイ変で動作させてみました。

pyrtlsdr Documentation

なお、pyrtlsdrを使う場合にも、RTL-SDRのUSBドライバは設定されていなければなりません。当方Windows11環境なので、Windowsの場合、Zadigによる設定が必須です(別件記事はこちら

pyrtlsdrそのものは、pypiでサポートされているとおり、pipでフツーにインストールが可能です。こんな感じ。pip_pyrtlsdr

ただし、pyrtlsdr自体は、以下のGithubページでサポートされているlibrtlsdrというライブラリが必要みたいです。以下のページから適切なlibrtlsdrをダウンロードし(当方 Windows11なので、Windows用の64ビット版のDLLが含まれているもの選択)、解凍後のディレクトリにPathを向けておく必要がありました。

librtlsdr / librtlsdr

ドキュメンテーションのサンプルプログラムを動かしてみる

今回上の方のリンクからダウンロードした以下の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信号が複素表示されております。Sample1_pyrtlsdr

後は、煮るなり焼くなりどうとでもせよ、という感じっす。

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()

実行結果が以下に。pyrtlsdr_sample2_PSD_plot

比較のため、別シリーズでインストール済のSDR#ソフトウエアで観察した、似た範囲のスペクトラムが以下に。SDR_spectrum

PythonでRF信号を捕まえられてるみたい。夢が広がっちゃうです。何年も前からあったのだからもっと早くやってればよかった。

手習ひデジタル信号処理(87) Scilab、前回の続きでNCOした信号をLPF へ戻る

手習ひデジタル信号処理(89) PythonからScilabへRTL-SDRデータをお裾分け へ進む