入门 PyVISA(二)

PyVISA与仪器进行通信

下面是一个简单运用PyVISA控制仪器的例子:

>>> import pyvisa
>>> rm = pyvisa.ResourceManager()
>>> rm.list_resources()
('ASRL1::INSTR', 'ASRL2::INSTR', 'GPIB0::14::INSTR')
>>> my_instrument = rm.open_resource('GPIB0::14::INSTR')
>>> print(my_instrument.query('*IDN?'))

在导入 pyvisa 后,我们将创建一个 ResourceManager 对象。如果调用时没有参数,PyVISA 会优先选择默认的backend(IVI),并尝试找到 VISA 共享库。如果失败,它将返回到已安装的 pyvisa-py。可以通过以下方式查看所使用的后端和共享库的位置(如果相关):

>>> print(rm)

一旦有了 ResourceManager,就可以使用 list_resources 方法列出可用资源。输出结果是列出 VISA 资源名称的元组。可以使用 list_resources() 。默认值为'?*::INSTR',这意味着默认情况下只列出资源名称以'::INSTR'结尾的仪器(特别是不列出 USB RAW 资源和 TCPIP SOCKET 资源)。要列出所有存在的资源,请在 list_resources 中输入'?*'。

在本例中,有一个仪器编号为 14 的 GPIB 仪器,因此要求 ResourceManager 打开"'GPIB0::14::INSTR'",并将返回的对象分配给 my_instrument。

请注意,open_resource 为您提供了 GPIBInstrument 类(更通用的 Resource 的子类)的实例。

>>> print(my_instrument)

有许多资源子类代表不同类型的资源,但不必担心,因为 ResourceManager 会提供相应的类。您可以在资源类中查看每个类的方法和属性。

然后用以下信息查询设备: IDN?这是标准的 GPIB 信息,表示 "你是什么?",或者在某些情况下,表示 "你的显示屏上现在显示的是什么?"。 query 是写操作发送信息的简写,随后是读操作。

>>> my_instrument.query("*IDN?")

等同于:

>>> my_instrument.write('*IDN?')
>>> print(my_instrument.read())

调用 rm.list_opened_resources() 可以访问所有已打开的资源。这将返回一个资源列表,但请注意,该列表不会动态更新。

正确配置仪器

对于大多数仪器,实际上需要正确配置仪器,使其能够理解计算机发送的信息(特别是如何识别命令的结束),并使计算机知道仪器何时结束对话。否则很可能会出现 VisaIOError 报告超时。

对于基于消息的工具(涵盖大多数用例),这通常包括正确设置资源的 read_termination 和 write_termination 属性。

要查找仪器应设置的值,首先要查阅手册。要查找的信息通常位于手册中 IO 操作部分的开头附近。如果找不到数值,可以尝试遍历几个标准值,但不建议采用这种方法。

获得这些信息后,就可以尝试配置仪器并开始通信,具体操作如下:

>>> my_instrument.read_termination = '\n'
>>> my_instrument.write_termination = '\n'
>>> my_instrument.query('*IDN?')

这里我们使用 "n",即 "换行"。这是一个常用值,另一个是 "r",即 "回车",在某些情况下使用空字节 "0"。对于通过串行通信的仪器,需要确保配置正确的波特率。默认波特率设置为 9600,但应查看仪器手册,确认使用情况下的正确值。如果希望配置其他串行仪器参数,请参阅资源类以获取完整的属性列表。可以如下配置 PyVISA,使其使用不同的波特率与仪器通信:

>>> my_instrument.baud_rate = 57600

确保仪器理解命令

使用查询(query)时,我们既要测试向仪器写入,也要测试从仪器读取。首先要做的是确定问题是发生在写入还是读取操作过程中。

如果仪器有前面板,则可以检查错误(有些仪器会在读取后立即显示一条瞬时信息)。如果出现错误,可能意味着您的命令字符串包含错误,或者仪器使用了不同的命令集(某些仪器同时支持传统命令集和 SCPI 命令)。如果没有出现错误,则意味着仪器没有检测到信息的结束,或者无法读取信息。下一步是确定所处的情况。

为此,可以寻找一条能在仪器上产生可见/可测量变化的命令,并将其发送出去。在没有错误的情况下,如果预期的变化没有发生,则意味着仪器不理解该命令已完成。这说明写入终止出现了问题。在此阶段,可以返回手册(某些仪器允许在识别值之间切换),或者尝试标准值(如 "n"、"r"、这两个值的组合、"0")。

