AM変調はアナログ変調方式の1つで、信号を搬送波の振幅に乗せて情報を伝達する方式です。AMラジオ放送で広く使われてきた歴史のある変調方式です。
本記事の内容
- AM変調の数学的定式化
- 変調指数と過変調
- 周波数スペクトルの解析
- 包絡線検波による復調
- Pythonでの完全な実装
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
AM変調の数学的定式化
信号波(ベースバンド信号)
送信したい情報を含む信号を $m(t)$ とします。簡単のため正弦波とすると、
$$ m(t) = A_m \cos(2\pi f_m t) $$
ここで $A_m$ は振幅、$f_m$ は信号の周波数です。
搬送波
搬送波は信号波より十分に高い周波数の正弦波です。
$$ c(t) = A_c \cos(2\pi f_c t) $$
AM変調信号
AM変調信号 $s(t)$ は次のように定義されます。
$$ s(t) = A_c [1 + m \cdot \hat{m}(t)] \cos(2\pi f_c t) $$
ここで $\hat{m}(t) = m(t)/A_m$ は正規化された信号波、$m = A_m / A_c$ は変調指数(modulation index)です。
正弦波の場合、
$$ s(t) = A_c [1 + m \cos(2\pi f_m t)] \cos(2\pi f_c t) $$
変調指数
変調指数 $m$ は変調の深さを制御するパラメータです。
$$ m = \frac{A_{\max} – A_{\min}}{A_{\max} + A_{\min}} $$
- $0 < m < 1$: 正常な変調
- $m = 1$: 100%変調(最大深度)
- $m > 1$: 過変調(信号が歪む)
周波数スペクトル
三角関数の積の公式を使って展開します。
$$ \begin{align} s(t) &= A_c \cos(2\pi f_c t) + \frac{mA_c}{2}\cos(2\pi(f_c + f_m)t) + \frac{mA_c}{2}\cos(2\pi(f_c – f_m)t) \end{align} $$
スペクトルは3つの成分から構成されます。
| 成分 | 周波数 | 振幅 |
|---|---|---|
| 搬送波 | $f_c$ | $A_c$ |
| 上側帯波(USB) | $f_c + f_m$ | $mA_c/2$ |
| 下側帯波(LSB) | $f_c – f_m$ | $mA_c/2$ |
電力効率
AM変調の電力効率は次のように計算されます。
$$ \eta = \frac{P_{\text{sideband}}}{P_{\text{total}}} = \frac{m^2/2}{1 + m^2/2} $$
$m = 1$(100%変調)でも効率は33%にとどまります。これはAM変調の大きな欠点です。
包絡線検波(復調)
AM信号の包絡線(振幅の変化)を抽出することで、元の信号を復調できます。
$$ \text{envelope}(t) = A_c [1 + m \cdot \hat{m}(t)] $$
包絡線検波はダイオードとRCフィルタで簡単に実装できます。これがAMラジオの受信方式です。
Pythonでの実装
import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import hilbert
# パラメータ
fs = 100000 # サンプリング周波数 [Hz]
T = 0.1 # 信号長 [s]
t = np.linspace(0, T, int(fs * T))
fc = 10000 # 搬送波周波数 [Hz]
fm = 500 # 信号波周波数 [Hz]
Ac = 1.0 # 搬送波振幅
# === AM変調 ===
fig, axes = plt.subplots(3, 2, figsize=(14, 14))
# 変調指数を変えたAM信号
for idx, m in enumerate([0.5, 1.0, 1.5]):
signal = np.cos(2 * np.pi * fm * t)
am = Ac * (1 + m * signal) * np.cos(2 * np.pi * fc * t)
envelope = Ac * (1 + m * signal)
axes[idx, 0].plot(t * 1000, am, 'b-', linewidth=0.3)
axes[idx, 0].plot(t * 1000, envelope, 'r-', linewidth=1.5, label='Envelope')
axes[idx, 0].plot(t * 1000, -envelope, 'r-', linewidth=1.5)
axes[idx, 0].set_xlabel('Time [ms]')
axes[idx, 0].set_ylabel('Amplitude')
axes[idx, 0].set_title(f'AM Signal (m = {m})')
axes[idx, 0].set_xlim(0, 10)
axes[idx, 0].legend()
# スペクトル
freq = np.fft.fftfreq(len(t), 1/fs)
am_fft = np.abs(np.fft.fft(am)) / len(t)
axes[idx, 1].plot(freq[:len(freq)//2], 2*am_fft[:len(freq)//2], 'b-')
axes[idx, 1].set_xlabel('Frequency [Hz]')
axes[idx, 1].set_ylabel('Magnitude')
axes[idx, 1].set_title(f'Spectrum (m = {m})')
axes[idx, 1].set_xlim(fc - 5*fm, fc + 5*fm)
if m <= 1:
status = "正常"
else:
status = "過変調"
axes[idx, 1].text(0.02, 0.95, status, transform=axes[idx, 1].transAxes,
fontsize=12, color='red' if m > 1 else 'green',
verticalalignment='top')
plt.tight_layout()
plt.show()
# === 復調(包絡線検波) ===
m = 0.8
signal = np.cos(2 * np.pi * fm * t) + \
0.5 * np.cos(2 * np.pi * 2 * fm * t) # 2つの周波数成分
signal = signal / np.max(np.abs(signal)) # 正規化
am_signal = Ac * (1 + m * signal) * np.cos(2 * np.pi * fc * t)
# ヒルベルト変換による包絡線検波
analytic = hilbert(am_signal)
envelope_detected = np.abs(analytic)
# DCオフセット除去と正規化
demodulated = (envelope_detected - Ac) / (m * Ac)
fig, axes = plt.subplots(3, 1, figsize=(14, 10))
# 元の信号
axes[0].plot(t * 1000, signal, 'b-', linewidth=1.5)
axes[0].set_title('Original Signal')
axes[0].set_xlabel('Time [ms]')
axes[0].set_ylabel('Amplitude')
axes[0].set_xlim(0, 20)
axes[0].grid(True)
# AM変調信号
axes[1].plot(t * 1000, am_signal, 'g-', linewidth=0.3)
axes[1].plot(t * 1000, envelope_detected, 'r-', linewidth=1.5, label='Detected envelope')
axes[1].set_title('AM Modulated Signal + Envelope Detection')
axes[1].set_xlabel('Time [ms]')
axes[1].set_ylabel('Amplitude')
axes[1].set_xlim(0, 20)
axes[1].legend()
axes[1].grid(True)
# 復調信号
axes[2].plot(t * 1000, signal, 'b-', linewidth=1, alpha=0.5, label='Original')
axes[2].plot(t * 1000, demodulated, 'r-', linewidth=1.5, label='Demodulated')
axes[2].set_title('Demodulated Signal')
axes[2].set_xlabel('Time [ms]')
axes[2].set_ylabel('Amplitude')
axes[2].set_xlim(0, 20)
axes[2].legend()
axes[2].grid(True)
plt.tight_layout()
plt.show()
# 電力効率の計算
print("=== AM変調の電力効率 ===")
for m_val in [0.25, 0.5, 0.75, 1.0]:
eta = m_val**2 / 2 / (1 + m_val**2 / 2)
print(f" m = {m_val:.2f}: 電力効率 = {eta*100:.1f}%")
まとめ
本記事では、AM変調の原理について解説しました。
- AM変調は搬送波の振幅を信号に応じて変化させる方式である
- 変調信号のスペクトルは搬送波成分とUSB・LSBの3成分からなる
- 変調指数 $m > 1$ では過変調となり、包絡線検波で正しく復調できなくなる
- 電力効率は $m=1$ でも33%と低い
- 包絡線検波は簡単な回路で実現できるため、AMラジオで広く使われてきた
次のステップとして、以下の記事も参考にしてください。