项目要求
项目上提出自动化测试需求,要求能够对板级信号使用示波器等仪器做自动化测量
实现方案
使用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)保存示波器的截图到本地文章来源:https://www.toymoban.com/news/detail-687851.html
脚本与注释
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=10000
print(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') # autoset
def set_HORIZONTAL(self, POSITION, SCALE): #horizontal settings
self.inst.write('HORIZONTAL:POSITION %s'%POSITION) #position means trigger point on the screen /%
self.inst.write('HORIZONTAL:SCALE %se-6'%SCALE) #scale means step /us
def open_ch(self,ch): # open channal
self.inst.write('DISplay:GLObal:CH%s:STATE ON'%ch)
def close_ch(self,ch): # close channal
self.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 bandwidth
self.inst.write('CH%s:SCAle %sE-3'%(ch,scale)) #channal scale/mv
self.inst.write('CH%s:POSition %s'%(ch,position)) #channal divisions above the center graticule
self.inst.write('CH%s:COUPLING DC'%ch) # DC coupling
self.inst.write('CH%s:TERMINATION 10.0E+5'%ch) #channal input resistence is 1MΩ
def trigger_set(self,ch,level): #trigger settings
self.inst.write('TRIGGER:A:EDGE:COUPLING DC') # DC trigger coupling with input signal to the trigger circuitry
self.inst.write('TRIGGER:A:EDGE:SOURCE CH%s'%ch)
self.inst.write('TRIGGER:A:EDGE:SLOPE RISE') #triggers on the rising edge of the signal
self.inst.write('TRIGGER:A:LEVEL:CH%s %s'%(ch,level)) # level specifies channal trigger level for seach 1, /V
def begin_trigger(self): #start once trigger action
self.inst.write('acquire:state 0') # stop
self.inst.write('acquire:stopafter SEQUENCE') # single
self.inst.write('acquire:state 1') # run
self.inst.query('*opc?') # sync
def data_caul(self,ch): #calculate the channal value
self.inst.write("HEADER 0")
self.inst.write('DATA:SOURCE CH%s'%ch)
self.inst.write("DAT:ENC SRI") # Signed Binary Format, LSB order
self.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 factors
xinc = 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 factors
ymult = 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 file
rawData = 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 point
file.write(str(xvalues))
file.write(",")
yvalues= float(rawData[i] - yoff) * ymult + yzero # Convert raw ADC value into a floating point value
file.write(str(yvalues))
file.write("\n")
# plotting the measurement figure
data = 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 label
plt.xlabel('time (seconds)') # x label
plt.ylabel('voltage (volts)') # y label
print("look for plot window...")
plt.savefig('test.png') #save test picture
plt.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 time
file = 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 技术交流论坛文章来源地址https://www.toymoban.com/news/detail-687851.html
到了这里,关于PyVISA使用——用python控制TEK示波器源码实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!