假设确认仪器理解了发送的命令,这意味着问题出在读取部分,而这部分更容易排除故障。可以尝试不同的 read_termination 标准值,但如果没有任何效果,可以使用 read_bytes() 方法。该方法最多只能读取指定的字节数。因此,可以尝试一次读取一个字节,直到遇到超时。出现这种情况时,很可能读取的最后一个字符就是终止字符。下面是一个快速示例:

my_instrument.write('*IDN?')
while True:
    print(my_instrument.read_bytes(1))

如果 read_bytes() 在第一次读取时超时,实际上意味着仪器没有应答。如果仪器很老,可能是因为这速度对它来说太快了,所以你可以尝试在读取之前等待一会儿(使用 Python 标准库中的 time.sleep)。否则,要么是你使用了一个不会导致任何应答的命令)。

某些仪器的响应速度可能较慢,因此可能需要增加超时时间或指定写入和读取操作之间的延迟时间。这可以使用 query_delay 全局设置,或者通过 delay=0.1 设置,例如写入后等待 100 毫秒再读取。

传输大量数据时,总传输时间可能会超过超时值,此时增加超时值timeout就能解决问题。

通过将 read_termination 设置为"",可以禁用终止符来检测输入报文的结束。在串行仪器中,确定输入结束的方法由 end_input 属性控制,默认设置为使用终止符,因此必须注意。要完全禁用终止符,应更改其值。

上文主要介绍了如何使用 PyVISA,如果你运行的是 Windows 或 MacOS,很可能可以使用第三方工具来。

使用第三方软件

National Instruments 和 Keysight 的 VISA 实现都附带有工具(NIMax、Keysight Connection Expert),可用于找出通信设置的问题所在。

在这两种情况下,都可以打开与仪器的交互式通信会话,并使用图形用户界面调整设置(这会让事情变得更简单)。基本程序如上所述,如果能在这些工具中的任何一个中运行,那么在大多数情况下,也能在 PyVISA 中运行。但是,如果在这些工具中无法运行,那么在 PyVISA 中也无法运行。

对于串行仪器(真正的或通过 USB 模拟的),您也可以尝试使用 Windows 上的 Putty 或 Tera Term、macOS 上的 CoolTerm 或 Terminal / screen 直接与之通信。

更复杂的示例

下面的示例展示了如何使用 SCPI 命令和 Keithley 2000 万用表测量 10 个电压。读取这些电压后,程序会计算平均电压并将其打印在屏幕上。

下面将逐步解释该程序。首先,必须初始化仪器:

>>> keithley = rm.open_resource("GPIB::12")
>>> keithley.write("*rst; status:preset; *cls")

在此,创建了仪器变量 keithley,该变量将用于仪器的所有后续操作。紧接着,将向仪器发送初始化和重置信息。

下一步是将所有测量参数,特别是间隔时间(500 毫秒)和读数个数(10)写入仪器。请参阅 SCPI 和 keithley 2000 手册。

interval_in_ms = 500
number_of_readings = 10
keithley.write("status:measurement:enable 512; *sre 1")
keithley.write("sample:count %d" % number_of_readings)
keithley.write("trigger:source bus")
keithley.write("trigger:delay %f" % (interval_in_ms / 1000.0))
keithley.write("trace:points %d" % number_of_readings)
keithley.write("trace:feed sense1; trace:feed:control next")

好了,现在仪器已经准备好进行测量了。接下来的三行将使仪器等待触发脉冲、触发脉冲并等待发送 "服务请求":

keithley.write("initiate")
keithley.assert_trigger()
keithley.wait_for_srq()

通过发送服务请求,仪器会告诉我们测量已经完成,结果已准备好传输。我们可以用 keithley.query("trace:data?") 来读取这些结果,但我们会得到以下结果:

-000.0004E+0,-000.0005E+0,-000.0004E+0,-000.0007E+0,
-000.0000E+0,-000.0007E+0,-000.0008E+0,-000.0004E+0,
-000.0002E+0,-000.0005E+0

必须将其转换为 Python 数字列表。幸运的是,query_ascii_values() 方法可以帮我们完成这项工作:

>>> voltages = keithley.query_ascii_values("trace:data?")
>>> print("Average voltage: ", sum(voltages) / len(voltages))

最后,我们应该重置仪器的数据缓冲器和 SRQ 状态寄存器,以便为新的运行做好准备。仪器手册中对此也有详细说明:

>>> keithley.query("status:measurement?")
>>> keithley.write("trace:clear; trace:feed:control next")

你可能感兴趣的:(PyVISA,python)