教程:使用 pyvisa 对测试设备进行 SCPI 自动化简介

发布于:2025-09-06 ⋅ 阅读:(18) ⋅ 点赞:(0)

在进行科学实验时,您的测试设备是测量您试图观察的数量的“眼睛和耳朵”。很多时候,购买者倾向于关注精度和分辨率等规格,同时也关注价格。其他一切都有点事后才想到的。

然而,来自知名测试和测量公司的大多数品牌仪器都具有一定的可编程性,这已经不是什么大秘密了。更好的仪器遵守许多标准,具有远程编程接口,可能附带软件驱动程序、示例代码,甚至是数百页长的编程手册。

然而,根据我的经验,许多优秀的仪器坐在工作台上,而操作员则一步一步地摆动旋钮,在实验室笔记本上一一写下读数,而仪器背面的遥控接口则没有插头。否则,他们使用的是仪器附带的软件——其中一些看起来像是在 Windows XP 时代构建的,但几乎总是,我听到抱怨他们如何“希望”他们能做一些与软件功能略有不同的事情(例如,使用第二或第三台仪器,组合其他供应商的仪器)。

当我看到这里时,我沮丧地叹了口气——因为我曾经也是这样。但是,我没有磨损乐器上的旋钮,而是决定研究如何实现自动化,并发现它出奇地容易,以至于我想知道为什么很少有人费心去尝试。也许是厚厚的编程手册和 SCPI 语法,这在其他任何地方都不常见。

从那时起,我无法想象如果不通过 pyvisa 使用 SCPI 自动化来完成我为这个博客所做的大部分实验。拥有它就像拥有自己的实验室助理,它永远不会累,永远不会犯错误,即使在我睡着的时候也能工作......它非常强大,但也有潜在的危险。

因此,我决定将本教程放在一起,试图将我所有的经验整理在一个地方,供那些可能想从支持 SCPI 的仪器中获得更多收益的人使用。假设了解基本的 Python 3 – 别担心,与大多数其他编程语言相比,它很容易学习。

免责声明:以下教程是出于善意提供的。对于因使用或无法使用所提供内容而导致的任何错误、遗漏或损害,无论它们如何发生,作者概不负责。自动化可能很危险 – 在开始无人值守地使用自动化进行测试序列之前,请确保您已经考虑了最坏情况下可能产生的风险。

什么是 VISA 和 pyvisa

说到测试设备自动化,您可能听说过“VISA”这个词。不,它与信用卡无关——事实上,它代表虚拟仪器软件架构,它是一种行业标准 API,用于从计算机与仪器进行通信。VISA 有许多不同的类型 - 最常见的是 National Instruments 的 NI-VISA,但也有是德科技 IO 库、泰克 TekVISA、罗德与施瓦茨 VISA 等。虽然它们应该在某种程度上是可互作的,但针对一种特定 VISA 构建的软件可能难以与另一种 VISA 一起运行(根据我的经验),这可能需要安装多个 VISA,其中一个被指定为主要 VISA。有时,这可能会导致冲突,从而完全中断仪器连接。

VISA 的工作是通过作系统及其驱动程序将您的应用程序(可以用 C 或任何其他为您的 VISA 提供库的语言编写)连接到设备。

您的程序将命令仪器执行某些任务——这通常通过一种称为 SCPI(可编程仪器标准命令)的语言完成,发音为“skippy”,就像丛林袋鼠一样。这些是发送到仪器的基于 ASCII 字符串的命令 - 在后面的部分中详细介绍。

自动化可以通过编写一个针对 VISA 和 spoke SCPI 命令编译的程序来完成,但这可能相当有限。在大多数情况下,商业 VISA 层几乎普遍在 Windows 上运行,这意味着程序不兼容跨平台。提供的语言通常仅限于 C 语言或其变体。使用可能特定于仪器的 SCPI 命令进行开发将非常繁重的代码,从而限制了程序直接移植到其他仪器的能力。

因此,还有其他自动化方法——IVI-COM 和 IVI-C 驱动程序试图将仪器功能抽象到更高的水平,解决不同型号仪器之间互换的问题。更复杂的解决方案,如National Instruments LabVIEW,还提供了图形编程界面,并率先使用了仪器驱动程序,这些驱动程序还将功能抽象到更高的水平,从而更容易地进行仪器替换。

我个人从来没有真正喜欢过这些。虽然我可以用 C 语言编写代码,但我必须投入大量工作来设置开发环境、理解 VISA 库文档以及它通常与给定的 VISA 发行版相关联的事实使其没有吸引力。它不会跨平台的事实也是一个很大的失望。另一方面,LabVIEW是一笔不合理的开支,就其安装规模而言,这是一个庞然大物。

这就是我决定使用 pyvisa 进行自动化的原因。它是一个位于 Python 程序和 VISA 层(NI-VISA 或 pyvisa-py)之间的“垫片”。它允许您使用 Python 进行编程这一事实是一个主要优势,因为它得到了库的良好支持,具有丰富的功能并且易于学习。与 pyvisa-py 交互的能力也意味着它可以轻松地在 Linux 上运行。最后,我有没有提到它是免费和开源的?

