ASK調變方式
https://techweb.rohm.com.tw/product/wireless/wireless-communication/23710/
調變指傳輸資料時,變換成最佳功率訊號。
調變方式大致上可以分成類比調變、數位調變、脈波調變、頻譜擴散4種。
類比調變使用在AM和FM廣播、短波廣播上。
數位調變方式為傳送”1″ 和 “0”二進位訊號的方式。
可以細分成利用振幅和頻率、相位等單載波進行調變,以及將不同的訊號調變成多個載波後再傳送出去的多載波調變。
其他還有更動脈波寬度的脈波調變、訊號能量分散在寬頻的頻譜擴散方式。

說明調變方式
無線通訊中,是藉由將聲音和資料加載在一定頻率的電波上,傳送資料。
本文將說明典型的調變方式概要。
- ASK (Amplitude Shift Keying)
- 利用變換有無類比訊號,來傳送資料的數位調變方式。
- FSK (Frequency Shift Keying)
- 利用類比訊號振幅的不同,調變數位訊號的方式,對於二進位資料0和1,藉由切換低頻和高頻來進行調變。

import tkinter as tk
from tkinter import ttk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
import matplotlib.pyplot as plt
# --- Matplotlib 中文設置 ---
try:
plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei', 'SimHei', 'sans-serif']
plt.rcParams['axes.unicode_minus'] = False
CHINESE_FONT = 'Microsoft JhengHei'
except:
CHINESE_FONT = 'sans-serif'
# --- ASK 調變函數 ---
def generate_ask_waveform(fm_hz, fc_hz, modulation_percentage, duration_sec=0.01):
"""
生成 ASK 調變波形數據。
fm_hz: 基帶信號頻率 (例如 1 kHz)
fc_hz: 載波信號頻率 (例如 2.45 GHz 或可視化頻率)
modulation_percentage: 調變百分比 (0 到 100)
duration_sec: 繪圖總時長
"""
try:
# 將百分比轉換為調變指數 m (0 到 1)
m = modulation_percentage / 100.0
# 為了清晰顯示,我們需要足夠的採樣點數。
fs = max(20000, 100 * fc_hz)
# 限制採樣頻率以防止程式在極高頻率下消耗過多資源
if fs > 1e6:
fs = 1e6
t = np.linspace(0, duration_sec, int(fs * duration_sec), endpoint=False)
# 1. 基帶信號 (數位信號 0 和 1)
# 使用方波模擬,確保每個週期內有 0 和 1 的切換
bit_duration = 1 / fm_hz
digital_signal = np.where((t % bit_duration) < (bit_duration / 2), 1.0, 0.0)
# 2. 載波信號
carrier_signal = np.cos(2 * np.pi * fc_hz * t)
# 3. ASK 調變
# 振幅 A(t): 當 digital_signal=1 時,振幅為 1;當 digital_signal=0 時,振幅為 1-m
amplitude_envelope = (1 - m) + m * digital_signal
# 最終 ASK 信號
ask_signal = amplitude_envelope * carrier_signal
return t, digital_signal, carrier_signal, ask_signal, fs
except Exception as e:
print(f"調變計算錯誤: {e}")
return None, None, None, None, None
# --- 繪圖函數 ---
def plot_waveform(t, digital_signal, carrier_signal, ask_signal, fs, ax_list):
"""繪製三個信號波形,並優化 Y 軸範圍。"""
# 清除舊圖
for ax in ax_list:
ax.clear()
# 1. 基帶信號 (數位信號)
ax_list[0].plot(t * 1000, digital_signal, color='red', label='基帶數位信號')
ax_list[0].set_title('基帶信號 ($f_m$)', fontproperties=CHINESE_FONT)
ax_list[0].set_ylabel('振幅', fontproperties=CHINESE_FONT)
# 優化 Y 軸範圍,讓 0 和 1 電平清晰顯示
ax_list[0].set_ylim(-0.1, 1.1)
ax_list[0].grid(True, linestyle=':')
ax_list[0].legend(loc='upper right')
# 2. 載波信號 (用於視覺化,可能是模擬頻率)
ax_list[1].plot(t * 1000, carrier_signal, color='blue', label='載波信號')
ax_list[1].set_title(f'載波信號 ($f_c$ = {float(entry_fc_plot.get()):.2f} Hz)', fontproperties=CHINESE_FONT)
ax_list[1].set_ylabel('振幅', fontproperties=CHINESE_FONT)
# 設置 Y 軸範圍為標準的正負 1 振幅
ax_list[1].set_ylim(-1.1, 1.1)
ax_list[1].grid(True, linestyle=':')
ax_list[1].legend(loc='upper right')
# 3. ASK 調變信號
ax_list[2].plot(t * 1000, ask_signal, color='purple', label='ASK 調變信號')
ax_list[2].set_title(f'ASK 調變信號 (m={float(entry_m.get()):.1f}%)', fontproperties=CHINESE_FONT)
ax_list[2].set_xlabel('時間 [ms]', fontproperties=CHINESE_FONT)
ax_list[2].set_ylabel('振幅', fontproperties=CHINESE_FONT)
# 設置 Y 軸範圍,略大於最大振幅
max_amp = np.max(np.abs(ask_signal))
ax_list[2].set_ylim(-max_amp * 1.1, max_amp * 1.1)
ax_list[2].grid(True, linestyle=':')
ax_list[2].legend(loc='upper right')
# 調整佈局,確保子圖間無重疊,且利用整個 Figure 高度
fig.tight_layout()
# 重新繪製圖形
canvas.draw()
# --- 主程式介面和執行 ---
def run_ask_modulation():
"""從輸入框獲取數值並執行計算與繪圖。"""
try:
fm_khz = float(entry_fm.get()) # 基帶信號頻率 (kHz)
fc_input = float(entry_fc_input.get()) # 載波信號頻率 (MHz/GHz - 僅供輸入記錄)
m = float(entry_m.get()) # 調變百分比 (%)
# 單位轉換
fm_hz = fm_khz * 1000 # 基帶信號 Hz
# --- 載波頻率處理 (視覺化) ---
# 如果輸入的載波頻率很高 (例如 >= 1000 MHz/GHz), 使用模擬載波頻率
if fc_input >= 1000:
# 使用基帶信號頻率的 50 倍作為視覺化載波,例如 1kHz -> 50kHz
fc_plot_hz = 50 * fm_hz
# 更新視覺化頻率顯示,並發出警告
entry_fc_plot.set(f"{fc_plot_hz:.2f}")
result_text.set(
f"⚠️ 警告: 輸入 $f_c$={fc_input} MHz/GHz 過高,\n"
f"繪圖時使用模擬載波 $f_c$ = {fc_plot_hz/1000:.1f} kHz。"
)
else:
# 假設輸入的是 kHz 或 MHz (如果數值不大)
fc_plot_hz = fc_input * 1000
entry_fc_plot.set(f"{fc_plot_hz:.2f}")
result_text.set("")
if fm_hz <= 0 or fc_plot_hz <= 0 or m < 0 or m > 100:
result_text.set("輸入值必須有效: 頻率 > 0, 調變百分比 0-100。")
return
# 計算波形數據
t, digital_signal, carrier_signal, ask_signal, fs = generate_ask_waveform(fm_hz, fc_plot_hz, m)
if t is not None:
# 執行繪圖
plot_waveform(t, digital_signal, carrier_signal, ask_signal, fs, [ax1, ax2, ax3])
except ValueError:
result_text.set("輸入值無效,請確保輸入數字。")
except Exception as e:
result_text.set(f"發生未預期錯誤: {e}")
# 設置 Tkinter 視窗
root = tk.Tk()
root.title("ASK 調變波形分析儀")
# 設置輸入框框架
input_frame = ttk.Frame(root, padding="10")
input_frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
# --- 輸入控件 ---
# 信號頻率 fm (kHz)
ttk.Label(input_frame, text="信號 $f_m$ (kHz):").grid(row=0, column=0, sticky=tk.W, padx=5, pady=5)
entry_fm = ttk.Entry(input_frame, width=15)
entry_fm.grid(row=0, column=1, padx=5, pady=5)
entry_fm.insert(0, "1") # 預設值 1 kHz
# 載波頻率 fc (MHz/GHz - 僅供輸入記錄)
ttk.Label(input_frame, text="載波 $f_c$ (MHz/GHz):").grid(row=1, column=0, sticky=tk.W, padx=5, pady=5)
entry_fc_input = ttk.Entry(input_frame, width=15)
entry_fc_input.grid(row=1, column=1, padx=5, pady=5)
entry_fc_input.insert(0, "2450") # 預設值 2.45 GHz -> 2450 MHz/GHz
# 隱藏或用於顯示模擬頻率 (Hz)
entry_fc_plot = tk.StringVar(value="")
# 調變百分比 m (%)
ttk.Label(input_frame, text="調變百分比 m (%):").grid(row=2, column=0, sticky=tk.W, padx=5, pady=5)
entry_m = ttk.Entry(input_frame, width=15)
entry_m.grid(row=2, column=1, padx=5, pady=5)
entry_m.insert(0, "80") # 預設值 80%
# 計算按鈕
ttk.Button(input_frame, text="執行 ASK 調變並繪圖", command=run_ask_modulation).grid(row=3, column=0, columnspan=2, pady=10)
# 結果/警告顯示
result_frame = ttk.Frame(root, padding="10")
result_frame.grid(row=0, column=1, sticky=(tk.W, tk.E, tk.N, tk.S))
result_text = tk.StringVar()
ttk.Label(result_frame, textvariable=result_text, justify=tk.LEFT, font=(CHINESE_FONT, 10), foreground='red').grid(row=0, column=0, sticky=tk.W)
# 繪圖區設置 (Matplotlib)
# 增大 figure 尺寸以提供更多繪圖空間
fig = Figure(figsize=(10, 9), dpi=100)
ax1 = fig.add_subplot(311) # 1. 基帶信號
ax2 = fig.add_subplot(312) # 2. 載波信號 (視覺化用)
ax3 = fig.add_subplot(313) # 3. ASK 調變信號
# 將 Matplotlib 圖形嵌入 Tkinter 介面
canvas = FigureCanvasTkAgg(fig, master=root)
canvas_widget = canvas.get_tk_widget()
canvas_widget.grid(row=1, column=0, columnspan=2, padx=10, pady=10)
# 執行一次初始計算和繪圖
run_ask_modulation()
# 啟動 Tkinter 主循環
root.mainloop()

沒有留言:
張貼留言