- Δ-Σ変調器の基本構造
• 入力:アナログ信号
例:音声、センサ電圧など。
• 前段:ローパスフィルタ
サンプリング前に高周波を除去(アンチエイリアシング用)。
• オーバーサンプリング
信号帯域幅の数十~数百倍のサンプリング周波数 fs を用いる。
• Δ-Σ変調器本体
• 累積加算器(∑)=積分器
• 減算器(Δ)=差分器
• 量子化器(1ビットDAC+コンパレータ)
• フィードバック経路
→ 入力信号に比例した**パルス密度列(0と1の列)**を生成する。
⸻
- 動作のイメージ(バケツモデル)
• 入力電圧に応じてキャパシタ(バケツ)に電荷が溜まる。
• 一定量に達すると「1」を出力し、溢れた分を差し引いてリセット。
• 入力が大きければ「1」が頻発、入力が小さければ「0」が多くなる。
• 結果:入力振幅に比例したパルス密度列が出力される。
⸻
- 出力の処理
• Δ-Σ変調器の出力は 高周波成分を多く含む1ビット列。
• そのままでは元信号は見えにくい。
• **デジタル・フィルタ(デシメーション・フィルタ)**を通すことで:
• 高周波ノイズを除去
• サンプリング周波数を fs → fs/N に間引き(ダウンサンプリング)
• 最終的に多ビットのディジタル信号へ変換
⸻
- ノイズシェーピング
• Δ-Σ変調器では量子化ノイズが避けられない。
• しかし積分器を組み込むことでノイズが高周波帯域へ押しやられる。
• これを ノイズシェーピング という。
• 信号帯域内(低周波)ではノイズが小さくなる → 高分解能な変換が可能。
⸻
- アンチエイリアシングフィルタの役割
• サンプリング前に必要不可欠。
• サンプリング周波数 fs の 1/2(ナイキスト周波数)を超える信号が入力すると**折り返し(エイリアシング)**が発生する。
• 例:
• fs = 10 MHz
• 入力信号 = 10.9 MHz
→ サンプリング後には 0.1 MHz の「偽信号」に見えてしまう。
• これを防ぐために、**ローパスフィルタ(アンチエイリアシングフィルタ)**をサンプリングの前段に挿入する。
⸻
- 設計者が持つべきイメージ
• Δ(差分):信号の時間変化(微分)をとる。
• Σ(積分):信号を累積する。
• Δ-Σ変調器=差分と積分を組み合わせて、量子化ノイズを高周波へ追いやる仕組み。
• アンチエイリアシングフィルタ=不要な高周波を事前に消して「偽信号」を防ぐ。
⸻
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import firwin, lfilter
# ================= Parameters =================
fs = 200000 # Sampling frequency [Hz] (oversampled)
fin = 1000 # Input sine frequency [Hz]
A = 0.7 # Input amplitude [V]
N = 2000 # Number of samples
Vref = 1.0 # 1-bit DAC levels (±Vref)
decim = 64 # Decimation factor
# ================= Input Signal =================
t = np.arange(N) / fs
x = A * np.sin(2*np.pi*fin*t)
# ================= Δ-Σ Modulator =================
v_int = np.zeros(N) # integrator output
y_bit = np.zeros(N) # quantizer output
y_dac = np.zeros(N) # DAC feedback
for n in range(N):
if n == 0:
v_int[n] = x[n]
else:
v_int[n] = v_int[n-1] + (x[n] - y_dac[n-1]) # integrator update
y_bit[n] = 1 if v_int[n] >= 0 else -1
y_dac[n] = Vref * y_bit[n]
# ================= Digital Decimation Filter =================
numtaps = 101
cutoff = fs/(2*decim) / (fs/2) # normalized cutoff
fir = firwin(numtaps, cutoff)
y_filt = lfilter(fir, 1.0, y_dac)
# Downsample
y_decim = y_filt[::decim]
t_decim = t[::decim]
# ================= Plot =================
plt.figure(figsize=(12,10))
plt.subplot(4,1,1)
plt.plot(t, x, label="Input (Analog Signal)")
plt.xlim(0, 2e-3)
plt.legend()
plt.ylabel("Amplitude [V]")
plt.subplot(4,1,2)
plt.plot(t, v_int, label="Integrator Output")
plt.xlim(0, 2e-3)
plt.legend()
plt.ylabel("Integrator Value")
plt.subplot(4,1,3)
plt.step(t, (y_bit+1)/2, where='post', label="Δ-Σ 1-bit Output")
plt.xlim(0, 2e-3)
plt.ylim(-0.2, 1.2)
plt.legend()
plt.ylabel("Bitstream")
plt.subplot(4,1,4)
plt.plot(t_decim, y_decim[:len(t_decim)], label="Decimated (Recovered Signal)")
plt.plot(t, x, 'r--', alpha=0.5, label="Original")
plt.xlim(0, 2e-3)
plt.legend()
plt.ylabel("Amplitude [V]")
plt.xlabel("Time [s]")
plt.tight_layout()
plt.show()