Pythonでディジタル変復調のBER(Bit Error Rate)計算をシミュレーションしてみる
こんにちは、ナベゾーです。
今回はPythonでディジタル変調の方式の1つであるBPSKによる変復調とビット誤り率(BER:Bit Error Rate)の計算のシミュレーションを行い、理論値との比較をグラフに描いてみたいと思います。
せっかくPythonの勉強をして資格まで取ったので、PythonのパッケージであるNumpyの基本的な使い方をディジタル変復調のBER計算のシミュレーションを通して抑えようというのが狙いです。
●この記事の目次
1.この記事で説明しないこと
Numpy、Matplotlibの使い方を説明することが目的であるため、BPSK、BERといったディジタル無線通信関連の専門用語の内容についてはこの記事では説明しません。
2.BPSK変調のBER測定シミュレーションのサンプルコード
ではさっそくPythonによるBPSK変調のBER測定シミュレーションのサンプルコードを以下に示します。
#パッケージのインポート import numpy as np import numpy.random as r import matplotlib.pyplot as plt import math as m # データサンプル数 N = 10 ** 7 # BERの計算結果の格納用リストを定義(初期値は空でappendで追加していく) BER_List = [] # シミュレーション値 BER_Theory_List = [] # 理論値 #(1)送信データの生成(0,1のランダムデータ) Tx_Data = r.randint(0, 2, N) #(2)SN比[dB]のリスト SN_dB_List = np.arange(0, 12.5, 0.5) # SN比[dB]の値を変化させながら、BERの値を計算 for SN_dB in SN_dB_List: #(3)雑音信号の生成 Pn = 10 ** (-SN_dB / 10) # 雑音電力 Noise_Sig = m.sqrt(Pn/2) * (r.randn(N) + 1j * r.randn(N)) #BPSK変調信号(送信信号)の作成 BPSK_Mod_Sig = np.where(Tx_Data == 1, Tx_Data, -1) # 受信信号(送信信号に雑音信号を加算)を作成 Rx_Sig = BPSK_Mod_Sig + Noise_Sig #(4)BPSK変調信号の復調処理 Rx_Data = np.where(Rx_Sig.real >= 0, 1, 0) #ビット誤り数を計算 BER = sum(abs(Tx_Data - Rx_Data)) / N BER_List.append(BER) #BERの理論値を計算 BER_Theory = 1 / 2 * m.erfc(m.sqrt(10**(SN_dB / 10))) BER_Theory_List.append(BER_Theory) #BERの計算結果をグラフに描画 plt.plot(SN_dB_List, BER_List, "ro", label="Simulation") # シミュレーション値のグラフの描画 plt.plot(SN_dB_List, BER_Theory_List, label="Theory") # 理論値のグラフの描画 plt.yscale("log") # Y軸を対数表示に設定 plt.xlabel("SN[dB]") # X軸のラベルを"SN[dB]"に設定 plt.ylabel("BER") # Y軸のラベルを"BER"に設定 plt.grid(True) # 目盛線の表示を有効化 plt.minorticks_on() # 補助目盛の表示を有効化 plt.legend() # 凡例の表示を有効化 plt.show() # グラフを画面に表示
BERのグラフ表示は以下のようになります。
図1-1 SN[dB] 対 BERグラフ
3.ディジタル変復調のシミュレーションで覚えておきたい関数
(1)numpy.random.randint()
0,1のランダムデータ列の生成には、numpy.random.randint()関数を使用します。
numpy.random.randint(X, Y, N)
の形式で、X~Y-1の範囲のランダム整数を含む1行N列のデータ列を生成します。
0,1のランダムデータを生成する場合は、
numpy.random.randint(0, 2, N)
とします。(2は含まれない)
サンプルコードでは記載していませんが、M行N列のランダムデータ列を生成する場合は、
numpy.random.randint(0, 2, [M, N])
とします。
(2)numpy.arange()
SN比を段階的に変化させながらfor文を回す際には、numpy.arange()で等差数列を生成します。
numpy.arrange(X, Y, Z)
の形式で、
XからZ刻みで最終項がY未満の値となる等差数列を生成します。
上記のサンプルコードでは、
numpy.arrange(0, 12.5, 0.5)
の形式で、0から0.5刻みで最終項が12.0となる等差数列を生成しています。
(3)numpy.random.randn()
白色雑音のデータ列の生成には、numpy.random.randn()関数を使用します。
numpy.random.randn(N)
の形式で、1行N列の標準正規分布の乱数データ列を生成します。
(4)numpy.where()
numpy.where()は、Numpy配列の各要素に対し、条件に応じた処理を行います。
numpy.where(Numpy配列の各要素
に対する条件式, 判定が真の場合の処理, 判定が偽の場合の処理)
の形式で使用します。
上記のサンプルコードでは、
Rx_Data = np.where(Rx_Sig.real >= 0, 1, 0)
の形式で、受信信号の実部が0以上であれば1、0未満であれば0という復調結果のデータ列を生成します。