知识渊博的人问我——“鉴于某些仪器可以通过 TCP/IP 套接字或 RS-232 串行进行命令,为什么还要费心使用 VISA?从某些方面来说,这是一个很好的问题,但我认为您仍然应该考虑将 pyvisa 用于这些工具是有充分理由的——

  • 当您处理多种乐器时,它使事情保持一致。
  • 它为您处理超时、格式化命令并解析回复,因此您不必将“6.4892345E+05”等字符串转换为数字。
  • 它使从一个接口过渡到另一个接口变得容易——当您的 LAN 插槽程序突然需要使用 USB-TMC 接口运行时会发生什么?使用 pyvisa,就像更改 VISA 资源名称一样简单,但使用套接字是一条完全不同的路径。
  • 它还允许您使用更复杂的协议,而不仅仅是普通套接字连接。使用 VXI-11 允许传递一些 IEEE488 式信号,而 HiSLIP 允许流水线作,从而提高速度。最重要的是,您无需担心这些协议的实现,因为它是由 VISA 层处理的。

使用 pyvisa 并不能解决 SCPI 命令有时特定于设备的问题,但对于一次性实验或家庭实验室来说,这很少是问题,因为您可能负担不起新仪器。此外,还有一些核心命令在所有仪器中都是通用的——无论如何,大多数作都可以用这些命令完成。

仪器物理层连接

多年来,仪器连接到主机的方式发生了变化,但是,有一些物理层连接,每个连接都有自己的优点和缺点。

 

最古老的是通用接口总线或简称 GPIB,也称为 IEEE-488。这是一种具有 24 触点微带连接器的并行总线,其风格与以前用于并行端口打印机的 Centronics 连接器相似,只是它们是螺钉固定且可堆叠的。该总线由 HP-IB 演变而来,在单个网段中最多可支持 15 个超过 20m 的设备,在带有有源扩展器的总线上总共最多支持 31 个设备。

这种特殊的总线现在被认为是一种“传统”连接形式,它主要是为了确保仪器与旧测试设置的直接替换互作性。就数据吞吐速度而言,它不如最新形式的连接快,而且成本相当高,因为控制器和电缆的成本很容易达到仪器成本的一半以上!它确实有一个关键优势,那就是专用线路,可用于确保总线上的多台仪器同步触发以同时进行测量。

 

下一个是不起眼的 RS-232 串行端口,它在 IBM PC 世界中可能被称为“COM”端口。该端口通常用于数据终端设备(调制解调器)和鼠标,但也可用于某些通过串行接受 SCPI 命令的仪器。现在,在一些现代 PC 上很少找到该端口,但 USB 转串行适配器可用于与此类设备连接。数据速率相对有限,大多数设备的常见波特率范围为 300bps 至 115,200bps。匹配设置(波特率、数据位、奇偶校验、停止位)和电缆配置(9 针/25 针、零调制解调器或直通)对于通信非常重要。RS-232 连接是主机到设备的,每个设备都需要一个单独的端口。虽然有特殊的流控制和状态行,但它们通常不用于同步或触发,而是所有命令都作为 ASCII 数据通过串行链路流动。

有些仪器通过 USB 连接,但使用 CDC(通信设备类)显示为串行端口。在这些情况下,您可以像通过串行连接一样与它们连接,但或者,某些仪器可以切换到 USB-TMC作,这可能更可取。

 

Images – Keithley 2450 SourceMeter、B&K Precision Model 8600 DC 电子负载和罗德与施瓦茨 NGM202 电源的后面板。你能看到提到的所有接口吗?

从这里开始,大多数仪器选择使用 USB 连接,这要方便得多,因为它主要是“即插即用”作,不需要配置或特殊驱动程序(除了在设备菜单中选择 USB 作为连接模式)。USB 连接通过 USB 测试和测量类(或简称 USB-TMC)和 USB488 进行标准化。这允许器件使用标准驱动程序运行,同时通过特殊的消息格式模拟GPIB的一些状态信令功能。USB 的使用通常还意味着更一致的延迟——USB 以 1kHz 的速度轮询设备,虽然是共享总线,但通常有足够的带宽用于仪器控制目的。限制主要与 USB 总线有关——例如,从设备到端口的最大距离为 5 米,并且通常适用最大五个集线器的级联深度,尽管有一些解决方案可能能够超出这些距离。总线也不是隔离的,这在某些应用中可能会出现问题,尽管有专有的扩展器、媒体转换器和隔离器可用。不幸的是,由于电缆成本低廉,互连设备的认证相对松懈,某些设备在面对强 EMI 噪声或芯片组不兼容时可能不可靠,尤其是在较远的距离上。

最现代的仪器连接形式是以太网——从字面上看,该仪器有点像“物联网”。这种连接被认为相当复杂且昂贵,需要实现完整的以太网 PHY、MAC 和 TCP/IP 网络堆栈以允许基本的“套接字”级别控制。然而,好处是多倍的,因为基于 IP 的设备可以轻松地在同一网络上与其他设备共享,可以像任何其他基于 IP 的服务(例如通过 VPN)类似地访问,并且可以与同一网络链路上的其他仪器和设备共享带宽。它还具有使用以太网连接的好处,该连接由两侧的变压器隔离,并且最近的交换机和设备之间可以达到 100m。支持以太网的高端仪器符合 LXI(仪器仪表 LAN 扩展),该仪器可以提供更多功能,包括 Web 界面、mDNS 发现、VXI-11/Hi-SLIP 协议和定时同步。尽管如此,以太网连接通常有一个显着的延迟缺点,该缺点可能因网络而异。这可能会影响设备触发的同步。另一个是大多数设备没有受到任何严肃保护,因此只能期望在仅具有受信任节点的安全网络上使用。

