編寫信號發(fā)生器(Signal Generator)的測試腳本需要結(jié)合硬件控制、測試邏輯和結(jié)果分析。以下是詳細(xì)的步驟和代碼示例(以Python為例),涵蓋從基礎(chǔ)控制到自動化測試的實(shí)現(xiàn)。
bashpip install pyvisa numpy matplotlib pandas
使用 PyVISA 通過 SCPI命令 控制信號發(fā)生器。
pythonimport pyvisa
class SignalGenerator: def __init__(self, resource): self.rm = pyvisa.ResourceManager() self.device = self.rm.open_resource(resource) self.device.timeout = 5000 # 超時(shí)時(shí)間(ms) self.device.read_termination = 'n' # 讀取終止符 self.device.write_termination = 'n' # 寫入終止符
def close(self): self.device.close()
pythonclass SignalGenerator: # ...(前述初始化代碼)
def set_frequency(self, freq_hz): """設(shè)置頻率(Hz)""" self.device.write(f"FREQ {freq_hz}Hz")
def set_power(self, power_dbm): """設(shè)置功率(dBm)""" self.device.write(f"POW {power_dbm}dBm")
def enable_output(self, state=True): """開啟/關(guān)閉輸出""" self.device.write(f"OUTP {'ON' if state else 'OFF'}")
def query(self, cmd): """發(fā)送查詢命令并返回結(jié)果""" return self.device.query(cmd).strip()
# 示例:設(shè)置調(diào)制(AM調(diào)制) def set_am_modulation(self, depth_percent): self.device.write("MOD OFF") # 先關(guān)閉調(diào)制 self.device.write("MOD:AM:STAT ON") # 開啟AM調(diào)制 self.device.write(f"MOD:AM:DEP {depth_percent}%") # 設(shè)置調(diào)制深度
使用JSON文件管理測試參數(shù),便于動態(tài)加載:
json// test_config.json{"frequency_list": [1e6, 10e6, 100e6], // 測試頻率點(diǎn)(Hz)"power_levels": [-20, 0, 10], // 測試功率(dBm)"modulation": {"type": "AM","depth": 30},"dwell_time_sec": 2 // 每個(gè)參數(shù)點(diǎn)的停留時(shí)間}
pythonimport json import time import pandas as pd from datetime import datetime
class AutomatedTest: def __init__(self, config_file): with open(config_file) as f: self.config = json.load(f) self.sg = SignalGenerator("TCPIP0::192.168.1.100::inst0::INSTR") # 替換為實(shí)際地址 self.results = []
def run_test(self): for freq in self.config["frequency_list"]: for power in self.config["power_levels"]: # 設(shè)置信號發(fā)生器參數(shù) self.sg.set_frequency(freq) self.sg.set_power(power)
# 可選:設(shè)置調(diào)制 if "modulation" in self.config: self._setup_modulation()
# 開啟輸出并等待穩(wěn)定 self.sg.enable_output(True) time.sleep(self.config["dwell_time_sec"])
# 采集結(jié)果(示例:讀取實(shí)際輸出值) actual_freq = float(self.sg.query("FREQ?")) actual_power = float(self.sg.query("POW?"))
# 記錄結(jié)果 self.results.append({ "Timestamp": datetime.now(), "Set_Frequency_Hz": freq, "Actual_Frequency_Hz": actual_freq, "Set_Power_dBm": power, "Actual_Power_dBm": actual_power, "Status": "PASS" if abs(actual_freq - freq) < 1e3 else "FAIL" })
# 關(guān)閉輸出(可選) self.sg.enable_output(False)
def _setup_modulation(self): mod = self.config["modulation"] if mod["type"] == "AM": self.sg.set_am_modulation(mod["depth"])
def save_results(self, filename): df = pd.DataFrame(self.results) df.to_csv(filename, index=False) print(f"Results saved to {filename}")
def close(self): self.sg.close()
# 執(zhí)行測試 if __name__ == "__main__": test = AutomatedTest("test_config.json") try: test.run_test() test.save_results("test_results.csv") finally: test.close()
pythonclass MultiDeviceTest: def __init__(self): self.sg = SignalGenerator("TCPIP0::192.168.1.100::inst0::INSTR") self.scope = ScopeController("TCPIP0::192.168.1.101::inst0::INSTR") # 示波器控制類
def measure_output(self): self.sg.enable_output(True) time.sleep(1) measured_power = self.scope.measure_power() # 偽代碼:通過示波器測量實(shí)際功率 return measured_power
pythondef adaptive_test():initial_power = -20while initial_power <= 10:sg.set_power(initial_power)measured = measure_dut_output() # 偽代碼:測量被測設(shè)備輸出if measured < THRESHOLD:initial_power += 2 # 動態(tài)調(diào)整功率else:break
pythonimport matplotlib.pyplot as plt
def generate_report(csv_file): df = pd.read_csv(csv_file)
# 繪制頻率誤差圖 plt.figure(figsize=(10, 5)) plt.plot(df["Set_Frequency_Hz"], df["Actual_Frequency_Hz"] - df["Set_Frequency_Hz"], 'o-') plt.xlabel("Set Frequency (Hz)") plt.ylabel("Frequency Error (Hz)") plt.title("Frequency Accuracy Test") plt.grid() plt.savefig("frequency_accuracy.png") plt.close()
錯(cuò)誤處理
pythondef safe_query(device, cmd, retries=3):for _ in range(retries):try:return device.query(cmd)except pyvisa.Error as e:time.sleep(1)raise Exception(f"Command {cmd} failed after {retries} retries")
日志記錄
pythonimport logginglogging.basicConfig(filename='test.log', level=logging.DEBUG, format='%(asctime)s - %(message)s')
性能優(yōu)化
SOUR:LIST:FREQ命令)。asyncio)控制多臺設(shè)備。python# main.py from automated_test import AutomatedTest import argparse
if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("--config", default="test_config.json") parser.add_argument("--output", default="test_results.csv") args = parser.parse_args()
test = AutomatedTest(args.config) try: test.run_test() test.save_results(args.output) generate_report(args.output) # 生成圖表 finally: test.close()
通過以上方法,可以高效實(shí)現(xiàn)信號發(fā)生器的自動化測試,適用于生產(chǎn)校驗(yàn)、研發(fā)驗(yàn)證等場景。