# SCPI instruments

> 使用 SCPI 的台式仪器，例如万用表、电源、电子负载和数据采集仪，通过 TCP、串行线路，或经由 VISA 的 USB 和 GPIB 连接：每种连接方式、“仪器”卡片、查询和写入命令、设备发现，以及两个完整示例。

**SCPI instruments** 驱动读写使用 SCPI 的台式仪器。SCPI 是 IEEE 488.2 测试设备的命令语言，覆盖万用表、电源、电子负载、数据采集仪（例如 Fluke 1586A Super-DAQ）、校准器，来自 Keysight、Rigol、Tektronix、Siglent、GW Instek、B&K Precision、Fluke 等厂商。每个点位向仪器发出一条查询，例如 `MEAS:VOLT:DC?` 或 `READ?`，并读取它的应答；被写入的点位发送一条带有数值的命令，例如 `VOLT 5`。这正是 LabVIEW 程序通过 VISA 进行的交互，只是在面板上设置，而不是在程序框图里连线；数值也像其他所有点位的数值一样，进入 Logic、仪表板，以及 [Process](process) 测试台的运行记录。

仪器通过以下三种方式之一连接，在创建它的设备时选定：

| 传输方式 | 如何连接仪器 | 适用于 |
| --- | --- | --- |
| **TCP（LXI 套接字）** | 仪器在其主机和端口上的 SCPI 套接字，大多数 LXI 仪器为 5025。本计算机上不需要安装任何东西。 | 带网口的仪器。 |
| **VISA（USB、GPIB、网络）** | 通过本计算机上安装的 VISA，按仪器的 VISA 资源名称连接。本产品不安装 VISA：只要装有 NI-VISA 或 Keysight IO Libraries Suite 之一，就使用它。 | 接在 USB 或 GPIB 接口上的仪器，或 VISA 按自己的名称连接的网络仪器。 |
| 在串行线路上 | 本驱动的一条串行线路，与线路上的其他仪器共用，一次只发一个请求。 | 带 RS-232 或 RS-485 接口的仪器。 |

串行线路上的仪器挂在它的线路下面，所以树的这一部分和 [Generic serial and TCP](driver-generic-serial-tcp) 一样读作**驱动 → 线路 → 设备 → 点位**。通过 TCP 或 VISA 连接的仪器挂在驱动下面，可以像任何其他驱动的设备一样归入文件夹，即**驱动 → 文件夹 → 设备 → 点位**。设备留在创建时所在的一侧：TCP 和 VISA 可以互换，但设备绝不会在线路和网络之间移动。

## 驱动页面 {#the-drivers-page}

标题栏下面那行写着“串行线路下挂共用一条总线的仪器，通过 TCP 或 VISA 连接的仪器直接挂在驱动下。添加一条线路或一台设备，然后打开它填写其查询。”，页面上下依次排着：

