概要
本記事では、デジタル信号処理(DSP)におけるFFT(高速フーリエ変換)を用いたスペクトル解析と、ADC(アナログ-デジタル変換)システムの性能指標であるSNDR、ENOB、SFDRの計算方法について解説します。
また、Pythonを用いた具体的な実装コードを紹介し、取得した信号のサンプリング、FFTによる周波数成分の解析、性能指標の算出方法を説明します。
1. 解析対象の信号
まず、time_data
と signal_data
を含むCSVファイルを読み込み、時系列信号を取得します。
この信号には、オフセット補正を行い、特定のサンプリング周波数(1MSPS: 1メガサンプル/秒)でサンプリングを行います。
# CSVファイルのアップロード
uploaded = files.upload()
file_name = list(uploaded.keys())[0]
data = pd.read_csv(file_name)
# 信号データの取得
time_data = data['time_data'].to_numpy()
signal_data = data['signal_data'].to_numpy()
アップロードした信号データは、以下のように可視化されます。
plt.figure(figsize=(10, 4))
plt.plot(time_data, signal_data, label="Original Signal")
plt.title('Original Signal vs Time')
plt.xlabel('Time [s]')
plt.ylabel('Signal')
plt.grid(True)
plt.legend()
plt.show()
オフセット補正
測定された信号にはオフセットが含まれる可能性があるため、オフセット補正を行います。本コードでは signal_data - 8
の処理を行い、信号の基準をゼロに近づけています。
signal_data_modified = signal_data - 8
補正後の信号をプロットして確認します。
plt.figure(figsize=(10, 4))
plt.plot(time_data, signal_data_modified, label="Modified Signal", color='r')
plt.title('Modified Signal vs Time')
plt.xlabel('Time [s]')
plt.ylabel('Modified Signal')
plt.grid(True)
plt.legend()
plt.show()
2. クロック信号とサンプリング
クロック信号の設定
デジタル回路では、クロック信号を用いて信号のサンプリングを行います。本コードでは、1MHz(1 MSPS)のサンプリングレートで遅延要素 delay_element = 0.00000028
を考慮しながら、サンプリング時刻を生成しています。
simulation_time = 0.000512 # シミュレーション時間 (512 µs)
sampling_rate = 1e6 # サンプリング周波数 (1 MSPS)
delay_element = 0.00000028 # 遅れ要素 (280 ns)
# サンプリング時刻の作成
sampled_time = np.arange(delay_element, simulation_time, 1 / sampling_rate)
信号のサンプリング
補間を用いて、作成した sampled_time
に対応する信号値を取得します。
sampled_signal = np.interp(sampled_time, time_data, signal_data_modified)
サンプリングした信号を可視化し、元の信号との比較を行います。
plt.figure(figsize=(10, 4))
plt.plot(time_data, signal_data_modified, label="Modified Signal", color='r', alpha=0.5)
plt.scatter(sampled_time, sampled_signal, color='b', label="Sampled Signal", zorder=3)
plt.title('Sampled Signal from delay_element to Simulation Time')
plt.xlabel('Time [s]')
plt.ylabel('Modified Signal')
plt.grid(True)
plt.legend()
plt.show()
また、最初の50点のサンプリング結果を表示します。
print("First 50 Sampled Points (Time [s] - Signal):")
for i in range(min(50, len(sampled_time))):
print(f"{sampled_time[i]:.9f} s - {sampled_signal[i]:.6f}")
3. FFT(高速フーリエ変換)を用いたスペクトル解析
FFTを用いて、サンプリングした信号の周波数スペクトルを解析します。
N = len(sampled_signal)
fs = sampling_rate # サンプリング周波数
freqs = np.fft.fftfreq(N, d=1/fs)[:N//2] # 正の周波数成分のみ取得
spectrum = np.abs(fft(sampled_signal)[:N//2]) # FFTの絶対値
# 最大値を0 dBに正規化
spectrum_magnitude_db = 20 * np.log10(spectrum / np.max(spectrum))
FFTスペクトルのプロット
plt.figure(figsize=(10, 4))
plt.plot(freqs / fs, spectrum_magnitude_db, label='FFT (Normalized)')
plt.axhline(y=0, color='r', linestyle='--', label='0 dB Reference')
plt.xlabel('Normalized Frequency (f/fs)')
plt.ylabel('Magnitude [dB]')
plt.title('FFT Spectrum (0 dB = max amplitude)')
plt.legend()
plt.grid(True)
plt.show()
4. ADCの性能評価指標(SNDR, ENOB, SFDR)
ADC(アナログ-デジタル変換)の評価には、以下の指標が重要です。
-
SNDR(Signal-to-Noise and Distortion Ratio)
- 信号成分のパワーとノイズ+歪成分のパワーの比
-
ENOB(Effective Number of Bits)
- SNDRを基にしたADCの有効ビット数
-
SFDR(Spurious-Free Dynamic Range)
- 最大信号成分とスプリアス歪成分の比
signal_power = np.max(spectrum)**2 # 信号成分のパワー
noise_power = np.sum(spectrum**2) - signal_power # ノイズ+歪成分のパワー
SNDR = 10 * np.log10(signal_power / noise_power) # SNDR計算
ENOB = (SNDR - 1.76) / 6.02 # ENOB計算
# SFDRの計算
spurious_spectrum = spectrum.copy()
spurious_spectrum[np.argmax(spectrum)] = 0 # 最大信号成分を除外
SFDR = 20 * np.log10(np.max(spectrum) / np.max(spurious_spectrum)) # SFDR計算
計算結果を表示します。
print(f"Simulation Time: {simulation_time:.6f} s")
print(f"SNDR: {SNDR:.2f} dB")
print(f"ENOB: {ENOB:.2f} bits")
print(f"SFDR: {SFDR:.2f} dB")
5. まとめ
本記事では、サンプリングした信号のFFT解析とADCの性能評価をPythonで実装する方法 を紹介しました。
特に、SNDR, ENOB, SFDRの計算 を通じて、ADCの性能を評価することが可能になります。
本手法を活用することで、実際のADCの性能を測定し、最適なデータ取得・処理方法を検討できます。
今後の応用として、ウィンドウ関数の適用やノイズ除去フィルタの設計 などの手法を導入することで、より精度の高いスペクトル解析が可能になります。