調變技術 (Modulation)
調變 (Modulation):通訊設備的發射端將「低頻訊號 (聲音)」處理成「高頻訊號 (電磁波)」之後,再傳送出去的過程,稱為「調變」。
解調 (Demodulation):通訊設備的接收端將「高頻訊號 (電磁波)」接收了之後,再還原成「低頻訊號 (聲音)」的過程,稱為「解調」。
ASK (Amplitude Shift Keying)
振幅位移鍵送 ASK,使電磁波跟隨數位訊號的「振幅大小」變化,載著數位訊號一起發射出去。當電磁波振幅大時,代表 1;振幅小時,代表 0。ASK 的技術最簡單,抗雜訊能力最差,較少使用在無線通訊上,而多使用在光纖通訊。
FSK (Frequency Shift Keying)
頻率位移鍵送 FSK,使電磁波跟隨數位訊號的「頻率高低」變化,載著數位訊號一起發射出去。當電磁波頻率高時,代表 1;頻率低時,代表 0。FSK 在頻率改變的瞬間可能使電磁波不連續,造成頻譜的特性變差。技術複雜,但抗雜訊能力比 ASK 好,錯誤率低,可使用在無線通訊上。
PSK (Phase Shift Keying)
相位位移鍵送 PSK,使電磁波跟隨數位訊號的「波形不同」變化,載著數位訊號一起發射出去。當電磁波相位為 180°(先下後上振動)時,代表 1;相位為 0°(先上後下振動)時,代表 0。技術最複雜,但抗雜訊能力最好,因此較常用在無線通訊上,例如無線網路。
Tkinter 介面: 用於接收 10-bit 的二進制輸入。
Matplotlib 邏輯: 根據輸入的 10-bit 數據,生成 ASK、FSK、PSK 的波形數據。
Tkinter 整合: 將 Matplotlib 圖表嵌入到 Tkinter 視窗中。
(使用 Matplotlib 整合至 Tkinter)
import tkinter as tk
from tkinter import ttk, messagebox
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
# --- 核心邏輯:波形生成函式 ---
def generate_modulation_signals(data_bits, fc=10, fs=1000):
"""
根據輸入的二進制數據,生成 ASK, FSK, PSK 訊號。
fc: 載波頻率 (Carrier Frequency)
fs: 採樣頻率 (Sampling Frequency)
"""
# 計算總時間長度 (假設每個 bit 持續 1 秒)
T_bit = 1
T_total = len(data_bits) * T_bit
# 創建時間軸
time = np.linspace(0, T_total, int(fs * T_total), endpoint=False)
# 初始化訊號
ask_signal = np.zeros_like(time)
fsk_signal = np.zeros_like(time)
psk_signal = np.zeros_like(time)
# 載波 (Carrier)
carrier = np.cos(2 * np.pi * fc * time)
# 循環處理每個 bit
for i, bit in enumerate(data_bits):
t_start = i * T_bit
t_end = (i + 1) * T_bit
# 找出當前 bit 區間的索引
idx = (time >= t_start) & (time < t_end)
# 1. ASK (Amplitude Shift Keying)
# '1' = 載波振幅 A1 (設為 1.0)
# '0' = 載波振幅 A0 (設為 0.2, 避免完全為零,以便觀察)
amplitude = 1.0 if bit == '1' else 0.2
ask_signal[idx] = amplitude * np.cos(2 * np.pi * fc * time[idx])
# 2. FSK (Frequency Shift Keying)
# '1' = 頻率 f1 (設為 1.5 * fc)
# '0' = 頻率 f0 (設為 0.5 * fc)
freq = 1.5 * fc if bit == '1' else 0.5 * fc
fsk_signal[idx] = np.cos(2 * np.pi * freq * time[idx])
# 3. PSK (Phase Shift Keying)
# '1' = 相位 φ1 (設為 0)
# '0' = 相位 φ0 (設為 pi/2, 即 90度相移,與圖片中180度相移略有不同,但能清楚顯示相位變化)
phase = 0 if bit == '1' else np.pi # 180度相移 (π)
psk_signal[idx] = np.cos(2 * np.pi * fc * time[idx] + phase)
# 模擬基頻訊號 (Baseband)
baseband = np.zeros_like(time)
for i, bit in enumerate(data_bits):
t_start = i * T_bit
t_end = (i + 1) * T_bit
idx = (time >= t_start) & (time < t_end)
baseband[idx] = 1.0 if bit == '1' else 0.0
return time, baseband, carrier, ask_signal, fsk_signal, psk_signal, T_total
# --- Tkinter 應用程式類 ---
class ModulationApp:
def __init__(self, master):
self.master = master
master.title("數位調變波形產生器")
# 設定 Tkinter 介面
main_frame = ttk.Frame(master, padding="10")
main_frame.pack(fill='both', expand=True)
input_frame = ttk.LabelFrame(main_frame, text="輸入 (10-bit 二進制)", padding="10")
input_frame.pack(fill='x', pady=5)
ttk.Label(input_frame, text="請輸入 10 個二進制位元 (例如: 1010101010):").pack(side='left', padx=10)
self.bit_input = ttk.Entry(input_frame, width=15)
self.bit_input.pack(side='left', padx=10)
self.bit_input.insert(0, "1010111001") # 預設值
ttk.Button(input_frame, text="產生波形", command=self.plot_signals).pack(side='left')
# Matplotlib 繪圖區域
self.fig, self.axs = plt.subplots(5, 1, sharex=True, figsize=(10, 8))
self.fig.tight_layout(pad=3.0) # 調整佈局
self.canvas = FigureCanvasTkAgg(self.fig, master=main_frame)
self.canvas_widget = self.canvas.get_tk_widget()
self.canvas_widget.pack(fill='both', expand=True, pady=10)
# 初始繪圖
self.plot_signals(initial=True)
def plot_signals(self, initial=False):
"""
根據輸入繪製 ASK, FSK, PSK 波形。
"""
data_str = self.bit_input.get().strip()
if initial:
# 初始時使用預設值
data_str = "1010111001"
if len(data_str) != 10 or not all(c in '01' for c in data_str):
messagebox.showerror("輸入錯誤", "請輸入剛好 10 個二進制位元 (0 或 1)。")
return
data_bits = list(data_str)
# 1. 生成數據
time, baseband, carrier, ask_signal, fsk_signal, psk_signal, T_total = \
generate_modulation_signals(data_bits)
# 2. 清除舊圖表
for ax in self.axs:
ax.clear()
# 3. 繪製
titles = ["(a) BASEBAND", "(b) CARRIER", "(c) ASK", "(d) FSK", "(e) PSK"]
signals = [baseband, carrier, ask_signal, fsk_signal, psk_signal]
for i, ax in enumerate(self.axs):
ax.plot(time, signals[i])
ax.set_title(titles[i], loc='left', fontsize=12)
ax.set_yticks([]) # 隱藏 Y 軸標籤
ax.set_xlim(0, T_total)
ax.grid(True, linestyle='--', alpha=0.6)
# 特別處理基頻訊號,使其看起來更像方波
if i == 0:
ax.step(time, signals[i], where='post')
ax.set_ylim(-0.2, 1.2) # 調整 y 軸範圍以顯示 0 和 1
# 標記 1 和 0
for bit_idx, bit in enumerate(data_bits):
ax.text(bit_idx + 0.5, 0.5, bit, fontsize=18, ha='center', va='center', color='red')
# 設置底部 X 軸標籤
self.axs[-1].set_xlabel("Time (sec)")
# 4. 更新 Canvas
self.canvas.draw()
# --- 執行主程式 ---
if __name__ == "__main__":
root = tk.Tk()
app = ModulationApp(root)
root.mainloop()


沒有留言:
張貼留言