【無線通信】変調方式の基礎をわかりやすく解説

変調(Modulation)方式とは、無線通信を行う際に、送受信したい信号を電気信号に乗せるために変換する方式のことです。

変調を行う理由は主に2つあります。1つは、音声や映像などの信号をそのままの周波数で送ると他の信号と干渉するため、搬送波(carrier wave)を用いて特定の周波数帯に信号を移動させること。もう1つは、アンテナの効率を高めるために、信号の周波数を高くすることです。

本記事の内容

  • 変調の必要性と基本概念
  • アナログ変調(AM, FM)
  • デジタル変調(ASK, PSK, QAM)
  • Pythonでの変調シミュレーション

変調の基本概念

搬送波 $c(t)$ は次のように表されます。

$$ c(t) = A_c \cos(2\pi f_c t + \phi_c) $$

変調とは、搬送波の3つのパラメータ(振幅 $A_c$、周波数 $f_c$、位相 $\phi_c$)のいずれかを、送信したい信号 $m(t)$ に応じて変化させることです。

変調方式 変化させるパラメータ
AM(振幅変調) 振幅 $A_c$
FM(周波数変調) 周波数 $f_c$
PM(位相変調) 位相 $\phi_c$

AM変調(振幅変調)

AM変調では、搬送波の振幅を信号波に比例して変化させます。

$$ s_{\text{AM}}(t) = [1 + m \cdot m(t)] \cos(2\pi f_c t) $$

ここで $m$ は変調指数($0 < m \leq 1$)です。変調指数が1を超えると過変調となり、信号が歪みます。

周波数スペクトル

信号波が $m(t) = \cos(2\pi f_m t)$ の場合、AM信号のスペクトルは、

$$ s_{\text{AM}}(t) = \cos(2\pi f_c t) + \frac{m}{2}\cos(2\pi(f_c + f_m)t) + \frac{m}{2}\cos(2\pi(f_c – f_m)t) $$

搬送波成分と上下のサイドバンドの3つの周波数成分から構成されます。

FM変調(周波数変調)

FM変調では、搬送波の瞬時周波数を信号波に比例して変化させます。

$$ s_{\text{FM}}(t) = A_c \cos\left(2\pi f_c t + 2\pi \Delta f \int_0^t m(\tau) d\tau\right) $$

ここで $\Delta f$ は最大周波数偏移です。FM変調指数 $\beta$ は、

$$ \beta = \frac{\Delta f}{f_m} $$

で定義されます。FM変調はAMに比べて雑音耐性が高いという利点があります。

デジタル変調

デジタル変調では、離散的なシンボルを搬送波のパラメータに対応させます。

PSK(位相偏移変調)

$M$-PSK では、$M$ 個の位相値を使用します。

$$ s_k(t) = A_c \cos\left(2\pi f_c t + \frac{2\pi k}{M}\right), \quad k = 0, 1, \ldots, M-1 $$

BPSK($M=2$)では、位相が $0$ と $\pi$ の2値を取ります。1シンボルあたり $\log_2 M$ ビットの情報を伝送できます。

QAM(直交振幅変調)

QAMは振幅と位相の両方を変調します。$M$-QAMの信号は、

$$ s(t) = a_I \cos(2\pi f_c t) – a_Q \sin(2\pi f_c t) $$

ここで $(a_I, a_Q)$ はコンスタレーション上の点です。16-QAMでは4ビット/シンボル、64-QAMでは6ビット/シンボルの情報を伝送できます。

Pythonでのシミュレーション

import numpy as np
import matplotlib.pyplot as plt

# パラメータ
fs = 10000     # サンプリング周波数 [Hz]
fc = 1000      # 搬送波周波数 [Hz]
fm = 50        # 信号波周波数 [Hz]
t = np.linspace(0, 0.05, int(fs * 0.05))

# 信号波(正弦波)
m_t = np.cos(2 * np.pi * fm * t)

# 搬送波
carrier = np.cos(2 * np.pi * fc * t)

fig, axes = plt.subplots(3, 2, figsize=(14, 12))

# AM変調
mod_index = 0.8
am_signal = (1 + mod_index * m_t) * np.cos(2 * np.pi * fc * t)
axes[0, 0].plot(t * 1000, am_signal, 'b-', linewidth=0.5)
axes[0, 0].plot(t * 1000, 1 + mod_index * m_t, 'r--', linewidth=1)
axes[0, 0].plot(t * 1000, -(1 + mod_index * m_t), 'r--', linewidth=1)
axes[0, 0].set_title(f'AM Modulation (m={mod_index})')
axes[0, 0].set_xlabel('Time [ms]')
axes[0, 0].set_ylabel('Amplitude')