还值得注意的是,有些仪器也使用 USB 和以太网,但可能不符合相关标准,并且可能使用自己的协议。检查制造商提供的文档通常可以明确仪器是否具有 SCPI 功能。还有其他供应商特定的远程控制总线,这些总线不是行业标准(例如吉时利 TSP-Link),可以在某些特殊情况下通过一台仪器“网关”向总线的其余部分发出命令。同样,可以使用适配器和网关将GPIB或USB转换为以太网,反之亦然。

硬件和软件先决条件

为了开始使用 pyvisa,您确实需要一个或多个支持 SCPI 的仪器以及将它们连接到计算机的某种方式。这几乎可以是任何中高端测试设备(例如数字万用表、电源、频谱分析仪等),只要它具有 GPIB、RS-232 串行、USB (TMC) 或以太网 (LXI) 连接并支持 SCPI 命令集(如果您不确定,请查看仪器手册)。

您还需要匹配的硬件来将其连接到计算机,例如 GPIB 控制器和 GPIB 电缆、RS-232 电缆连接到 RS-232 端口或 USB 适配器、USB A 到 B 引线或以太网电缆。当然,连接类型和电缆必须匹配,除非使用特殊的适配器或网关进行连接。

 

在插入之前,您可能需要配置设备。确保通过设备菜单选择您打算使用的匹配接口,因为大多数设备一次只能使用一个接口。

  • 对于GPIB连接,您需要配置一个地址(对于设备,通常为1到30个),单个总线通常限制为20m的总电缆长度和15个设备。
  • 对于 RS-232 连接,请注意波特率、数据位、奇偶校验和停止位,尽管通常波特率是最重要的,因为其余参数通常是 8/N/1。
  • 对于 USB-TMC 连接,假设您的软件和驱动程序已正确安装,它非常“即插即用”。
  • 最后,对于以太网,您需要知道是否要运行DHCP自动配置,或者是否要为仪器分配静态IP地址(如果是,则为静态IP地址、子网掩码、网关和DNS地址)。错误设置这些地址可能会导致网络冲突,或者可能意味着无法从您的计算机访问仪器。您可以选择通过交换机将以太网仪器连接到局域网(LAN),但应注意确保只有受信任的设备位于该网络上,因为大多数以太网仪器不具有安全性,因此LAN上的任何设备都可能控制或重新配置您的仪器!不用说,仪器不应直接连接到互联网!

pyvisa 最好的一点是它在大多数主要作系统上同样适用。要运行它,您需要安装 Python 3.x。在 Windows 上,您可以使用预装了许多常见库的“一体化”包,例如 WinPython(我使用它,因为它是可移植的)或 Anaconda。在 Linux 上,Python 通常已经安装或通过包管理器使用

sudo apt-get install python3 python3-pip

安装后,您将需要安装 pyvisa。 在 Windows 下,这就像运行

pip install pyvisa

但在 Linux 下,您可能应该直接运行它,然后再次以 sudo 为前缀,以确保它适用于您的用户和 root,因为您的用户可能没有硬件访问功能(如果您不向用户提供该权限,您将不得不以 root 身份运行脚本,这可能存在潜在危险)。

注意: 如果您的 Linux 系统将已弃用的 Python 2.x 作为默认的 Python 解释器,则在本教程的其余部分,您将需要使用 pip3 而不是 pip,并使用 python3 而不是 python

如果您被告知您的 pip 版本已过时,您不妨使用

python -m pip install –upgrade pip

最后,由于pyvisa实际上只是VISA层的“包装器”,因此您需要安装一个受支持的VISA层才能与之通信。如果您运行的是Windows,实际上,您应该使用National Instruments的NI-VISA软件包。这是一个笨重的软件,但一般来说,它是支持最良好的VISA层——仪器附带的“捆绑”软件可能已经安装在计算机上。可以避免在Windows上使用NI-VISA,但随后您需要为每台仪器制作自己的驱动程序并自行签名,这只是一大堆麻烦。

但是,在 Linux 上,您还需要安装 pyvisa-py,它提供基于 Python 的 VISA 层,以及 pyusb(用于 USB-TMC 仪器)和 pyserial(用于串行连接仪器)。这可以通过使用以下命令(带和不带 sudo 来完成)

pip install pyvisa-py pyusb pyserial

到目前为止,您应该已经准备好安装了。要测试这一点 – WinPython 用户需要打开 WinPython 命令提示符并输入 python,他们应该会看到一个带有 Python 版本的横幅。Linux 用户需要打开一个终端窗口并输入 python3,他们同样应该会看到 Python 横幅。

从那里,您应该能够输入

import pyvisa

它应该返回到提示符,就像下面的示例一样。如果是这样,那么恭喜你,你的安装成功了,你可以输入 exit() 退出。

