1 VISA简介 / VISA Introduction
VISA(Virtual Instrument Software Architecture,简称为VISA),即虚拟仪器软件结构,是VXI plug&play联盟制定的I/O接口软件标准及其规范的总称。VISA提供用于仪器编程的标准I/O函数库,称为VISA库。VISA函数库驻留在计算机系统内,是计算机与仪器的标准软件通信接口,计算机通过它来控制仪器。
作为通用I/O标准,VISA提供了统一的设备资源管理、操作和使用机制,它独立于硬件设备、接口、操作系统和编程语言,具有与硬件结构无关的特点。VISA的这一特性使之适用于各种仪器接口,无论仪器使用的串口还是其他任何一种总线,诸如GPIB、VXI、PXI和LXI等,都具有相同的操作函数,从而实现了控制操作上的统一。Visa基于自底向上的结构模型,创造了一个统一形式的I/O控制函数集。一方面,对初学者或是简单任务的设计者来说,Visa提供了简单易用的控制函数集,在应用形式上相当简单;另一方面,对复杂系统的组建者来说,Visa提供了非常强大的仪器控制功能与资源管理。
2 PyVISA库 / PyVISA Library
PyVISA是Python的一个包,使Python能够独立于接口(如GPIB,RS232,USB,Ethernet)控制各种测量设备。PyVISA极大的简化了对仪器的控制方式,仅仅需要几行代码即可以实现对仪器的操作。
2 PyVISA环境搭建
需要利用Python实现对仪器的控制,首先需要对环境进行相应的配置,基本在于以下几点,
1. 确保系统中有visa32.dll文件的存在;
2. 安装相应的仪器驱动软件;
3. 安装pyvisa包。
其中,visa32.dll文件一般存放的位置在c:/windows/system32/visa32.dll,而仪器的驱动可到相应官网进行下载,而pyvisa包则可以使用pip进行安装,
pip install pyvsia
3 PyVISA基本用法
下面介绍一下pyvisa用于仪器控制的基本使用方式,十分简单,详细的使用方式可以参考官方说明。
1 import visa 2 3 visa_dll = 'c:/windows/system32/visa32.dll' 4 tcp_addr = 'TCPIP::192.168.1.1::inst0::INSTR' 5 gpib_addr = 'GPIB0::12::INSTR' 6 7 # Create an object of visa_dll 8 rm = visa.ResourceManager(visa_dll) 9 10 # Create an instance of certain interface(GPIB and TCPIP) 11 tcp_inst = rm.open_resource(tcp_addr) 12 gpib_inst = rm.open_resource(gpib_addr) 13 14 # Command '*IDN?' can fetch instrument info 15 # Using write()/read()/query() function to make communication with device 16 # according to the command type 17 print(tcp_inst.query('*IDN?')) 18 print(gpib_inst.query('*IDN?'))
4 PyVISA应用实例
下面是一些在使用pyvisa进行仪器控制时编写的基本使用实例,可作为使用参考。
Note: 实例中仅仅是实现了一部分需求,若需要完成更多的命令需求,可以参考手册文件。
4.1 安捷伦E5071C (TCP/IP)
1 import visa 2 3 class E50X(): 4 def __init__(self, ip, visaDLL=None, *args): 5 self.ip = ip 6 self.visaDLL = 'c:/windows/system32/visa32.dll' if visaDLL is None else visaDLL 7 self.address = 'TCPIP::%s::inst0::INSTR' % self.ip 8 self.resourceManager = visa.ResourceManager(self.visaDLL) 9 10 def open(self): 11 self.instance = self.resourceManager.open_resource(self.address) 12 self.instance.write('MMEM:STOR:SNP:FORM DB') 13 14 def close(self): 15 if self.instance is not None: 16 self.instance.close() 17 self.instance = None 18 19 def create_dir(self, path): 20 print('MMEM:MDIR "%s"' % path) 21 self.instance.write('MMEM:MDIR "%s"' % path) 22 23 def recall_sta(self, filename): 24 print('MMEM:LOAD "%s"' % filename) 25 self.instance.write('MMEM:LOAD "%s"' % filename) 26 # Time sleep in case of sta load uncompleted 27 time.sleep(0.5) 28 29 def wind_act(self, wind): 30 self.instance.write('DISP:WIND%d:ACT' % wind) 31 32 def wind_max(self, wind): 33 self.instance.write('DISP:MAX %s' % wind) 34 35 def trigger(self, status): 36 cmdList = {'hold': 'OFF', 'continuous': 'ON'} 37 self.instance.write('INIT1:CONT %s' % cmdList[status]) 38 39 def save_snp(self, name, n=2): 40 print('MMEM:STOR:SNP "%s.s%dp"' % (name, n)) 41 self.instance.write('MMEM:STOR:SNP "%s.s%dp"' % (name, n)) 42 43 def save_image(self, imagname, fmt): 44 assert fmt in ['jpg', 'png'], 'Invalid postfix of image' 45 print('MMEM:STOR:IMAG "%s.%s"' % (imagname, fmt)) 46 self.instance.write('MMEM:STOR:IMAG "%s.%s"' % (imagname, fmt)) 47 48 def reset(self): 49 self.instance.write('*RST') 50 51 def read_idn(self): 52 idn = self.instance.query('*IDN?') 53 print(idn) 54 return idn 55 56 def read_data(self, wind=1, trac=1, axis='x'): 57 posi = {'x': 'XAX?', 'y': 'FDAT?'} 58 data = self.instance.query('CALC%d:TRAC%d:DATA:%s' % (wind, trac, posi[axis])) 59 return eval(data) 60 61 def tran_file(self): 62 re = self.instance.query(":MMEM:TRAN? 'D:\\22.S2P'") 63 with open("x.S2P", 'w') as f: 64 f.write(re) 65 print(type(re)) 66 67 if __name__ == '__main__': 68 e50 = E50X('192.168.1.17') 69 e50.open() 70 e50.read_idn() 71 e50.tran_file() 72 e50.close()
4.2 安捷伦C34970A (GPIB)
1 import visa 2 3 class A34X(): 4 def __init__(self): 5 self.address = 'GPIB0::8::INSTR' 6 self.visaDll = 'c:/windows/system32/visa32.dll' 7 self.resourceManager = visa.resourceManager(self.visaDll) 8 def open(self): 9 self.instance = resourceManager.open_resource(self.address) 10 self.idn = self.instance.query('*IDN?') 11 print(self.idn) 12 13 def reset(self): 14 self.instance.write('*RST') 15 16 def set_dc(self): 17 self.instance.write('CONF:CURR:DC AUTO, (@119, 120)')