用Python复现1G蜂窝网络:从频分多址到信号调制的全流程仿真
当摩托罗拉工程师马丁·库帕在1973年拨出第一通蜂窝电话时,他手中的"砖头"设备背后是一套精妙的模拟通信系统。如今,我们只需几行Python代码就能重现这套改变人类通信方式的技术原型。本文将带您深入1G网络的核心技术——频分多址(FDMA)系统,通过可交互的代码仿真,揭示模拟蜂窝网络的运作奥秘。
1. 环境搭建与基础概念
在开始仿真前,我们需要配置Python科学计算环境。推荐使用Anaconda创建专属虚拟环境:
conda create -n 1g_sim python=3.8 conda activate 1g_sim pip install numpy matplotlib scipy ipywidgets关键概念解析:
- 载波频率:1G网络使用的800-900MHz频段电磁波
- 信道带宽:TACS标准中每个语音信道占用25kHz
- 频分双工(FDD):上下行采用不同频率实现双向通信
- 频分多址(FDMA):通过频率分割实现多用户接入
注意:实际1G系统采用模拟电路实现,本文通过数字信号处理技术进行等效模拟
2. 频谱资源规划与可视化
让我们首先模拟TACS系统的频谱分配。假设系统总带宽25MHz,需要划分为多个25kHz的信道:
import numpy as np import matplotlib.pyplot as plt total_bandwidth = 25e6 # 25MHz channel_bandwidth = 25e3 # 25kHz channel_count = int(total_bandwidth / channel_bandwidth) # 生成频率轴 frequencies = np.linspace(800e6, 825e6, channel_count) plt.figure(figsize=(12, 4)) for i in range(10): # 只显示前10个信道 plt.axvspan(frequencies[i], frequencies[i]+channel_bandwidth, alpha=0.5, label=f'Channel {i+1}') plt.xlabel('Frequency (Hz)') plt.ylabel('Amplitude') plt.title('FDMA Channel Allocation') plt.legend() plt.grid() plt.show()执行这段代码将生成频谱分配示意图,直观展示FDMA如何将连续频谱划分为离散信道。在真实系统中,这些信道会被动态分配给不同用户和基站。
3. 频率调制(FM)实现
模拟语音信号需要通过频率调制载波传输。以下是FM调制的Python实现:
def fm_modulate(carrier_freq, baseband_signal, deviation=5e3, fs=1e6): """ 频率调制实现 :param carrier_freq: 载波频率 (Hz) :param baseband_signal: 基带语音信号 :param deviation: 最大频偏 (Hz) :param fs: 采样率 (Hz) :return: 调制信号 """ t = np.arange(len(baseband_signal)) / fs # 计算相位变化 phase = 2 * np.pi * carrier_freq * t + 2 * np.pi * deviation * np.cumsum(baseband_signal) / fs return np.cos(phase) # 生成测试信号 fs = 44100 # 音频采样率 duration = 0.1 # 秒 t_audio = np.linspace(0, duration, int(fs * duration)) audio_signal = 0.5 * np.sin(2 * np.pi * 1000 * t_audio) # 1kHz测试音 # 上采样到射频采样率 rf_fs = 10e6 # 10MHz采样率 audio_resampled = np.interp( np.linspace(0, duration, int(rf_fs * duration)), np.linspace(0, duration, len(audio_signal)), audio_signal ) # 调制到850MHz载波 carrier = 850e6 modulated = fm_modulate(carrier, audio_resampled) # 绘制频谱 from scipy.fft import fft, fftfreq N = len(modulated) yf = fft(modulated)[:N//2] xf = fftfreq(N, 1/rf_fs)[:N//2] plt.plot(xf, 20*np.log10(np.abs(yf))) plt.xlim([carrier-50e3, carrier+50e3]) plt.xlabel('Frequency (Hz)') plt.ylabel('Magnitude (dB)') plt.title('FM Signal Spectrum') plt.grid() plt.show()这段代码展示了如何将基带语音信号调制到射频载波,并通过快速傅里叶变换(FFT)验证调制结果。注意频谱图中显示的信号带宽约为25kHz,符合TACS标准要求。
4. 多用户FDMA系统仿真
现在我们将多个用户整合到一个完整的FDMA系统中:
class FDMA_User: def __init__(self, user_id, base_freq): self.user_id = user_id self.carrier_freq = base_freq + user_id * 25e3 self.audio_buffer = np.array([]) def transmit(self, audio_signal): """ 用户发送语音 """ return fm_modulate(self.carrier_freq, audio_signal) def receive(self, rf_signal, channel_freq): """ 用户接收语音 """ if abs(channel_freq - self.carrier_freq) > 12.5e3: return None # 非本用户信道 # 简化解调过程 demodulated = np.diff(np.unwrap(np.angle(rf_signal))) return demodulated / (2 * np.pi * 5e3) # 假设已知频偏 # 创建3个用户 users = [FDMA_User(i, 850e6) for i in range(3)] # 生成不同频率的测试音频 test_audios = [ 0.3 * np.sin(2 * np.pi * 800 * t_audio), 0.4 * np.sin(2 * np.pi * 1200 * t_audio), 0.2 * np.sin(2 * np.pi * 1500 * t_audio) ] # 各用户同时传输 composite_signal = np.zeros(int(rf_fs * duration)) for user, audio in zip(users, test_audios): audio_rs = np.interp(np.linspace(0, duration, int(rf_fs * duration)), np.linspace(0, duration, len(audio)), audio) composite_signal += user.transmit(audio_rs) # 绘制复合信号频谱 yf = fft(composite_signal)[:len(composite_signal)//2] xf = fftfreq(len(composite_signal), 1/rf_fs)[:len(composite_signal)//2] plt.figure(figsize=(12, 4)) plt.plot(xf, 20*np.log10(np.abs(yf))) plt.xlim([849.9e6, 850.1e6]) plt.xlabel('Frequency (Hz)') plt.ylabel('Magnitude (dB)') plt.title('Composite FDMA Signal Spectrum') plt.grid() plt.show()这个仿真展示了三个用户同时在相邻信道上传输时的频谱情况。通过观察频谱图,可以清晰看到三个独立的25kHz信道,每个承载不同用户的语音信号。
5. 蜂窝网络扩展与频率复用
真实的1G网络通过蜂窝结构实现频率复用。以下代码模拟七小区频率复用模式:
def create_hex_grid(center_freq, reuse_factor=7): """ 生成六边形蜂窝频率分配方案 """ cell_channels = [] available_channels = list(range(1000)) # 假设共1000个信道 for i in range(reuse_factor): cell_channels.append(available_channels[i::reuse_factor]) return cell_channels # 可视化频率复用 cell_channels = create_hex_grid(850e6) plt.figure(figsize=(10, 8)) colors = plt.cm.tab10.colors for i in range(7): angle = 2 * np.pi * i / 7 x, y = np.cos(angle), np.sin(angle) plt.scatter(x, y, color=colors[i], s=1000, alpha=0.5) plt.text(x, y, f'Cell {i+1}\n{len(cell_channels[i])} channels', ha='center', va='center') plt.title('7-Cell Frequency Reuse Pattern') plt.axis('equal') plt.axis('off') plt.show()这段代码生成的图形展示了经典的七小区频率复用模式,每个小区使用不同的频率组,相同频率组的小区间隔足够距离以避免干扰。这种设计使有限的频谱资源能够服务更大地理范围。
6. 完整通信流程仿真
让我们模拟一个完整的呼叫建立过程:
class BaseStation: def __init__(self, cell_id): self.cell_id = cell_id self.available_channels = create_hex_grid(850e6)[cell_id % 7] self.assigned_channels = {} def assign_channel(self, user): if not self.available_channels: return None channel = self.available_channels.pop(0) self.assigned_channels[user.user_id] = channel return 850e6 + channel * 25e3 def release_channel(self, user): if user.user_id in self.assigned_channels: channel = self.assigned_channels.pop(user.user_id) self.available_channels.append(channel) # 模拟呼叫流程 bs = BaseStation(1) caller = FDMA_User(101, 850e6) callee = FDMA_User(102, 850e6) print("=== 呼叫建立过程 ===") # 主叫用户请求信道 caller_freq = bs.assign_channel(caller) print(f"主叫用户分配到频率: {caller_freq/1e6:.2f} MHz") # 被叫用户请求信道 callee_freq = bs.assign_channel(callee) print(f"被叫用户分配到频率: {callee_freq/1e6:.2f} MHz") # 模拟语音传输 caller_audio = 0.5 * np.sin(2 * np.pi * 800 * t_audio) caller_signal = caller.transmit(caller_audio) # 基站转发(简化版) callee_received = callee.receive(caller_signal, callee_freq) # 呼叫结束 bs.release_channel(caller) bs.release_channel(callee) print("信道已释放")这个简化流程展示了1G网络中的关键操作:信道分配、信号传输和资源释放。虽然实际系统要复杂得多,但这个仿真捕捉到了FDMA系统的核心逻辑。
7. 性能分析与现代对比
通过仿真我们可以量化1G系统的关键指标:
| 指标 | 1G模拟系统 | 现代4G/5G |
|---|---|---|
| 频谱效率 | 低 (~1 call/25kHz) | 高 (>1 bps/Hz) |
| 语音质量 | 一般 (SNR 30-40dB) | 优秀 (高清语音) |
| 安全性 | 低 (易窃听) | 高 (强加密) |
| 数据能力 | 无 | 支持高速数据 |
虽然1G技术已被淘汰,但理解它的设计原理仍有重要意义:
- 频分多址思想在现代OFDMA中仍有体现
- 蜂窝结构仍是移动网络的基础架构
- 模拟调制技术在某些专业领域仍有应用
在Jupyter Notebook中运行这些代码,您可以交互式地调整参数,观察不同配置下系统性能的变化。例如,尝试修改channel_bandwidth变量,可以看到信道容量与语音质量的权衡关系。