| 部分 | 包含什么 |
| --- | --- |
| **串行线路** | 驱动的线路，用标题右侧的**添加线路**增加：**线路**、**物理参数组**（端口 · 波特率 · 格式，不含超时，因为本驱动的线路没有超时）、**设备**、**状态**，以及打开、启用、禁用和删除操作。为空时显示“还没有串行线路。” |
| **扫描范围** | 发现设备在 VISA 列出的仪器之外还要询问的地址；见[设备发现](#discovery)。只为有“配置 Connector”权限的角色绘制。 |
| **设备** | 驱动的所有设备，包括线路上的设备，列与任何驱动的[设备表](connector-drivers#the-device-table)相同，用标题右侧的**添加设备**增加，它创建一台 TCP 设备。为空时显示“还没有设备。” |

标题栏在括号里显示设备数；只要有一条线路，树中的驱动行就会同时计数两层（“1 条线路 · 2 台设备”）。驱动的命令栏上有**发现设备**。右键单击驱动行会提供**添加设备**、**添加线路**、**新建文件夹**、**刷新**和**发现设备**，一条分隔线之后是**移除驱动**；在栏底的“新建…”菜单里，本驱动那一项提供**新建设备**、**新建串行线路**和**新建文件夹**，然后是它的线路、文件夹和设备。驱动添加之后就出现在树里的“驱动”文件夹下面，不论有没有线路或设备。

## 串行线路 {#serial-line}

本驱动的线路就是[串行线路](connector-lines)中描述的那种线路，字段与 [Generic serial and TCP](driver-generic-serial-tcp#serial-line) 驱动的线路相同。它的页面写着“一条物理串行总线：其上仪表共用的端口设置，一次只发一个请求。”，“物理线路”卡片包含**名称**、**串行端口**（带**刷新**）、**波特率**和**串行格式**，十种格式全部可选，其中 8 位的六种，7 位的四种。它没有传输模式、响应超时、最小事务间隔，也没有发现单元的卡片：每台仪器在自己的“仪器”卡片上说明什么结束它的消息、等待应答多久；仪器靠问它的内容区分，而不是靠地址，所以线路的“设备”表没有单元 ID 列。

在这里创建的线路一开始是禁用的，以便在端口打开之前输入端口设置；端口、波特率和格式只有在线路禁用时才能修改。在线路上或它的右键菜单里点**添加设备**，会在这条线路上创建一台本驱动的设备。线路永远属于创建它时所在的驱动：其他驱动的设备不会挂到它上面，一个端口只属于一条线路，无论线路属于哪个驱动。

驱动为线路上的所有仪器只打开一次端口，一次发送一个请求，等到应答后才发下一个。端口打开期间它保持 DTR 有效，因为通过 DTR 和 DSR 控制输出节奏的仪器（例如 Keysight 34401A 或 E36xx 电源）在 DTR 无效时什么也不发送。端口故障后，会在一段暂停后重新打开，只要故障持续，暂停时间就从 1 秒翻倍直到 1 分钟；端口上的每台仪器都会重新准备，像第一次连接时一样重新发送初始化命令。

## 设备 {#device}

### 连接 {#connection}

| 字段 | 含义 | 默认值 |
| --- | --- | --- |
| **传输方式** | 在驱动下创建的设备：**TCP（LXI 套接字）**，“工作站连接到仪器的 SCPI 套接字，即其主机和端口；大多数 LXI 仪器为 5025。”，或 **VISA（USB、GPIB、网络）**，“工作站通过本计算机上安装的 VISA，按 VISA 资源名称打开仪器。”两者可以互换；线路上的设备在这里显示它的线路。 | **TCP（LXI 套接字）** |
| **主机** | TCP：仪器的主机名或 IP 地址。 | 空 |
| **端口** | TCP：仪器应答 SCPI 的端口，1 到 65535。框留空时以灰色显示 5025，并按该端口连接仪器。 | 5025 |
| **VISA 资源** | VISA，取代主机和端口：“VISA 列出的仪器名称，例如 USB0::0x0957::0x1A07::MY12345678::INSTR 或 GPIB0::22::INSTR。发现设备会自动填入。”这就是 NI MAX 和 Keysight Connection Expert 为仪器显示的名称。 | 空 |
| **串行线路 · 固定** | 线路上的设备：线路名称及其下的端口、波特率和格式，只读。 | 添加它时所在的线路 |

新设备是一台 TCP 设备：它显示“尚未填写主机”，在有主机之前不会连接。VISA 设备不连接任何主机，也从不等待主机。切换到 VISA 会保留主机和端口，供切回 TCP 时使用；切换到 TCP 会保留资源。驱动无法处理的设备不会保存，操作记录条会说明原因：

| 你输入 | 操作记录条显示 |
| --- | --- |
| 1 到 65535 之外的端口 | “请输入 1 到 65535 之间的端口，或留空以使用 5025。” |
| VISA 但没有资源 | “请输入仪器的 VISA 资源，例如 USB0::0x0957::0x1A07::MY12345678::INSTR，或运行发现设备。” |
| 含有空格或普通 ASCII 以外字符的资源 | “VISA 资源中含有空格或普通 ASCII 以外的字符。请按 VISA 列出的样子输入。” |

标题栏显示的 Base URI 就是运行时地址：`scpi://tcp/<host>:<port>`、`scpi://visa/<resource>` 或 `scpi://serial/<line id>/<port>/<baud>/<format>`，后面依次跟着结束符（`term`）、响应超时（`timeout`）、写入确认（`check`）和初始化命令（`setup`，一条接一条，用 `%0A` 分隔）。线路上设备的副本留在那条线路上；TCP 或 VISA 设备的副本落在驱动本身这一层。

### “仪器”卡片 {#the-instrument-card}

在“连接”卡片下面，**仪器**卡片说明仪器是什么，以及工作站如何与它对话。

| 字段 | 含义 | 默认值 |
| --- | --- | --- |
| **标识（\*IDN?）** | 只读：“工作站连接时仪器对 \*IDN? 的应答：制造商、型号、序列号和固件版本。”在仪器应答之前显示“尚未应答”，设备不再连接时又回到这个显示。不应答 `*IDN?` 的仪器照样读取，只是没有标识。 | |
| **结束符** | **LF（换行）**、**CR LF（回车、换行）**或 **CR（回车）**：“结束每条发送的命令和每条读取的应答。几乎所有仪器都用 LF；部分串口仪器使用 CR LF 或 CR。” | **LF（换行）** |
| **响应超时（ms）** | 100 到 60000：“查询等待应答、写入等待仪器错误队列的时间。测量较慢时需要更长。” | 2000 |
| **写入确认** | “SCPI 不对任何命令作出确认，因此写入要在之后询问仪器来确认。”每个选项发送什么，见[写入](#writing)：**错误队列（SYST:ERR?）**、**无：发送即确认**，或者等命令执行完毕再查错误队列，即 **先确认完成，再查错误队列（\*OPC?、SYST:ERR?）**。 | **错误队列（SYST:ERR?）** |
| **初始化命令** | 每行一条命令，最多 32 条，每条最多 512 个字符：“工作站每次连接时按顺序发送，每行一条，例如 \*RST 或 CONF:VOLT:DC 10。它们引起的错误写入诊断日志。” | 空 |

工作站每次连接仪器，以及串行线路每次重新打开端口时，都按顺序发送：写入确认读取错误队列时先发 `*CLS`，然后是初始化命令，接着把错误队列读入诊断日志（初始化命令引起的错误记在那里，不会让设备停下），最后询问 `*IDN?`，其应答就是“标识”字段显示的内容。卡片不接受的值不会保存，操作记录条会说明原因：“响应超时必须在 100 到 60000 ms 之间。”、“某条初始化命令含有普通 ASCII 以外的字符（例如排版引号），任何仪器都无法读取。”或“初始化命令最多 32 条，每条最多 512 个字符。”SCPI 是普通 ASCII，所以从手册里复制来、带有排版引号或不换行空格的命令，会在输入时就被拒绝，而不是发给一台读不懂它的仪器。

### 本计算机上的 VISA {#visa-on-this-computer}

本产品不带 VISA，也不安装 VISA。VISA 设备通过本计算机上已有的 64 位 VISA 库（`visa64.dll`）打开仪器，NI-VISA（LabVIEW 会安装它）和 Keysight IO Libraries Suite 都会把这个库放到这里。只有 VISA 设备需要它：走 TCP 或串行线路的仪器不用它也能连接。工作站会自己检查这个库能否加载，不必等待设备：驱动的页面、VISA 设备的页面或智能体第一次询问时检查一次，缺少期间每 30 秒再检查一次。在 Connector 启动之前，不知道是否有 VISA，因此什么也不显示。缺少期间：

| 在哪里 | 显示什么 |
| --- | --- |
| VISA 设备的页面 | 一条注意提示“本计算机未安装 VISA”，以及下面的步骤。它的两个链接会在计算机的浏览器里打开 NI 和 Keysight 的页面。 |
| 驱动的页面 | 只要驱动至少有一台 VISA 设备，就显示同一条提示，并附上“安装之前，此驱动中走 VISA 的设备保持离线，配置保持不变；走 TCP 或串行线路的设备不受影响。”只有 TCP 设备和串行设备的驱动不显示。 |
| VISA 设备的最后一个错误 | 同样的步骤，与驱动自身的原因一样用英文写出。设备保持离线，配置保持不变。 |
| “传输方式”列表 | 仍然提供 VISA，这样可以在安装 VISA 之前先准备好设备。 |
| 发现设备 | 只询问在“扫描范围”卡片里输入的主机，并连同两个页面一起说明：“本计算机未安装 VISA，因此扫描无法通过它列出 USB、GPIB 或网络仪器，只询问输入的主机。要列出它们，请以管理员身份安装 64 位 VISA”，后面跟着 NI-VISA 和 Keysight IO Libraries Suite 的地址。这句话会留在结束扫描的那一行里。 |
| 智能体 | `driver_capabilities` 在 Scpi 驱动的 `prerequisite` 下给出这些步骤，`installed` 为 false，`neededBy` 指出 VISA 设备；`device_discover` 在 `cut` 里说明同样的内容。 |

安装方法：

1. 从 NI 的页面 [NI-VISA Download](https://www.ni.com/en/support/downloads/drivers/download.ni-visa.html) 下载 NI-VISA，或者从 Keysight 的页面 [IO Libraries Suite Downloads](https://www.keysight.com/us/en/lib/software-detail/computer-software/io-libraries-suite-downloads-2175637.html) 下载 Keysight IO Libraries Suite。
2. 两者任选其一即可，装有 LabVIEW 的计算机已经有 NI-VISA。NI 的页面在下载前要求用 NI 账户登录；Keysight 的页面直接链接到安装程序。请选择最新的 Windows 安装程序：在 64 位 Windows 上，两者都会安装 64 位 VISA，这是 Ganter Lab 唯一能识别的版本。
3. 从 C: 盘上的文件夹以管理员身份运行安装程序（Keysight 的安装程序不能从其他盘安装），并在它要求时重启计算机。

只安装了 32 位库（`visa32.dll`）的 VISA（例如为 32 位 Windows 制作的）不会被识别：Ganter Lab 只读取 64 位的 `visa64.dll`。

安装后 30 秒内，提示会消失，VISA 设备按现有配置连接，无需重启 Ganter Lab。带网络端口的仪器也可以不用 VISA，通过 TCP 连接。

## 点位寻址 {#tag-addressing}

本驱动的点位向它的仪器发出一条查询。它的**信号源**卡片包含：

| 字段 | 含义 | 默认值 |
| --- | --- | --- |
| **查询** | 点位要问的内容，按仪器编程手册的写法：`MEAS:VOLT:DC?`、`READ?`、`SOUR:VOLT?`、`OUTP?`。普通 ASCII，最多 512 个字符。只写点位什么也不问，也不需要查询。 | 必填 |
| **应答中的值** | 被读取的点位。“留空读取整个应答。填数字则读取逗号分隔应答中从 1 数起的那个值，例如 READ? 的第三个通道填 3。”框为空时显示“整个应答”。1 到 1000。 | 空 |
| **写入命令** | 被写入的点位：“写入时发送的内容，在数值所在位置放 {value}，例如 VOLT {value} 或 CURR {value:0.000}。Boolean 以 1 或 0 发送。对 Boolean 点位，不含 {value} 的命令（例如 \*TRG）在写入 true 时发送。” | 必填 |

点位的访问方式用不到的字段不会绘制，并保留它的值，等再次用到时使用。数据类型有 Boolean、Int32、Int64、Float、Double 和 String，默认 Float。字段无法成立的点位不会保存，点位页面会说明缺少什么：

| 你输入 | 点位页面显示 |
| --- | --- |
| 被读取的点位没有查询 | “请输入向仪器发出的查询，例如 MEAS:VOLT:DC?，或将点位设为只写。” |
| 查询含有排版引号或其他普通 ASCII 以外的字符 | “查询含有普通 ASCII 以外的字符（例如排版引号），或超过 512 个字符。” |
| 应答中的值超过 1000 | “应答中的值从 1 数到 1000。留空则读取整个应答。” |
| 被写入的点位没有写入命令 | “请输入写入时发送的命令，例如 VOLT {value}，或将点位设为只读。” |
| 不是 `{value}` 或 `{value:FORMAT}` 的花括号，或者值出现两次 | “写入命令含有普通 ASCII 以外的字符、不是 {value} 或 {value:FORMAT} 的花括号，或者值出现了两次。” |
| 非 Boolean 点位上不含 `{value}` 的命令 | “请在写入命令中数值所在位置放 {value}。只有 Boolean 点位可以不带它发送命令。” |
| 不格式化数字的格式，或者用在 Boolean 或 String 点位上的格式 | “value: 后面的格式必须用于格式化数字，例如 0.000 或 F2，并且只有数值点位可以使用。” |

只读的**源地址（总线）**一行显示驱动收到的内容：读取整个应答的点位是 `ask=READ?`，读取其中第三个值的是 `ask=READ?&field=3`，既读又写的点位是 `ask=VOLT?&write=VOLT {value}`，只写点位是 `write=*TRG`。

## 读取 {#reading}

在点位的轮询间隔，工作站发送查询，并在响应超时之内读取一条直到结束符为止的应答。取出的文本，即整个应答或点位指定的那个值，先按点位的类型读取，再由点位自己的各个环节换算，和所有驱动一样（见[数值转换链](connector-value-pipeline)）：

| 应答内容 | 读作 |
| --- | --- |
| `+1.23456789E+00`、`-0.5`、`12` | Float 或 Double：这个数，无论工作站用什么语言，小数分隔符都是点。 |
| `9.91E37` | SCPI 的非数值，即仪器没有读数时的应答：在 Float 或 Double 点位上读作 NaN，由它的[无效读数](connector-value-pipeline#the-device-answered-without-a-number)环节处理；在 Int32 或 Int64 点位上被拒绝。`9.9E37` 表示超量程，仍然读作这个数。 |
| `+1.20000000E+01` | Int32 或 Int64：12。小数被拒绝。 |
| `1`、`ON`、`0`、`OFF` | Boolean：1 和 ON 为真，0 和 OFF 为假；true、false、yes 和 no 也能读。 |
| `"Ready, armed"` | String：去掉引号的字符，连写的两个引号变成一个。引号内的逗号不分隔值。 |

| 情况 | 读取会怎样 |
| --- | --- |
| 同一设备上发出相同查询的点位 | 它们在其中最短轮询间隔的一半时间内共用一条应答，所以读取多通道 `READ?` 各个通道的点位只花一次测量。任何一次写入都会丢弃所有保留的应答。 |
| 响应超时之内没有应答 | 读取失败。设备读取错误队列时，工作站随后会问 `SYST:ERR?`，所以写错的查询失败时，原因里带有仪器自己的条目，例如 `-113,"Undefined header"`。点位针对[设备没有应答](connector-value-pipeline#the-device-did-not-answer)的策略决定它显示什么。 |
| 应答中的值少于点位指定的序号 | 读取失败，并说明应答有几个值。 |
| 点位类型容纳不了的文本 | 读取失败，并写出这段文本。 |

## 写入 {#writing}

写入和其他任何驱动的写入走同一个通道：写入框接收工程值，在发送原始值之前把转换环节倒过来执行（见 [Connector](connector)）。发送的命令就是写入命令，在 `{value}` 的位置放上数值：数字用不变区域性写出，取能读回同一个数的最短文本，或按 `{value:FORMAT}` 用 .NET 数字格式格式化（`CURR {value:0.000}` 把 1.5 发送为 `CURR 1.500`）；Boolean 发送为 `1` 或 `0`，所有 SCPI Boolean 参数都接受；文本照原样发送，由命令自己带上所需的引号（`DISP:TEXT "{value}"`）。非数值和无穷大在发送任何东西之前就被拒绝。在 Boolean 点位上，不含 `{value}` 的命令（例如 `*TRG`）在写入 true 时发送，写入 false 被拒绝。

| 写入确认 | 发送什么 | 写入报告什么 |
| --- | --- | --- |
| **错误队列（SYST:ERR?）** | `*CLS`、命令、`SYST:ERR?` | 队列应答没有错误（`0` 或 `+0,"No error"`）时写入完成。任何其他条目都会用仪器自己的话拒绝写入，例如 `-222,"Data out of range"`。没有应答就是没有响应：不知道仪器是否接受了这个值。 |
| **先确认完成，再查错误队列（\*OPC?、SYST:ERR?）** | `*CLS`、命令、`*OPC?`、`SYST:ERR?` | 同上，但要等仪器执行完命令：用于需要稳定的输出或需要切换的继电器。 |
| **无：发送即确认** | 只有命令 | 一发送就完成，用于没有错误队列的仪器。这时没有应答的查询在报告中不带仪器的错误。 |

写入和读取一起在设备的队列里排队：在线路上，它们共用线路一次一个的请求；通过 TCP 和 VISA 时，使用设备自己的连接。

## 设备发现 {#discovery}

驱动页面带有一张**扫描范围**卡片，里面有一个可选的框，“用于 TCP 探测的仪器地址，例如 192.168.0.20 或 192.168.0.20:5025（留空则查找 VISA 列出的仪器）”。发现设备随后依次问两个问题：

| 问题 | 何时 | 提供什么 |
| --- | --- | --- |
| VISA 列出的每个仪器资源，无论在 USB、GPIB 还是网络上，依次打开并用 `*IDN?` 询问。进度行逐个写出：“正在询问 USB0::0x0957::0x1A07::MY12345678::INSTR 的标识…”。 | 本计算机安装了 VISA 时。没有 VISA 时，扫描会说明这一点以及 VISA 的下载位置，这句话会留在结束扫描的那一行里（[本计算机上的 VISA](#visa-on-this-computer)）。 | 每台应答的仪器，作为已填好资源的 VISA 设备。 |
| 通过 TCP 向框中的主机发 `*IDN?`，使用它的端口或 5025：“正在询问 192.168.0.20:5025 的标识…”。 | 只有框中有地址时。 | 这台仪器，作为该主机和端口上的 TCP 设备。 |

每台仪器有 1.5 秒应答，不应答的仪器不会提供。候选项按它应答的制造商和型号命名（`Keysight Technologies 34461A`），带有“仪器”卡片的所有默认值，不带任何点位，因为仪器不会公布它的查询列表：“没有报告任何点位。把设备添加进来，再在它的编辑器里配置点位。”资源已被本驱动某台设备使用的 VISA 候选项会标为已配置，提供“打开”而不是“添加”；通过 TCP 找到的仪器从不匹配，因为主机只是连接仪器的地方。VISA 把计算机的每个串口都列为资源（`ASRL3::INSTR`），不管有没有接东西，询问就会写到接在上面的东西上：扫描会把它们排除在外，串口仪器应放在本驱动的串行线路上。在 VISA 设备上手工输入的串口资源照样会打开。框里不是主机的内容会在框下被拒绝，发现设备变灰：“SCPI 扫描通过 TCP 请这里填写的仪器报告自身标识：填写它的 IP 地址或名称，需要时带上端口（例如 192.168.0.20 或 192.168.0.20:5025）。留空则只询问 VISA 列出的仪器。”扫描的其他行为见[设备发现](connector-discovery)。

## 示例：TCP 上的万用表 {#example-a-multimeter-over-tcp}

网络上的 Keysight 34461A 在它的 LXI 套接字（端口 5025）上应答 SCPI。读取它的直流电压：

1. 在驱动页面上点**添加设备**；命名为 `DMM`，保持 **TCP（LXI 套接字）**，**主机**填 192.168.0.20，**端口**保持 5025。
2. 在**仪器**卡片上保持 **LF（换行）**、**响应超时（ms）** 2000 和**错误队列（SYST:ERR?）**，并输入两条**初始化命令**，先 `*RST` 再 `CONF:VOLT:DC 10`：工作站每次连接时，万用表都会复位并设为 10 V 量程的直流电压测量。
3. 连接后，“标识”字段显示万用表的应答，例如 `Keysight Technologies,34461A,MY53212345,A.02.14-02.40-02.14-00.49-02-01`。
4. 点**添加点位**；命名为 `Voltage`，Double，只读，**查询**填 `READ?`，**应答中的值**留空，**单位**填 V。`READ?` 按设定的功能测量一次并应答结果。

Base URI 为 `scpi://tcp/192.168.0.20:5025?term=lf&timeout=2000&check=errorqueue&setup=*RST%0ACONF:VOLT:DC 10`。智能体用两次工具调用完成同样的事：

```
device_upsert driver=Scpi name=DMM transport=Tcp host=192.168.0.20 port=5025 setupCommands='*RST\nCONF:VOLT:DC 10'
tag_upsert device=DMM name=Voltage opcUaType=Double address='READ?' unit=V
```

## 示例：RS-232 上的电源 {#example-a-power-supply-on-rs-232}

Keysight E3631A 在它的 RS-232 接口上应答 SCPI，9600 波特、8 个数据位、无校验、2 个停止位；通过 RS-232 时，它要先切到远程模式才接受命令。设置它的电压、切换输出并读取电流：

1. 在驱动页面上点**添加线路**；命名为 `PSU line`，选 `COM4`，**波特率**设为 9600，**串行格式**设为 `8N2`，然后**启用**这条线路。
2. 在线路上点**添加设备**；命名为 `PSU`。在**仪器**卡片上把**响应超时（ms）**设为 3000，在**初始化命令**里只输入一行 `SYST:REM`，并把**写入确认**设为**先确认完成，再查错误队列（\*OPC?、SYST:ERR?）**，这样写入要等输出跟上之后才算完成。
3. 点**添加点位** `Setpoint`，Double，读写，**查询** `VOLT?`，**写入命令** `VOLT {value}`。
4. 点**添加点位** `Output`，Boolean，读写，**查询** `OUTP?`，**写入命令** `OUTP {value}`：写入 true 发送 `OUTP 1`，写入 false 发送 `OUTP 0`，电源对 `OUTP?` 应答 1 或 0。
5. 点**添加点位** `MeasuredCurrent`，Double，只读，**查询** `MEAS:CURR?`，**单位** A。

`Setpoint` 点位的总线地址是 `ask=VOLT?&write=VOLT {value}`。像这台一样有多路输出的电源，作用于它当前选中的那一路；再加一条初始化命令，例如 `INST:SEL P6V`，即可选定。用智能体的工具完成同样的事：

```
serial_line_upsert driver=Scpi name='PSU line' serialPort=COM4 baudRate=9600 serialFormat=8N2
device_upsert driver=Scpi name=PSU transport=SerialLine serialLineId=<id> responseTimeoutMs=3000 setupCommands='SYST:REM' writeCheck=CompletionAndErrorQueue
tag_upsert device=PSU name=Setpoint opcUaType=Double accessType=ReadAndWrite address='VOLT?' writeTemplate='VOLT {value}'
tag_upsert device=PSU name=Output opcUaType=Boolean accessType=ReadAndWrite address='OUTP?' writeTemplate='OUTP {value}'
tag_upsert device=PSU name=MeasuredCurrent opcUaType=Double address='MEAS:CURR?' unit=A
```

## 智能体工具 {#agent-tools}

`driver_capabilities` 在 `scpi` 下描述本驱动：三种传输方式、本计算机是否有 VISA（在 `prerequisite` 下，附带安装的每个步骤）、结束符、响应超时、写入确认、初始化命令、查询和写入命令的写法、应答如何读取、设备发现，以及上面的两个示例。`device_upsert driver=Scpi` 接受 `transport`（`Tcp` 为默认，`Visa`，或由 `serialLineId` 隐含的 `SerialLine`）、TCP 用的 `host` 和 `port`、VISA 用的 `visaResource`、本驱动线路用的 `serialLineId`、`terminator`（`Lf`、`CrLf` 或 `Cr`；也接受 `\n`、`\r\n` 和 `\r`）、`responseTimeoutMs`（100 到 60000）、`writeCheck`（`ErrorQueue`、`CompletionAndErrorQueue` 或 `None`）和 `setupCommands`（每行一条，或用 `\n` 分隔；`''` 清空）。`tag_upsert` 接受作为 `address` 的查询、`valueField`（1 到 1000；0 或省略则读取整个应答）和 `writeTemplate`（`''` 清空）。`serial_line_upsert driver=Scpi` 创建本驱动的线路，只带 `serialPort`、`baudRate` 和 `serialFormat`。`device_discover driver=Scpi` 运行扫描，用 `target` 指定 TCP 探测。工具返回的设备带有 `scpi`，仪器应答后其中包含仪器的标识；点位也带有 `scpi`。其他工具见[智能体工具](agent-tools)。

## 值得了解的限制 {#limits-worth-knowing}

- Fluke NetDAQ 2640A、2645A、2680A 和 2686A 说的是 Fluke 自己的协议，不是 SCPI：本驱动不读取它们。Fluke 1586A Super-DAQ 和 2638A Hydra Series III 说 SCPI，本驱动可以读取。
- 以 IEEE 488.2 二进制块（一个 `#`、一个长度和原始字节）发送的应答，例如波形或屏幕截图，不会读取：点位读取的是以文本写出的应答。
- 本产品不安装 VISA。本计算机上没有 NI-VISA 或 Keysight IO Libraries Suite 时，无法连接 USB 和 GPIB 仪器；TCP 仪器和串口仪器照常连接。
- 扫描不列出 VISA 的串口资源（`ASRL…::INSTR`）：串口仪器应放在本驱动的串行线路上。
- 每个值都靠轮询读取：驱动不等待服务请求（SRQ），也不等待状态字节。
- 设备不能在串行线路和网络之间移动，也不能移到另一条线路：在它该在的地方创建，再删除旧的。
