PyVISA使用——用python控制TEK示波器源码实现
項目要求
項目上提出自動化測試需求,要求能夠對板級信號使用示波器等儀器做自動化測量
實現方案
使用PyVISA 方案實現。
VISA (Virtual Instrument Software Architecture) 是一個用于訪問測量儀器和控制計算機之間的接口標準,由美國國家儀器公司(National Instruments)推出,用于實現儀器之間的通信和控制。VISA提供了一組標準API函數,可以實現多種通信協議和連接方式的儀器控制。VISA相比于VXI11更加靈活,支持多種接口(底層協議),比如GPIB,RS232,USB, VXIBus等,對于儀器控制有更強大的功能。
Pyvisa是一個基于Python語言開發的訪問VISA資源的工具包。通過調用VISA標準API函數來實現與儀器的通信和控制。Pyvisa提供了一組Python的API函數,可以方便地訪問VISA庫中的函數和方法,從而實現與儀器的數據讀取、寫入、控制等操作。Pyvisa相比于LabVIEW,Pyvisa是一種跨平臺的軟件,可以在Linux,Windows和Mac OS上運行,且其擁有更靈活的用戶界面,可以自行定制。
如果該腳本運行在服務器上,建議使用Pycharm Professional 或者VSCode + Remote-SSH 插件進行開發,即本地開發,遠程部署或調試。
本例使用SCPI命令訪問示波器的VISA庫,SCPI命令的格式見示波器軟件編程手冊
腳本實現功能
(1)連接示波器
注意:電腦并沒有使用NI-VISA后臺,而是使用純python代碼實現的Pyvisa-py, 因此需要提前安裝下 pip install -U pyvisa-py
(2)簡單設置示波器參數,包括channal 選擇,橫軸窗口設置,縱軸電壓窗口設置,Trigger觸發方式選擇
(3)波形數據以csv 和圖片格式保存到本地
(4)保存示波器的截圖到本地
腳本與注釋
import time import pyvisa as visa import numpy as np import matplotlib.pyplot as plt import pandas as pd from datetime import datetime from pyvisa.errors import VisaIOError from PIL import Image# rm = visa.ResourceManager('@py') # rm.list_resources() # Tek = rm.open_resource('TCPIPO::10.163.xxx.xxx::INSTR') # Tek.timeout=10000 # print(Tek.query('*IDN?')) # self.inst.write('*RST') # self.inst.write('AUTOSET EXECUTE')class Tektronix_DPO:def __init__(self):self.rm = visa.ResourceManager('@py')self.rm.list_resources()self.inst = self.rm.open_resource('TCPIPO::10.163.xxx.xxx::INSTR')self.inst.timeout=10000print(self.inst.query('*IDN?'))self.inst.write('CLEAR')self.inst.write('ACQuire:MODe?')self.inst.write('ACQUIRE:STOPAFTER RUNSTOP')self.inst.write('ACQuire:STATE RUN')self.inst.write('autoset EXECUTE') # autosetdef set_HORIZONTAL(self, POSITION, SCALE): #horizontal settingsself.inst.write('HORIZONTAL:POSITION %s'%POSITION) #position means trigger point on the screen /%self.inst.write('HORIZONTAL:SCALE %se-6'%SCALE) #scale means step /usdef open_ch(self,ch): # open channalself.inst.write('DISplay:GLObal:CH%s:STATE ON'%ch)def close_ch(self,ch): # close channalself.inst.write('DISplay:GLObal:CH%s:STATE OFF'%ch)def vertical_ch(self,ch,scale,position): #channal settings,self.inst.write('CH%s:BANDWIDTH FULl'%ch) # at its maximum bandwidthself.inst.write('CH%s:SCAle %sE-3'%(ch,scale)) #channal scale/mvself.inst.write('CH%s:POSition %s'%(ch,position)) #channal divisions above the center graticuleself.inst.write('CH%s:COUPLING DC'%ch) # DC couplingself.inst.write('CH%s:TERMINATION 10.0E+5'%ch) #channal input resistence is 1MΩdef trigger_set(self,ch,level): #trigger settingsself.inst.write('TRIGGER:A:EDGE:COUPLING DC') # DC trigger coupling with input signal to the trigger circuitryself.inst.write('TRIGGER:A:EDGE:SOURCE CH%s'%ch)self.inst.write('TRIGGER:A:EDGE:SLOPE RISE') #triggers on the rising edge of the signalself.inst.write('TRIGGER:A:LEVEL:CH%s %s'%(ch,level)) # level specifies channal trigger level for seach 1, /Vdef begin_trigger(self): #start once trigger actionself.inst.write('acquire:state 0') # stopself.inst.write('acquire:stopafter SEQUENCE') # singleself.inst.write('acquire:state 1') # runself.inst.query('*opc?') # syncdef data_caul(self,ch): #calculate the channal valueself.inst.write("HEADER 0")self.inst.write('DATA:SOURCE CH%s'%ch)self.inst.write("DAT:ENC SRI") # Signed Binary Format, LSB orderself.inst.write("DAT:WIDTH 1")self.inst.write("DAT:START 1")recordLength = int(self.inst.query('horizontal:recordlength?'))self.inst.write("DAT:STOP {0}".format(recordLength)) # Set data stop to match points available# Fetch horizontal scaling factorsxinc = float(self.inst.query("WFMO:XINCR?"))xzero = float(self.inst.query("WFMO:XZERO?"))pt_off = int(self.inst.query("WFMO:PT_OFF?"))# Fetch vertical scaling factorsymult = float(self.inst.query("WFMO:YMULT?"))yzero = float(self.inst.query("WFMO:YZERO?"))yoff = float(self.inst.query("WFMO:YOFF?"))# Fetch waveform data and save as csv filerawData = self.inst.query_binary_values('curve?', datatype='b', container=np.array) dataLen = len(rawData)t0 = (-pt_off * xinc) + xzero with open('horizonal_vector.csv',mode='w') as file:for i in range(0,dataLen):xvalues = t0 + xinc * i # Create timestamp for the data pointfile.write(str(xvalues))file.write(",") yvalues= float(rawData[i] - yoff) * ymult + yzero # Convert raw ADC value into a floating point valuefile.write(str(yvalues))file.write("\n") # plotting the measurement figuredata = pd.read_csv("horizonal_vector.csv")data_x = data.iloc[:,0]data_y = data.iloc[:,1]plt.plot(data_x, data_y)plt.title('channel 1') # plot labelplt.xlabel('time (seconds)') # x labelplt.ylabel('voltage (volts)') # y labelprint("look for plot window...")plt.savefig('test.png') #save test pictureplt.show()def close(self):self.inst.close()self.rm.close()def get_screen(self):self.inst.write("HARDCopy:PORT FILE;")self.inst.write("EXPort:FORMat PNG")self.inst.write("HARDCopy:FILEName \"C:\\est_Temp\\Temp.png\"")self.inst.write("HARDCopy STARt")self.inst.write("FILESystem:READFile \"C:\\Low_Speed_Test_Temp\\Temp.png\"")imgData = self.inst.read_raw()dt = datetime.now()fileName = dt.strftime("DPO70000_%Y%m%d_%H%M%S.png") # Generate a filename with date and timefile = open(fileName, "wb")file.write(imgData)file.close()self.inst.write('FILESystem:DELEte \"C:\\Test_Temp\\Temp.png\"') # Delete image file from instrument's hard disk.if __name__ == "__main__":my=Tektronix_DPO()my.set_HORIZONTAL(0,40E-3)my.open_ch(1)my.vertical_ch(1,200,0)my.trigger_set(1,0)my.begin_trigger()my.data_caul(1)my.get_screen()my.close()參考
【1】TEK DPO系列示波器編程手冊
【2】PyVISA官方文檔
【3】TEK 技術交流論壇
總結
以上是生活随笔為你收集整理的PyVISA使用——用python控制TEK示波器源码实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 关于12306火车票销售的简单思考
- 下一篇: 慢聊Go之JSON编码解码中的道法术