1. 光模块自动化测试环境搭建与验证
任务目标
用 Python + PyVISA 搭建一套最小可运行的光模块自动化测试台控制层:通过 LAN/GPIB 统一寻址可编程光衰减器、光功率计、误码仪、示波器和待测光模块(DUT),逐个执行 *IDN? 身份查询,并读取光功率计与衰减器的关键状态,确认远程通信链路全部正常。
环境与依赖
- Python 3.9+,安装
pip install pyvisa pyvisa-py(无厂商 VISA 时用 pyvisa-py 后端)。 - 各仪器已配置固定 IP 或 GPIB 地址,且与本机在同一网段/总线可达。
- DUT 通过其控制接口(示例按 SCPI over TCP 处理)暴露可寻址资源串。
实现思路
用一张“资源名 → 角色”的配置表描述测试台拓扑,InstrumentRack 负责按配置打开 VISA 会话并缓存句柄;verify_all() 对每台仪器发送 *IDN? 并校验返回非空;随后对衰减器设置一个衰减值、对光功率计读取功率,作为“可读写”验证。任一环节异常都会被记录并计入失败,最终汇总通过/失败清单。
关键完整代码
import pyvisa
# 资源名 → 角色。请按实际地址替换(LAN 用 TCPIP0::<ip>::inst0::INSTR,GPIB 用 GPIB0::<addr>::INSTR)
RACK = {
"attenuator": "TCPIP0::192.168.1.31::inst0::INSTR",
"power_meter": "TCPIP0::192.168.1.32::inst0::INSTR",
"ber_tester": "TCPIP0::192.168.1.33::inst0::INSTR",
"oscilloscope": "TCPIP0::192.168.1.34::inst0::INSTR",
"dut": "TCPIP0::192.168.1.40::inst0::INSTR",
}
class InstrumentRack:
def __init__(self, mapping, timeout_ms=5000):
self.rm = pyvisa.ResourceManager("@py") # 无厂商 VISA 时用 pyvisa-py 后端
self.timeout_ms = timeout_ms
self.mapping = mapping
self.sessions = {}
def open_all(self):
for role, res in self.mapping.items():
inst = self.rm.open_resource(res)
inst.timeout = self.timeout_ms
inst.write_termination = "\n"
inst.read_termination = "\n"
self.sessions[role] = inst
def query(self, role, cmd):
return self.sessions[role].query(cmd).strip()
def write(self, role, cmd):
self.sessions[role].write(cmd)
def close_all(self):
for inst in self.sessions.values():
inst.close()
self.rm.close()
def verify_all(rack):
results = {}
for role in rack.mapping:
try:
idn = rack.query(role, "*IDN?")
results[role] = ("PASS", idn) if idn else ("FAIL", "empty *IDN?")
except Exception as exc: # 通信超时/地址错误等
results[role] = ("FAIL", repr(exc))
# 读写验证:衰减器设 10 dB,功率计读功率
try:
rack.write("attenuator", "ATT 10")
results["attenuator_rw"] = ("PASS", rack.query("attenuator", "ATT?"))
except Exception as exc:
results["attenuator_rw"] = ("FAIL", repr(exc))
try:
results["power_meter_rw"] = ("PASS", rack.query("power_meter", "READ?"))
except Exception as exc:
results["power_meter_rw"] = ("FAIL", repr(exc))
return results
if __name__ == "__main__":
rack = InstrumentRack(RACK)
try:
rack.open_all()
report = verify_all(rack)
finally:
rack.close_all()
failed = [k for k, (s, _) in report.items() if s == "FAIL"]
for k, (s, info) in report.items():
print(f"{s:4} {k:16} {info}")
print("\nRESULT:", "ALL PASS" if not failed else f"FAILED: {failed}")
运行与验证
- 把
RACK中的资源串改成现场实际地址,保存为rack_check.py。 - 执行
python rack_check.py。 - 观察输出:每台仪器应打印
PASS及其*IDN?返回串;衰减器与功率计额外出现attenuator_rw、power_meter_rw两行。 - 判定通过条件:末行输出
RESULT: ALL PASS。若出现FAILED: [...],对应角色即通信异常,需检查 IP/GPIB 地址、网段连通性或仪器远程模式是否开启。
注意:*IDN? 与 ATT/READ? 为通用示例命令,实际命令字以各仪器编程手册为准;若某仪器不支持某命令,会体现为该行 FAIL,属预期行为。