RFID 負載調變
在 RFID(特別是 ISO/IEC 14443 標準)中,13.56 MHz 是載波(Carrier),而 212 kHz 的**副載波(Subcarrier)**則是用於從卡片(PICC)回傳資料到讀卡機(PCD)時的負載調變。
載波 (f_c):13.56MHz。
副載波 (f_s):212kHz}即 f_c / 64)。
調變方式:資料(Bit Stream)先調變在副載波上(通常是 BPSK 或 OOK),然後副載波再透過負載調變掛載到載波上。
Python Tkinter 模擬程式
為了能在螢幕上清楚看見波形,我們在繪圖時會按比例縮小頻率(否則13.56 MHz 的波紋太密會變成色塊),但保持運算邏輯正確。
import tkinter as tk
from tkinter import messagebox
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import platform
# --- 中文與環境設定 ---
def setup_matplotlib_fonts():
sys_plat = platform.system()
if sys_plat == "Windows":
plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei']
elif sys_plat == "Darwin":
plt.rcParams['font.sans-serif'] = ['Heiti TC']
plt.rcParams['axes.unicode_minus'] = False
setup_matplotlib_fonts()
class RFIDModulationApp:
def __init__(self, root):
self.root = root
self.root.title("RFID 13.56MHz 副載波調變模擬器 (212kHz)")
self.root.geometry("1100x850")
self.create_widgets()
def create_widgets(self):
# 控制面板
ctrl = tk.LabelFrame(self.root, text=" 參數設定 ", padx=10, pady=10)
ctrl.pack(side=tk.LEFT, fill=tk.Y, padx=10, pady=10)
tk.Label(ctrl, text="資料位元 (例如 101):").pack(anchor=tk.W)
self.ent_bits = tk.Entry(ctrl, width=15)
self.ent_bits.insert(0, "101")
self.ent_bits.pack(pady=5)
tk.Label(ctrl, text="載波頻率 (fc) MHz:").pack(anchor=tk.W, pady=(10,0))
self.ent_fc = tk.Entry(ctrl, width=15)
self.ent_fc.insert(0, "13.56") # 僅作顯示參考
self.ent_fc.pack(pady=5)
tk.Label(ctrl, text="副載波頻率 (fs) kHz:").pack(anchor=tk.W, pady=(10,0))
self.ent_fs = tk.Entry(ctrl, width=15)
self.ent_fs.insert(0, "212")
self.ent_fs.pack(pady=5)
tk.Button(ctrl, text="生成調變波形", command=self.update_plot,
bg="#E91E63", fg="white", font=("Arial", 10, "bold")).pack(fill=tk.X, pady=20)
# 說明
note = ("【RFID 物理層說明】\n"
"1. 副載波 fs = fc / 64\n"
"2. 卡片回傳資料時,會以\n"
" 212kHz 切換負載阻抗。\n"
"3. 下圖示範副載波如何\n"
" 調變 13.56MHz 的振幅。")
tk.Label(ctrl, text=note, justify=tk.LEFT, fg="#666").pack(side=tk.BOTTOM)
# 繪圖區
self.fig, self.axs = plt.subplots(3, 1, figsize=(8, 10))
self.canvas = FigureCanvasTkAgg(self.fig, master=self.root)
self.canvas.get_tk_widget().pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=10, pady=10)
def update_plot(self):
try:
bits = [int(b) for b in self.ent_bits.get() if b in '01']
if not bits: raise ValueError("請輸入有效位元")
# 為方便視覺觀察,對頻率進行比例縮放 (13.56Mhz太高無法在畫面上繪圖)
# 我們假設 fc = 1000Hz, fs = 1000/8 = 125Hz 進行演示
fs_val = 212 # kHz
bit_rate = 106 # kbps (RFID標準速率)
t_bit = 1.0 # 每個位元的標準化時間
fs_visual = 16 # 在一個位元內的副載波週數
fc_visual = 128 # 在一個位元內的載波週數
samples = 2000
t = np.linspace(0, len(bits), len(bits) * samples)
carrier_wave = np.sin(2 * np.pi * fc_visual * t)
subcarrier_signal = np.zeros_like(t)
modulated_wave = np.zeros_like(t)
for i, bit in enumerate(bits):
start = i * samples
end = (i + 1) * samples
# 1. 生成副載波 (在該位元區間內)
# RFID 常見的副載波調變:如果 bit=1,副載波發送;bit=0,副載波暫停 (OOK範例)
if bit == 1:
subcarrier_signal[start:end] = np.sign(np.sin(2 * np.pi * fs_visual * t[start:end]))
else:
subcarrier_signal[start:end] = 0
# 2. 負載調變效果 (副載波改變載波的振幅深淺)
# 振幅變化量約為 10% (RFID 典型負載調變深度)
modulation_depth = 0.3 # 為了視覺效果加強到 0.3
amplitude = 1.0 + modulation_depth * subcarrier_signal[start:end]
modulated_wave[start:end] = amplitude * carrier_wave[start:end]
# 繪圖
for ax in self.axs: ax.clear()
# 子圖 1: 原始資料與副載波
self.axs[0].plot(t, subcarrier_signal, color='blue', lw=1)
self.axs[0].set_title(f"副載波信號 (212kHz 邏輯代表)")
self.axs[0].set_ylabel("振幅")
# 子圖 2: 載波
self.axs[1].plot(t[:500], carrier_wave[:500], color='gray', alpha=0.5)
self.axs[1].set_title("13.56MHz 載波 (局部放大)")
# 子圖 3: 最終調變信號 (負載調變)
self.axs[2].plot(t, modulated_wave, color='red', lw=0.8)
self.axs[2].set_title("RFID 負載調變結果 (副載波掛載於載波振幅上)")
self.axs[2].set_xlabel("位元時間")
for ax in self.axs: ax.grid(True, alpha=0.3)
self.fig.tight_layout()
self.canvas.draw()
except Exception as e:
messagebox.showerror("錯誤", f"參數錯誤: {e}")
if __name__ == "__main__":
root = tk.Tk()
app = RFIDModulationApp(root)
root.mainloop()

沒有留言:
張貼留言