4. 测试仪器程控基础与SCPI指令
光模块自动化测试平台的核心能力,是把光功率计、可调衰减器、误码仪等仪器从“手动旋钮”变成“程序可寻址、可读回、可判定”的受控对象。实现这一点的技术底座是 SCPI 指令、VISA 通信层与 PyVISA 编程接口。本节围绕这三层展开,并补充连接超时、错误查询与状态寄存器等工程细节。
SCPI 指令结构:一棵可预测的命令树
SCPI(Standard Commands for Programmable Instruments)建立在 IEEE 488.2 通用命令之上,采用树状层级结构。命令由冒号分隔的路径组成,例如 :SOURce:POWer:LEVel:IMMediate:AMPLitude。SCPI 的关键规则是:大写字母为缩写必需部分,小写可省略,因此上述命令可写作 :SOUR:POW:LEV:IMM:AMPL。命令分为两类:设置类(无问号,如 :POW 3.0)和查询类(以问号结尾,如 :POW?),查询会返回响应,必须由程序读取,否则会残留在输出缓冲区中污染后续查询。
参数与单位也需注意。SCPI 允许在数值后附加单位后缀,如 DBM、MW、NM、HZ,仪器会按后缀换算。例如设置光功率计波长 :SENS:WAV 1310NM,设置衰减器衰减量 :INP:ATT 10DB。若省略单位,仪器使用当前默认单位,容易产生歧义,工程代码中建议始终显式带单位。
常用仪器控制命令
光功率计的核心是波长设置与功率读取。不同波长下光电探测器响应度不同,因此测试前必须设置与光源一致的波长。典型流程::SENS:WAV 1310NM 设置波长,:SENS:POW:UNIT DBM 指定单位,随后 :READ? 返回当前功率。若返回 -3.25,表示 -3.25 dBm。部分仪器支持 :INIT 触发一次测量后再 :FETC? 取结果,适合需要精确同步的场景。
可调衰减器用于模拟链路损耗,验证接收灵敏度。设置衰减量用 :INP:ATT 10DB,回读用 :INP:ATT?。工程上建议“设置后回读”,因为机械式或步进式衰减器存在最小步进(如 0.1 dB),写入 10.05 dB 可能被量化为 10.1 dB,回读可确认实际生效值。输出开关 :OUTP:STAT ON/OFF 用于保护被测件,切换衰减量前可先关闭输出。
误码仪负责发送码型并统计误码。发送侧设置码型 :SOUR:DATA PRBS31,接收侧查询误码率 :SENS:ERR?、误码数 :SENS:ERR:COUN?、速率 :SENS:RATE?。误码测试需要先复位计数器 :SENS:ERR:RES,再等待统计时间,最后读取。若误码率为 0 但误码数不为 0,说明统计窗口内误码数极少,需结合总比特数判断是否可信。
VISA 库与 PyVISA 使用
VISA(Virtual Instrument Software Architecture)是仪器通信的统一抽象层,屏蔽 GPIB、USB、LAN、串口等物理差异。PyVISA 是 VISA 的 Python 绑定,安装后需配合后端(如 NI-VISA 或 pyvisa-py)。基本用法如下:
import pyvisa
rm = pyvisa.ResourceManager()
print(rm.list_resources())
# ('TCPIP0::192.168.1.10::inst0::INSTR', 'ASRL3::INSTR')
opm = rm.open_resource('TCPIP0::192.168.1.10::inst0::INSTR')
opm.timeout = 3000 # 单位 ms
opm.write(':SENS:WAV 1310NM')
opm.write(':SENS:POW:UNIT DBM')
power = float(opm.query(':READ?'))
print(power) # 例如 -3.25
opm.close()
资源地址格式为 接口类型::地址::INSTR。LAN 仪器常用 TCPIP0::IP::inst0::INSTR,串口为 ASRL3::INSTR,USB 为 USB0::0x1234::0x5678::SN::INSTR。若 list_resources() 为空,通常是后端未安装或仪器未上电。
仪器连接与超时处理
超时是自动化测试最常见的故障。PyVISA 的 timeout 属性默认可能为 2000 ms,对于需要长时间统计的误码测试明显不足。建议按仪器类型分别设置:光功率计 2000 ms,衰减器 3000 ms,误码仪 10000 ms 以上。超时后 PyVISA 抛出 VisaIOError,应捕获并记录,而不是让程序崩溃。
try:
ber = float(ber_meter.query(':SENS:ERR?'))
except pyvisa.errors.VisaIOError as e:
print('查询超时:', e)
ber_meter.clear() # 清空缓冲区,恢复会话
超时后必须调用 clear() 或 read_raw() 清空残留数据,否则下一次查询可能读到上一次的旧值。这是“超时后数据错位”的典型根因。
错误查询与状态寄存器
SCPI 提供两层错误机制。第一层是错误队列:SYST:ERR? 返回最早的一条错误,格式为 <错误码>,"<描述>",如 0,"No error" 表示无错误,-113,"Undefined header" 表示命令头拼写错误。建议每次关键操作后查询一次,直到返回 0 为止。
第二层是状态寄存器。IEEE 488.2 定义了状态字节寄存器(STB),其中 bit5 为 ESB(事件状态位),bit6 为 MSS(主状态汇总)。通过 *ESE 32 使能 ESB,再用 *STB? 读取状态字节,可判断是否发生过错误事件。更细的故障可用 STAT:QUES:EVEN? 查询 questionable 状态寄存器。工程实践中,建议在测试脚本开头执行 *CLS 清状态、*RST 复位仪器,再开始正式测试,避免历史错误干扰判断。
*RST → *CLS → 设置超时 → 设置波长/单位/衰减量 → 回读确认 → 开始测试。每一步都应有回读或错误查询作为确认,而不是“发完即认为成功”。
SYST:ERR?,程序会“看起来正常”但实际未生效,导致测试结果不可信。