# AM スペクトル
freq = np.fft.fftfreq(len(t), 1/fs)
am_fft = np.abs(np.fft.fft(am_signal)) / len(t)
axes[0, 1].plot(freq[:len(freq)//2], 2*am_fft[:len(freq)//2])
axes[0, 1].set_title('AM Spectrum')
axes[0, 1].set_xlabel('Frequency [Hz]')
axes[0, 1].set_ylabel('Magnitude')
axes[0, 1].set_xlim(0, 2000)

# FM変調
delta_f = 200  # 最大周波数偏移
fm_signal = np.cos(2 * np.pi * fc * t +
                   2 * np.pi * delta_f * np.cumsum(m_t) / fs)
axes[1, 0].plot(t * 1000, fm_signal, 'b-', linewidth=0.5)
axes[1, 0].set_title(f'FM Modulation (Delta_f={delta_f}Hz)')
axes[1, 0].set_xlabel('Time [ms]')
axes[1, 0].set_ylabel('Amplitude')

# FM スペクトル
fm_fft = np.abs(np.fft.fft(fm_signal)) / len(t)
axes[1, 1].plot(freq[:len(freq)//2], 2*fm_fft[:len(freq)//2])
axes[1, 1].set_title('FM Spectrum')
axes[1, 1].set_xlabel('Frequency [Hz]')
axes[1, 1].set_ylabel('Magnitude')
axes[1, 1].set_xlim(0, 2000)

# BPSK
n_symbols = 20
bits = np.random.randint(0, 2, n_symbols)
samples_per_symbol = len(t) // n_symbols
bpsk_signal = np.zeros_like(t)
for i, bit in enumerate(bits):
    phase = 0 if bit == 1 else np.pi
    idx_start = i * samples_per_symbol
    idx_end = (i + 1) * samples_per_symbol
    bpsk_signal[idx_start:idx_end] = np.cos(
        2 * np.pi * fc * t[idx_start:idx_end] + phase)

axes[2, 0].plot(t * 1000, bpsk_signal, 'b-', linewidth=0.5)
# ビット列を重ねて表示
bit_signal = np.repeat(bits * 2 - 1, samples_per_symbol)[:len(t)]
axes[2, 0].plot(t * 1000, bit_signal * 1.2, 'r-', linewidth=1, alpha=0.5)
axes[2, 0].set_title('BPSK Modulation')
axes[2, 0].set_xlabel('Time [ms]')
axes[2, 0].set_ylabel('Amplitude')

# QAMコンスタレーション
M = 16  # 16-QAM
n_qam_symbols = 1000
np.random.seed(42)
qam_data = np.random.randint(0, M, n_qam_symbols)
# 16-QAMのコンスタレーション
levels = np.array([-3, -1, 1, 3])
I = levels[qam_data % 4]
Q = levels[qam_data // 4]
# 雑音の付加
snr_db = 15
noise_std = np.sqrt(np.mean(I**2 + Q**2) / (2 * 10**(snr_db/10)))
I_noisy = I + noise_std * np.random.randn(n_qam_symbols)
Q_noisy = Q + noise_std * np.random.randn(n_qam_symbols)

axes[2, 1].scatter(I_noisy, Q_noisy, s=5, alpha=0.3, c='blue')
axes[2, 1].scatter(I, Q, s=50, c='red', marker='x', zorder=5)
axes[2, 1].set_title(f'16-QAM Constellation (SNR={snr_db}dB)')
axes[2, 1].set_xlabel('In-phase (I)')
axes[2, 1].set_ylabel('Quadrature (Q)')
axes[2, 1].grid(True)
axes[2, 1].set_aspect('equal')

plt.tight_layout()
plt.show()

まとめ

本記事では、無線通信における変調方式の基礎を解説しました。

  • 変調とは搬送波のパラメータ(振幅・周波数・位相)を信号に応じて変化させることである
  • AM変調は振幅を変化させ、スペクトルは搬送波とサイドバンドで構成される
  • FM変調は周波数を変化させ、AM比べて雑音耐性が高い
  • デジタル変調(PSK, QAM)では離散シンボルを搬送波パラメータに対応させる
  • QAMは振幅と位相の両方を使うことで高い周波数利用効率を実現する

次のステップとして、以下の記事も参考にしてください。

関連タグ: AM FM PSK QAM 変調 無線通信