Python 3.6.6 (v3.6.6:4cf1f54eb7, Jun 27 2018, 03:37:03) [MSC v.1900 
64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more 
information.
>>> import pyvisa
>>>

注意: 较旧的代码示例可能使用“import visa”行而不是“import pyvisa”。这仍然被接受,但可能会导致冲突,因为另一个包也使用名称“visa”,因此建议从现在开始使用“import pyvisa”,对于依赖于 visa 名称的旧代码,您可以使用“import pyvisa as visa”作为解决方法。您在较新版本的 pyvisa 上可能会收到的错误可以注意到这一点 –

/usr/local/lib/python3.7/dist-packages/visa.py:23: FutureWarning: 
The visa module provided by PyVISA is being deprecated. You can 
replace `import visa` by `import pyvisa as visa` to achieve the 
same effect.

The reason for the deprecation is the possible conflict with the 
visa package provided by the 
https://github.com/visa-sdk/visa-python which can result in hard 
to debug situations.
FutureWarning,

VISA 资源名称

为了使用工具,您必须首先知道如何处理它。可以通过 VISA 访问的每种工具都有自己的唯一地址,称为 VISA 资源名称。您可以通过多种方式检查您的设备及其资源名称。

如果您使用的是Windows并使用NI-VISA,那么您将安装一个名为NI-MAX的工具。该工具允许您通过展开左侧的树来检查可用的设备和接口。单击仪器将显示完整的资源名称。

 

这个特殊的工具对于检查您的仪器是否正常工作也非常有用——单击“打开VISA测试面板”并单击顶部工具栏上的“输入/输出”按钮,您可以直接发送/接收命令以检查仪器的运行情况通过NI-VISA。

 

对于运行Linux或不想调用NI-MAX的用户,您还可以通过运行一些Python命令来检查哪些设备连接到您的机器,如下所示 –

>>> import pyvisa
>>> rm = pyvisa.ResourceManager()
>>> rm.list_resources()
('USB0::0x05E6::0x2110::1374001::INSTR', 
'TCPIP0::192.168.80.18::inst0::INSTR', 
'TCPIP0::192.168.80.19::inst0::INSTR', 
'TCPIP0::192.168.80.3::inst0::INSTR', 'ASRL1::INSTR')

结果是运行NI-VISA的Windows计算机的示例。在运行 Linux 和 pyvisa-py 的 Raspberry Pi 上运行相同的字符串,字符串略有不同 –

>>> import pyvisa
>>> rm = pyvisa.ResourceManager()
>>> rm.list_resources()
('USB0::65535::34816::602197010716810015::0::INSTR',)

请注意,USB资源字符串如何在Linux中使用十进制表示法,通过pyvisa-py和十六进制与NI-VISA一起使用。无论如何,这些字符串通常是可以互换的。应该注意的是,字符串可以区分大小写——“inst0”需要小写,否则可能会抛出错误!

最后,对于基于 LXI LAN 的仪器,可以通过直接在 Web 浏览器中访问 IP 地址,通过其 Web 界面找到这些详细信息和一些基本的 SCPI 命令能力。

 

某些仪器不会自动检测,尤其是某些GPIB、串行和LAN(插座)仪器。这只是意味着您必须编写与特定仪器相对应的自己的资源名称,例如

'ASRL1::INSTR' for Serial Port 1

'GPIB::5' for GPIB Instrument Address 5 (assuming one controller)

'GPIB1::10' for GPIB Instrument Address 10 (on the first controller)

'TCPIP0::192.168.80.61::5025::SOCKET' for a TCP/IP socket connection
....................... to 192.168.80.61 on the port 5025 (SCPI-RAW)

…VISA 层将尝试按照指示建立连接,如果无法建立通信,则出错。其中一些特定连接需要额外的参数配置才能使用——有关更多详细信息,请参阅末尾的提示和技巧部分。

SCPI 命令类型和格式

也许您已经浏览了仪器的编程手册,并对文档的厚度感到困惑 - 不用担心,其中许多都与细节有关,除非您选择使用给定的命令,否则您可能不需要担心这些细节。

从基础开始 - 所有 SCPI 命令都是发送到仪器的 ASCII 字符串。SCPI 命令有两种类型 - 集合命令和查询命令。设置命令告诉仪器执行某些作,而查询命令要求仪器响应一些信息。有些命令只能作为 set 命令使用,其他命令只能作为查询命令使用,而通常命令可以同时用作 set 和 query 命令,以便您可以查询之前设置的值。查询命令可以通过“?” 符号的存在来区分。

在编程上,set 命令涉及将包含终止字符(通常为“\n”)的字符串写入仪器,而查询命令涉及将带有终止字符的字符串写入仪器,然后从仪器读取响应(通常直到终止字符或通过其他方式发出终止信号)。工具将使用数据响应有效查询,尽管某些作可能比其他作花费更长的时间。无效的查询通常会导致记录错误、发出哔哔声并且没有响应。从仪器读取的查询的默认超时为 2000 毫秒 - 除非将超时调整得更高,否则任何需要更长时间才能返回的查询都将导致超时错误(有关更多信息,请参阅提示和技巧)。但是,发出不正确的查询命令将导致超时,这可能需要您采取手动步骤来恢复。

大多数设备只能按顺序处理 SCPI 命令,并且一次只能处理一个。因此,如果发出查询命令,则通过让每个查询命令写入后立即读取来读取它们放置在输出缓冲区中的结果,这一点很重要。如果不这样做,您可能会与仪器不同步并读取错误的响应!计算机、VISA 层、作系统和物理层将命令传输到仪器也需要时间;以及仪器接收、处理和响应命令所花费的时间。这种延迟将限制您控制仪器的速度。

SCPI 命令从根开始排列成层次结构,由冒号符号 (:) 表示。根下面的第一层通常称为“子系统”,其下层通常称为命令或子命令,每个级别都用冒号分隔。默认情况下,命令从根级别开始解释。

命令以类似于以下方式在编程手册中列出:

[:SOURce:]VOLTage <Value>

SCPI 命令本身通常不区分大小写。可以通过省略所有小写字母来缩写命令。可以通过省略方括号中的“可选”部分来进一步缩写命令——这些替代方案通常是为了确保严格符合 SCPI 层次结构原则并提高与其他仪器编写的代码的兼容性。命令可以以“:”开头,以确保它们被解释为来自根,但是,如果您不使用命令串联 (;),则并不总是需要这样做。使用命令串联时,其他命令将被视为在同一级别上。许多命令接受值输入——在上述命令的情况下,这将是电压,但也可以是字符串。方括号内的值可以省略。

因此,以下命令都是等效的(及其小写版本):

SOURCE:VOLTAGE 10
SOURCE:VOLT 10
SOUR:VOLTAGE 10
SOUR:VOLT 10
VOLT 10

有些命令是几乎所有相同类型仪器的常见命令(例如 MEAS:VOLT?),而其他命令可能特定于给定型号的仪器。有时,您的编程手册会对此以及首选命令进行一些注释或建议(因为某些命令可能是旧命令,无法充分利用较新仪器的全部功能)。

一些常见命令和总线命令采用不同的形式,而是以星号 (*) 开头。这包括 *RST、*IDN、*STB、*OPC 等命令。这些命令是IEE488.2通用命令,通常适用于大多数支持SCPI的仪器并执行定义的功能。

一旦你掌握了这一点,只需浏览你的编程手册,找到实现你想要执行的任何测试可能需要的命令。通常,这只涉及提供的过多命令中的少数几个。

编写一些简单的 pyvisa 程序

本节将向您介绍一些非常简单的程序,这些程序主要在这里提供“引导”参考,具有一点指导性,并让您有信心继续编写一些自己的代码。

世界您好

您通常学习编写的第一个程序是“Hello World”程序。在这种情况下,仪器等效物是一个连接到仪器并检索其身份的程序。

import pyvisa
resource_manager = pyvisa.ResourceManager()
# You can change the variable name and resource name
ins_ngm202 = resource_manager.open_resource("TCPIP0::192.168.80.18::inst0::INSTR")
print(ins_ngm202.query("*IDN?"))
ins_ngm202.close()

这个简单的程序首先导入 pyvisa,然后连接到资源管理器。从那里,我们连接到 VISA 资源名称 .在关闭和退出之前,我们将 *IDN? 查询的结果打印到控制台。

该程序中的大多数行将对几乎所有程序都是通用的。

显示文本和蜂鸣声

也许您对“Hello World”的想法是显示一些文本——某些仪器可以使用 DISP:TEXT 命令来做到这一点。同样,我们可以使用 BEEP 命令使仪器发出哔哔声。

import pyvisa
resource_manager = pyvisa.ResourceManager()
# You can change the variable name and resource name
ins_ngm202 = resource_manager.open_resource("TCPIP0::192.168.80.18::inst0::INSTR")
ins_ngm202.write("DISP:TEXT \"Hello World\"")
ins_ngm202.write("BEEP")
ins_ngm202.close()

控制输出,测量电压和电流

从温和的事情开始,举一个设置电压和电流,打开输出,等待五秒钟,测量电压和电流,然后关闭输出的例子怎么样?

import pyvisa
import time
resource_manager = pyvisa.ResourceManager()
# You can change the variable name and resource name
ins_ngm202 = resource_manager.open_resource("TCPIP0::192.168.80.18::inst0::INSTR")
ins_ngm202.write("SOUR:VOLT 10")
ins_ngm202.write("SOUR:CURR 1")
ins_ngm202.write("OUTP 1")
time.sleep(5)
voltage = ins_ngm202.query_ascii_values("MEAS:VOLT?")
current = ins_ngm202.query_ascii_values("MEAS:CURR?")
ins_ngm202.write("OUTP 0")
print("Voltage was "+str(voltage[0])+". Current was "+str(current[0])+".")
ins_ngm202.close()

这个程序稍微复杂一些,但实际上做了一些实用的事情。您会注意到我们还导入了时间模块,因为它对生成延迟很有用。仪器的 SOURCE 子系统用于设置输出电压和电流,MEASURE 子系统用于读回值,而 OUTPUT 子系统则控制输出状态。

您会注意到,set 命令是使用 .write 函数编写的,而查询是使用 .query_ascii_values 函数编写的。事实上,有几种方法可以编写查询函数——你可以使用 .write 后跟 .read,它将返回一个包含原始响应的 Python 对象。然而,许多对仪器的查询会导致返回一个或多个逗号分隔的数值,因此在这种情况下,使用.query_ascii_values将非常有帮助地将其转换为数字对象的 Python 列表 - 因此,您无需使用可能显示“2.9777E+02”的字符串,而是可以使用实际数字,以便可以直接对结果运行比较和数学运算。但是,即使返回值只是单个值,该函数也会返回一个列表,因此索引表示法(即 [0])用于访问列表中的第一个元素进行打印,而 str 函数用于将该数字转换回可打印字符串,因为 运算符需要匹配的数据类型。

虽然这个简单的程序可能有效,但它有一些缺陷,将在下一个稍微复杂一点的示例中解释。

I-V 扫描

假设您想使用 0-3V 的电源以 1mV 的步长运行 LED 扫描,电流限制为 20mA,并记录从中产生的数据以及以 Unix 秒为单位的时间,如何实现?

好吧,这并不难,但您可能应该做一些事情,但可能并不那么明显——这是我的解决方案:

import pyvisa
import csv
import time
resource_manager = pyvisa.ResourceManager()
# You can change the variable name and resource name
ins_ngm202 = resource_manager.open_resource("TCPIP0::192.168.80.18::inst0::INSTR")

ins_ngm202.write("*RST")
ins_ngm202.write("SYST:REM")
ins_ngm202.write("INST:NSEL 1")
ins_ngm202.write("SOUR:VOLT 0")
ins_ngm202.write("SOUR:CURR 0.02")
ins_ngm202.write("OUTP 1")
ins_ngm202.query("*OPC?")

with open("log.csv","w",newline="") as csvfile :
  logfile = csv.writer(csvfile)
  logfile.writerow(["Time","Voltage Requested","Voltage Readback","Current Readback"])
  for x in range (0,3001,1) :
    ins_ngm202.write("SOUR:VOLT "+str(x/1000.0))
    ins_ngm202.query("*OPC?")
    readback = ins_ngm202.query_ascii_values("READ?")
    logfile.writerow([time.time(),(x/1000.0),readback[0],readback[1]])

ins_ngm202.write("OUTP 0")
ins_ngm202.write("SYST:LOC")
ins_ngm202.close()

这段代码对上面的例子进行了相当大的扩展——现在我还导入了 csv 模块以允许编写.csv日志文件(尽管它也可以使用常规文件句柄来完成)。

前面代码的问题之一是我们不知道仪器的先前状态是什么。它几乎可以在任何配置中,因此仅设置一些设置并不能保证输出符合我们的预期。因此,最好发出 *RST 命令将仪器重置为手册中列出的默认值,以便一切都处于已知状态。

另一个问题是,之前的代码执行了,但没有处理仪器状态——有人可能在执行过程中玩弄前面板更改设置,从而导致意外结果。有一个命令 (SYST:REM) 将设备设置为远程控制模式,锁定前面板,直到发出相应的 SYST:LOC 调用或从前面板解锁。并非所有仪器都实现此命令。

对于多通道仪器,每个通道都被视为自己的“仪器”,需要 INST:NSEL 或 INST:SEL 命令来选择以下命令将定向到哪个仪器。在这种情况下,该命令指示以下命令在通道 1 上生效,但是,某些命令是“全局”的,会影响所有通道(例如 OUTP:GEN 0 关闭所有输出),因此执行命令时必须小心!

最后,应该注意的是,发出单独的 MEAS:VOLT? 和 MEAS:CURR?命令可能不会产生您期望的结果,原因有几个——一是两次调用之间可能有足够的时间延迟,以至于您无法获得电压和电流的同步读数。另一个是,当您告诉它们时,某些仪器可能不会实际测量它们,而是返回电流值,因此,如果仪器处理命令的速度很快,则循环可能会多次读取相同的值。

这就是阅读仪器手册非常重要的地方——一些仪器使用 FETC? 或 READ?来读取现有测量值,而 MEAS 总是导致进行新的测量。其他可能需要使用 TRIG:SOUR BUS 设置为软件触发,然后是 INIT 和 *TRG 命令来触发测量,然后是 FETC? 来读取它们。对于具有最新固件的 NGM202,READ是一种阻塞调用,每次返回一组新的值,包括同一调用中的电压和电流,因此比使用单独的测量调用更快。

截取屏幕截图

工具不仅限于返回 ASCII 值。事实上,许多工具也能够返回二进制数据——一种常见的二进制数据类型是屏幕截图图像。这个程序可以拉取屏幕截图并将其写入文件——

import pyvisa
resource_manager = pyvisa.ResourceManager()
# You can change the variable name and resource name
ins_ngm202 = resource_manager.open_resource("TCPIP0::192.168.80.18::inst0::INSTR")
f = open("screenshot.png","wb")
ins_ngm202.write("HCOP:DATA?")
data=ins_ngm202.read_raw()
# Returned data is prefixed with #nxxxxx where n is the number of bytes in 
# length field, xxxxxx is the bytes of data which is trailed by \n. Index 
# notation is used to drop the header and footer.
f.write(data[(data[1]-46):-1])
f.close()
ins_ngm202.close()

该程序与其他程序略有不同——它编写一个查询命令,然后调用一个read_raw函数,以从 HARDCOPY 子系统检索图像数据。这些数据实际上是以特定方式编码的——#nxxxxx 其中 n 是一个 ASCII 数字,表示长度字段中的字节数,x 是 ASCII 数字,表示字节数。整个记录都以终止字符为尾。Python 索引用于“切片”返回的数据以删除标头和终止字符,将二进制数据写入名为 screenshot.png 的文件中(假设您的仪器返回 PNG 数据,则该文件有效 - 有些还返回 BMP)。

 

从这些例子中,应该清楚地知道,使用 pyvisa 工作的东西相对容易,但要使其防弹,需要对仪器的工作原理进行一些注意和理解。下一节将介绍更多我在这些示例中没有介绍的提示和技巧。请记住,这只是一个介绍,因此我不会涵盖复杂的内容(例如状态可疑寄存器),我可能会将其保存到更高级的教程中。

您还会看到,散布在我的许多博客中,一些 pyvisa 代码,因此希望您能更好地理解这些程序列表。应该注意的是,我并不总是遵循最佳实践,因为有时只要您熟悉您的仪器和设置,您就可以走一些捷径(尤其是一次性实验)。

一般 SCPI 自动化提示和技巧

本节仅整理了一些使用乐器的提示和技巧。其中一些被认为是最佳实践,而另一些则是我从使用来自不同供应商的许多不同品牌的乐器中收集到的提示。

设置值

虽然上面的示例显示了一个非常简单的值设置,但应该注意的是,您隐含地相信仪器已经执行了您的命令。如果由于任何原因,仪器无法执行命令(例如通信错误、缓冲区溢出或损坏),您的程序将不知道,除非它做一些额外的工作。一种方法可能是检查错误队列(见后面的小节)。

但另一种非常简单的方法是立即查询设置值以查看它是否匹配(由于潜在的浮点引起的错误,余量很小)。例如,如果你做一个 SOUR:VOLT 10,你可以跟进一个 SOUR:VOLT? 希望响应是 1.00000+E01 或类似。这被认为是很好的做法,但是,我发现使用可靠的仪器没有必要。

您还可以借此机会使用自动化功能以随机顺序设置值 - 例如,当一个方向的扫描可能产生有偏差的结果时,您可以反向扫描或按随机顺序扫描。您还可以借此机会获取多个读数并将它们平均以获得更“可靠”的结果,并拥有与之相匹配的统计数据。

同步、超时和延迟

另一个潜在的问题是您的程序不确切知道给定的 set 命令何时执行,因为您可能一个接一个地发送一系列 set 命令。

为此,有 *OPC? 查询,当作完成到该点时,它将始终返回 1。或者,*WAI 也是另一个可以类似使用的命令,尽管我更喜欢前者。

您可能遇到的另一个问题是仪器速度慢或命令序列长,这可能会花费仪器比预期更长的时间才能响应。如果超时时间超过默认的 2000 毫秒超时时间,这将导致超时错误。

您可以使用 .timeout 指令重新配置超时,例如

ins_ngm202.timeout = 10000

将重新配置 ins_ngm202 到 10 秒的超时。

如果您按顺序发送大量设置命令而不在序列中撒上 *OPC?,您的慢速乐器也可能会遭受缓冲区溢出。添加固定延迟(例如使用 time.sleep)通常被认为是不好的形式,但有时如果性能不重要,这可能是最简单的方法。

错误队列

当在执行 SCPI 命令期间发生错误时,例如由于命令输入错误或通信错误,大多数设备都会发出哔哔声,并且屏幕上可能会亮起错误播报器。

您可以使用 SYST:ERR? 查询,它将返回最新的错误并将其从队列中删除。要检索完整的错误队列,需要重新发出命令,直到您获得第一个元素的无错误返回“0”。消息的用处可能因仪器而异,但检查程序中的错误队列以确保仪器正常工作可能是一种很好的做法。

另外值得注意的是,某些错误不一定出现在错误队列上,而是可能设置某些状态字节。有关详细信息,请参阅您的手册,因为每种仪器对其位图状态字节的使用方式不同。

语言和语法

某些设备能够同时使用 SCPI 和其他语言运行。最常见的例子是支持 Keithley TSP 的仪器。要让它们进入 SCPI 模式,请发出 *LANG SCPI 命令以远程切换命令集。或者,您可以通过前面板或 Web 界面进行切换。

还有一些仪器(例如泰克 PA1000)明确要求每个命令都以冒号开头,否则将被忽略。

大多数工具对终止字符有些挑剔,它通常是一个换行符 (\n)。发送带有 \r\n 的命令可能会导致错误。

多种仪器

有来自多个供应商的多个工具?没问题,只需使用自己的名称和相应的资源字符串声明每个工具,如下所示:

ins_ngm202 = resource_manager.open_resource("TCPIP0::192.168.80.18::INST0::INSTR")
ins_k2110 = resource_manager.open_resource("USB0::0x05E6::0x2110::1374001::INSTR")
ins_bk8600 = resource_manager.open_resource("USB0::0xFFFF::0x8800::602197010716810015::INSTR")

然后,您可以使用相应的名称写入每个 –

print("Setting Up - NGM202")
ins_ngm202.write("OUTP:GEN 0")
ins_ngm202.write("INST:NSEL 1")
ins_ngm202.write("SENS:VOLT:RANG:AUTO 0") 
ins_ngm202.write("SENS:VOLT:RANG 5")
ins_ngm202.write("SENS:CURR:RANG:AUTO 0") 
ins_ngm202.write("SENS:CURR:RANG 10")
ins_ngm202.write("OUTP:MODE SOUR")
ins_ngm202.write("SOUR:VOLT 5.000")
ins_ngm202.write("SOUR:CURR 6.000")
ins_ngm202.write("INST:NSEL 2")
ins_ngm202.write("VOLT:DVM 1")
ins_ngm202.write("SOUR:VOLT 0.000")
ins_ngm202.write("SOUR:CURR 3.000")
ins_ngm202.write("OUTP 1")
ins_ngm202.query("*OPC?")

print("Setting Up - K2110")
ins_k2110.write("FUNC \"CURR:DC\"')
ins_k2110.write("CURR:NPLC 10")
ins_k2110.write("TRIG:SOUR BUS")
ins_k2110.write("CURR:DC:RANG 10")
ins_k2110.query("*OPC?")

print("Setting Up - BK8600")
ins_bk8600.write("SOUR:FUNC CURR")
ins_bk8600.write("CURR 0")
ins_bk8600.write("REM:SENS 1")
ins_bk8600.write("INP 1")
ins_bk8600.query("*OPC?")

在上面,我的脚本设置了一个实验,我为 MAX77751 路测执行了该实验,其中我需要我的罗德与施瓦茨 NGM202 电源、B&K 型号 8600 直流电子负载和吉时利 2110 数字万用表协同工作。SCPI 的强大之处在于,它们都可以来自不同的供应商,但几乎可以无缝地协同工作。

另请注意,在上面,您的函数参数需要双引号字符并且您使用双引号字符串,您需要使用反斜杠字符“\”对其进行转义。

HiSLIP 连接

一些高性能仪器提供一种支持流水线的以太网协议,称为 HiSLIP,是高速 LAN 仪器协议的缩写。对于支持 HiSLIP 的设备,端口扫描将显示端口 4880 打开。

因此,以太网设备可以通过多种不同的方式连接 –

# Connect using a raw socket
ins_ngm202 = resource_manager.open_resource("TCPIP0::192.168.80.18::5025::SOCKET")
# Connect using regular VXI-11
ins_ngm202 = resource_manager.open_resource("TCPIP0::192.168.80.18::INST0::INSTR")
# Connect using HiSLIP
ins_ngm202 = resource_manager.open_resource("TCPIP0::192.168.80.18::hislip0")

通常,在您的 VISA 层支持的情况下使用 HiSLIP 更可取,但是使用 VXI-11 更为常见,尤其是在支持 LXI 的仪器中,并且原始插座与旧的 LXI 之前支持以太网的仪器更兼容。

插座连接

与基于套接字的仪器(即未实现 HiSLIP 或 VXI-11 的旧仪器或网关)连接需要的不仅仅是更改 VISA 资源名称! 如果您只更改资源名称,您很快就会发现您发送到仪器的任何查询命令都将以超时结束。这是因为您必须显式声明要在套接字连接实例中使用的终止字符。可能需要查阅手册或进行一些反复试验。

ins_k2110 = resource_manager.open_resource('TCPIP0::192.168.80.61::5025::SOCKET')
ins_k2110.read_termination = "\n"

例如,通过 USB-TMC 转以太网桥接使用我的 Keithley 2110,所需的附加配置是read_termination值。

ins_hmp4040 = resource_manager.open_resource("TCPIP0::192.168.80.13::5025::SOCKET")
ins_hmp4040.read_termination = "\n"
ins_hmp4040.query_termination = "\n"

但是,有些仪器略有不同,例如,我的罗德与施瓦茨HMP4040决定使用集合的换行符和查询命令进行回复。因此,它需要read_terminationquery_termination集。

不可靠/困难的仪器

生活中一个不幸的事实是,某些仪器在远程控制下工作时可能不可靠。这可能会导致在测试过程中失去对仪器的控制,在运行一定时间后持续发出哔哔声/喷出随机的神秘错误,或者某些命令无法按照手册中声称的方式工作。

在拔出头发之前,最好检查一下您是否使用优质电缆连接了仪器。我遇到过这样的情况:USB 电缆、集线器或主机上的 USB 控制器与测试仪器的兼容性问题导致随机“通用错误”以随机不可重复的方式发生。有时您可能会发现将电缆更换为必要长度最小的优质屏蔽电缆可以消除问题。

除此之外,可能需要偶尔重新启动您的仪器以确保它们保持可靠。更换仪器是另一种选择,尽管价格昂贵。

但有时,重要的是要进行防御性编码并尽可能地尝试从错误中恢复。这可能包括使用 try, except 循环在发生错误时多次重试读数。也许在出现一定数量的错误后,您可以尝试关闭仪器手柄并重新建立仪器连接。

如果做不到这一点,我不遗余力地集成代码,将远程控制的电源开关切换到硬电源循环仪器,以使它们恢复生机,尽管这是一种“蛮力方法”。值得庆幸的是,大多数现代乐器往往相当可靠。

自动化可能很危险!

重要的是要记住——自动化既方便又强大,但它也可能非常危险。想象一下这样一个场景:您可能正在用电源为电池充电——如果您突然失去与仪器的连接或仪器完全停止响应,会发生什么情况?也许电池可能会爆炸、着火、伤害某人或烧毁您的房子。

虽然通过自动化可以方便地执行如此多的测试,但您应该考虑谨慎进行,以确保“最坏情况”最终不会让您或您的仪器付出高昂的代价。拥有一个备用遥控电源开关来隔离仪器机架的电源可能是一个简单的备用计划,可以在出现问题时通过脚本驱动。否则,确保您的脚本会提醒您注意问题,您手头有人可以联系并知道如何安全关闭仪器可能至关重要。无论你做什么,都不要把它当作事后的想法。

即使没有这一点,手头有第二台仪器来监视第一台仪器也可能是个好主意——例如,获得第二意见可能至关重要,因为电压的轻微偏差可能会导致火灾后果。许多源仪器都具有板载过压、过流和过功率保护功能,即使您的代码将输出配置错误,也适当设置这些保护可以提供第二种安全保护。

结论

VISA架构的整个理念是让各种仪器通过软件以统一的方式进行控制。您无需担心您的设备是否来自单一供应商——事情应该正常工作。SCPI 命令集标准化了不同类型测试设备的命令格式和通用命令集。品牌测试设备供应商的大多数仪器都支持通过 GPIB、RS-232、USB 或以太网使用远程控制连接以及使用 SCPI 命令。

我希望通过阅读本教程,您意识到测试设备的自动化并不困难。通过使用 pyvisa 作为 Python 和 VISA 层之间的中间人,可以使用易于学习的 Python 语言控制仪器,同时保持完全免费和跨平台。一旦理解了 SCPI 命令的标准格式,就可以轻松命令仪器执行作和进行测量。通过能够自动化使用测试设备,您可以使它们始终如一地可重复,从而执行更好的实验,您可以获得比手动更精细的读数,您甚至可以进行无人值守的实验,程序可以根据您从仪器获得的读数做出决策。当然,还有一些更精细的细节和最佳实践,其中一些我在本教程中已经谈到了。

入门并不难,那些厚厚的编程手册也没什么好害怕的。一旦您意识到通过 SCPI 自动化为您提供的所有可能性,在执行测试序列时,您可能不会回到摆弄旋钮和记下值。因此,如果您有支持 SCPI 的仪器,那么是时候连接它并开始自动化了!

 


网站公告

今日签到

点亮在社区的每一天
去签到