2. 控制软件指令下发无响应的分层排查

故障现象与分层假设

上位机下发一段脉冲序列后,AWG 面板无输出、示波器无波形、采集端无返回。此时不要急于拆机或重装驱动,先把"指令从软件到仪器"的路径切成四层:软件层(序列编译与下发逻辑)、驱动层(VISA/厂商驱动与句柄状态)、总线层(LAN/USB/GPIB 连接与超时)、硬件层(通道使能、触发源、输出负载)。排查原则是自下而上确认通路,自上而下缩小范围:先用最小复现脚本确认"指令是否真的到达仪器",再用仪器面板状态反推"仪器是否真的执行"。

软件层 序列编译 / 下发调用 句柄打开 / 错误码捕获 驱动层 VISA / 厂商驱动 超时 / 会话状态 总线层 LAN / USB / GPIB 地址 / 连接 / 延迟 硬件层 通道使能 / 触发源 输出负载 / 幅度偏置 最小复现脚本(隔离变量) ① 打开会话 → 查询 *IDN? 确认仪器在线 ② 仅下发单条 :OUTP1 ON,读回状态 ③ 下发最小脉冲序列,读 :SYST:ERR? ④ 记录每步耗时与返回码 仪器面板状态确认 通道指示灯 / 输出使能状态 触发源设置(内/外/总线) 错误队列 / 事件日志 采样率 / 幅度 / 偏置读数 故障归属判断 *IDN? 无返回 → 总线/驱动层 有返回但无输出 → 硬件配置层 错误码非零 → 软件/驱动层 面板状态异常 → 硬件层

最小复现脚本:把"无响应"变成可读的返回码

排障的第一步不是改配置,而是写一个只做一件事的脚本:确认会话能打开、仪器能应答、单条指令能执行。下面用 PyVISA 给出可直接运行的最小复现脚本,关键点在于每一步都打印耗时与返回,让"卡在哪一层"变成可观测的事实。

import time
import pyvisa

RESOURCE = "TCPIP0::192.168.1.50::inst0::INSTR"  # 示例地址,按实际替换

rm = pyvisa.ResourceManager()

def step(name, fn):
    t0 = time.perf_counter()
    try:
        result = fn()
        dt = (time.perf_counter() - t0) * 1000
        print(f"[OK]   {name:28s} {dt:7.1f} ms  -> {result!r}")
        return result
    except Exception as e:
        dt = (time.perf_counter() - t0) * 1000
        print(f"[FAIL] {name:28s} {dt:7.1f} ms  -> {type(e).__name__}: {e}")
        raise

inst = step("open_resource", lambda: rm.open_resource(RESOURCE))
inst.timeout = 3000  # 3 s,便于快速暴露总线层超时

step("query *IDN?", lambda: inst.query("*IDN?").strip())
step("clear status", lambda: inst.write("*CLS"))
step("output1 ON", lambda: inst.write(":OUTPut1:STATe ON"))
step("read output state", lambda: inst.query(":OUTPut1:STATe?").strip())
step("load minimal pulse", lambda: inst.write(
    ":SOURce1:FUNCtion:PULSe;"
    ":SOURce1:PULSe:PERiod 1e-6;"
    ":SOURce1:PULSe:WIDTh 100e-9;"
    ":SOURce1:VOLTage:AMPLitude 0.5"
))
step("check error queue", lambda: inst.query(":SYSTem:ERRor?").strip())
inst.close()
脚本中 inst.timeout = 3000 是刻意设短:若 *IDN? 在 3 秒内超时,说明问题在总线层或驱动层,而不是脉冲序列本身。若 *IDN? 正常但 :OUTPut1:STATe? 返回 0,则指令已到达仪器但被硬件配置拒绝。

逐层隔离的判断依据

观察点正常表现异常表现归属层级
open_resource毫秒级返回句柄超时或报 VI_ERROR_RSRC_NFOUND总线层(地址/连接)
*IDN?返回厂商型号字符串超时、乱码、空串总线层 / 驱动层
:OUTPut1:STATe?返回 1返回 0 或报错硬件层(通道使能)
:SYSTem:ERRor?0,"No error"非零错误码软件层(指令语法/参数)
面板触发源与脚本设定一致仍为外部触发且无外触发信号硬件层(触发配置)

面板状态反查:仪器到底执行了什么

脚本只能告诉你"指令发出去了",不能告诉你"仪器执行了"。因此必须对照面板:若 :OUTPut1:STATe? 返回 1 但面板通道灯不亮,说明状态查询与实际硬件状态不一致,优先怀疑驱动层缓存或固件状态机;若面板显示触发源为"External"而脚本未配置触发,则脉冲序列在等待一个永远不会到来的外触发,表现为"无输出"而非"报错"。这类静默失败最容易被误判为硬件损坏。

常见误判:看到"无输出"就直接更换 AWG 通道或线缆。实际上本例中约一半的"无响应"来自触发源配置不匹配或输出负载设为高阻而实际接 50 Ω,属于硬件层配置问题,换硬件并不能解决。

隔离结论与下一步

按上述顺序执行后,故障会被收敛到唯一一层:总线层问题表现为连接/地址/超时;驱动层问题表现为会话异常或状态查询与实际不符;软件层问题表现为错误队列非零(指令语法、参数越界);硬件层问题表现为通道使能、触发源、负载或幅度配置与预期不符。确认层级后,再进入该层的专项修复,避免在错误的层级上反复试错。