python 操作TK示波器(NI-VISA)

NI-VISA这是一种美国的一家公司的协议,主要用来和仪器通信,当然这只是一种通信的格式,具体的操作我们还是要参照示波器的说明书。

我们直接采用Python里面自带的NI—VISA库文件。pip install pyvisa,然后安装好NI-VISA的驱动,百度到官网即可下载安装。

通过VISA发送相应命令(示波器编程文档有命令集)即可完成对示波器的控制,并且通过VISA可以接收返回值,比如波形数据等。

这里是通过USB来与示波器通信


1         rm = visa.ResourceManager()
2         # res = rm.list_resources()
3         # print(rm)
4         # print(res)
5         self.inst = rm.open_resource('USB0::0x0699::0x0528::C019161::INSTR')


第一行是得到visa资源管理器,第二行的res会是返回当前与电脑连接的端口地址,采用print()将其打印出来即可看到你的示波器地址。然后就可以注释掉了,然后使用第五行的代码即可打开示波器通信通道。

源码如下:

泰克示波器python控制 泰克示波器程控指令_恢复出厂设置


1 import matplotlib.pyplot as plt
  2 import visa
  3 import time
  4 from datetime import datetime # std library
  5 
  6 class Tektronix_MSO64:
  7     def __init__(self):
  8         visa_dll = 'c:/windows/system32/visa32.dll'
  9         self.rm = visa.ResourceManager()
 10         # res = rm.list_resources()
 11         # print(rm)
 12         # print(res)
 13         self.inst = self.rm.open_resource('USB0::0x0699::0x0528::C019161::INSTR')
 14         ##############################################
 15         self.inst.write("*IDN?")
 16         print(self.inst.read())
 17         self.inst.write('CLEAR')
 18         self.inst.write('ACQuire:MODe?')
 19         print(self.inst.read())
 20         self.inst.timeout = 25000
 21         self.inst.write('ACQUIRE:STOPAFTER RUNSTOP')
 22         self.inst.write('ACQuire:STATE RUN')
 23 
 24 
 25     def set_HORIZONTAL(self,POSITION,SCALE):#HORIZONTAL position,HORIZONTAL scale /us
 26         self.inst.write('HORIZONTAL:POSITION %s'%POSITION)
 27         self.inst.write('HORIZONTAL:SCALE %se-6'%SCALE)
 28 
 29     def open_ch(self,ch):#关闭相应通道
 30         self.inst.write('DISplay:GLObal:CH%s:STATE ON'%ch)
 31 
 32     def close_ch(self,ch):#打开相应通道
 33         self.inst.write('DISplay:GLObal:CH%s:STATE OFF'%ch)
 34 
 35     def vertical_ch(self,ch,scale,position):#通道,ch scale/mv,ch POSition,
 36         self.inst.write('CH%s:BANDWIDTH FULl'%ch)#at its maximum bandwidth
 37         self.inst.write('CH%s:SCAle %sE-3'%(ch,scale))
 38         self.inst.write('CH%s:POSition %s'%(ch,position))
 39         self.inst.write('CH%s:COUPLING DC'%ch)#直流
 40         self.inst.write('CH%s:TERMINATION 10.0E+5'%ch)#1兆欧
 41 
 42     def trigger_set(self,ch,level):#通道,触发电压
 43         self.inst.write('TRIGGER:A:EDGE:COUPLING DC')#边沿触发
 44         self.inst.write('TRIGGER:A:EDGE:SOURCE CH%s'%ch)
 45         self.inst.write('TRIGGER:A:EDGE:SLOPE RISE')#上升沿触发
 46         self.inst.write('TRIGGER:A:LEVEL:CH4 %s'%level)
 47 
 48     def begin_trigger(self):#开启一次触发
 49         self.inst.write('ACQuire:STOPAfter SEQuence')
 50         while 1:#等触发了才借宿
 51             time.sleep(1)
 52             self.inst.write('TRIGGER:STATE?')
 53             TRIGGER_STATE =self.inst.read()
 54             if TRIGGER_STATE[0] == "S":
 55                 print('have triggered')
 56                 break
 57 
 58     def data_caul(self,ch):#通道
 59         self.inst.write('DATA:SOURCE CH%s'%ch)
 60         self.inst.write('DATa:ENCdg ASCIi')
 61         self.inst.write('WFMOUTPRE:BYT_NR 4')
 62         self.inst.write('DATA:START 1')
 63         self.inst.write('DATA:STOP 250e6')
 64         self.inst.write('WFMOUTPRE?')
 65         preamble= self.inst.read()
 66         #获取HORIZONTAL:POSITION
 67         self.inst.write('HORIZONTAL:POSITION?')
 68         HORIZONTAL_p=self.inst.read()
 69         HORIZONTAL_pfloat=float(HORIZONTAL_p)
 70         #获取HORIZONTAL:SCALE
 71         self.inst.write('HORIZONTAL:SCALE?')
 72         HORIZONTAL_S=self.inst.read()
 73         HORIZONTAL_Sfloat=float(HORIZONTAL_S)
 74         #获取ch POSition
 75         self.inst.write('CH%s:POSition?'%ch)
 76         divus_str = self.inst.read()
 77         divus_float = float(divus_str)
 78         #获取ch SCAle
 79         self.inst.write('CH%s:SCAle?'%ch)
 80         div_str = self.inst.read()
 81         div_float = float(div_str)
 82         #########################################################获取采样点数目
 83         j=0
 84         point_str=' '
 85         for i in range(0,len(preamble)):
 86             if preamble[i]==',':
 87                 j+=1
 88             elif j==4:
 89                 point_str=point_str+preamble[i]
 90             elif j==5:
 91                 point_len=len(point_str)
 92                 point_str=point_str[2:(point_len-6)]
 93                 break
 94         point_int=int(point_str)
 95         print('point_num:%d'%point_int)
 96         ######################################################数据处理
 97         data = self.inst.query('CURVE?')
 98         x = []
 99         dat = [' ']
100         dat1 = []
101         j = 0
102         for i in range(0, len(data)):
103             if data[i] == ',':
104                 dat1.append(float(dat[j])/32000*div_float*5-div_float*divus_float)
105                 x.append((int(j)/point_int*HORIZONTAL_Sfloat*10-HORIZONTAL_Sfloat*10*HORIZONTAL_pfloat/100))
106                 j += 1
107                 dat.append(' ')
108             else:
109                 dat[j] = dat[j] + data[i]
110         plt.plot(x, dat1)
111 
112     def close(self):
113         self.inst.close()
114         self.rm.close()
115 
116     def get_screen(self):
117         self.inst.write('SAVE:IMAGE "E:/waveform_screen.bmp"')
118         time.sleep(1)
119         self.inst.write('FILESYSTEM:READFILE "E:/waveform_screen.bmp"')
120         img = self.inst.read_raw()
121         dt = datetime.now()
122         fileName = dt.strftime("%Y%m%d_%H%M%S.bmp")  # 以当前时间建立文件名
123         imgFile = open('./waveform/' + fileName, "wb")  # 打开图片文件,如果没有就会新建一个
124         imgFile.write(img)
125         imgFile.close()
126         self.inst.write('FILESYSTEM:DELETE "E:/waveform_screen.bmp"')
127 
128 
129 
130 
131 
132 if __name__ == "__main__":
133     fig = plt.figure()
134     my=Tektronix_MSO64()
135     my.set_HORIZONTAL(10,200)
136     my.open_ch(4)
137     my.open_ch(3)
138     my.open_ch(2)
139     my.open_ch(1)
140     my.vertical_ch(4,2000,1)
141     my.vertical_ch(3,2000,2)
142     my.vertical_ch(2,2000,2)
143     my.vertical_ch(1,2000,2)
144     my.trigger_set(4,2)
145     my.begin_trigger()
146     my.data_caul(4)
147     my.data_caul(3)
148     my.data_caul(2)
149     my.data_caul(1)
150     my.get_screen()
151     plt.show()
152     my.close()


泰克示波器python控制 泰克示波器程控指令_开发语言_02

根据示波器编程文档,通过visa发送相应命令,接收相应返回值即可完成对示波器的控制,获取数据等,具体命令可以参考相应的编程文档。

此代码具有以下功能:

设置水平轴相关设置;

设置通道相关设置;

打开,关闭相应通道;

设置触发;

开启一次触发;

获取波形数据,并处理数据,然后通过plot()显示出来;

获取截屏图片,保存到pc本地;

下面是其他控制代码。可以设置测量方式,读取泰克示波器的上升沿等

# coding=utf-8
from datetime import datetime
import pyvisa
import time


class Tektronix_MSO64:

    def __init__(self):
        rm = pyvisa.ResourceManager("C:/Windows/System32/visa32.dll")
        self.inst = rm.open_resource('USB0::0x0699::0x0368::C031376::INSTR')
        self.inst.write("*IDN?")  # 返回示波器识别码
        # print(self.inst.read())
        self.inst.write('*CLS')  # 清除示波器状态
        self.inst.write('*ESR?')  # 查询标准状态寄存器的内容
        # print(self.inst.read())
        self.inst.write('ALLEV?')  # 使示波器返回所有事件及其消息
        # print(self.inst.read())
        # self.inst.write('FACTORY')  # 恢复出厂设置
        self.inst.timeout = 50000

    def close(self):
        self.inst.write('*CLS')  # 清除示波器状态
        self.inst.write('*ESR?')  # 查询标准状态寄存器的内容
        # print(self.inst.read())
        # self.inst.write('FACTORY')  # 恢复出厂设置
        self.inst.close()

    def set_horizontal(self, VOLTS, SCALE):
        self.inst.write('CH1:VOLTS %s' % VOLTS)  # 设置示波器的垂直刻度
        self.inst.write('HOR:MAIN:SCALE %se-3' % SCALE)  # 设置示波器的水平刻度
        self.inst.write('TRIG:MAIN:LEVEL 2.4')  # 触发装置设置为2.4V

    def operate_set(self):
        self.inst.write('AUTORANGE:STATE ON')  # 启动自动量程功能
        self.inst.write('ACQUIRE:STOPAFTER SEQUENCE')  # 按下RUN/STOP按钮将示波器设置为停止采集
        self.inst.write('ACQuire:STATE ON')  # 开始采集数据,将采集次数重置为0

    # self.inst.write('*OPC?')  # 查询OPC操作是否已完成
    # print(self.inst.read())

    def period_measure(self):
        self.inst.write('MEASU:IMMED:TYPE PERIOD')  # 设置为测量周期
        self.inst.write('MEASU:IMMED:VALUE?')  # 执行前面命令指定的立即示波器测量
        global reperiod
        str_rperiod = self.inst.read()
        str_rperiod = str_rperiod[str_rperiod.rfind(' '):]
        rperiod = float(str_rperiod) * 1000
        rperiod = '%.2f' % rperiod
        reperiod = float(rperiod)
        print('实测周期:', reperiod)

    def frequency_measure(self):
        self.inst.write('MEASU:IMMED:TYPE FREQ')  # 设置为测量频率
        self.inst.write('MEASU:IMMED:VALUE?')  # 执行前面命令指定的立即示波器测量
        global rfrequent
        str_frequency = self.inst.read()
        str_frequency = str_frequency[str_frequency.rfind(' '):]
        rfrequency = float(str_frequency)
        rfrequency = '%.2f' % rfrequency
        rfrequent = float(rfrequency)
        print('实测频率:', rfrequent)

    def duty_measure(self):
        self.inst.write('MEASU:IMMED:TYPE PDUTY')  # 设置为测量占空比
        self.inst.write('MEASU:IMMED:VALUE?')  # 执行前面命令指定的立即示波器测量
        global reduty
        str_duty = self.inst.read()
        str_duty = str_duty[str_duty.rfind(' '):]
        rduty = float(str_duty)
        rduty = '%.2f' % rduty
        reduty = float(rduty)
        print('实测占空比:', reduty)

    def rise_time_measure(self):
        self.inst.write('MEASU:IMMED:TYPE RISE')  # 设置为测量上升时间
        self.inst.write('MEASU:IMMED:VALUE?')  # 执行前面命令指定的立即示波器测量
        str_rise = self.inst.read()
        str_rise = str_rise[str_rise.rfind(' '):]
        rise = float(str_rise)
        rise = '%.2f' % rise
        riser = float(rise)
        print('实测上升时间:', riser)

    def positive_pulse_width_measure(self):
        self.inst.write('MEASU:IMMED:TYPE PWIDTH')  # 设置为测量正脉冲宽度
        self.inst.write('MEASU:IMMED:VALUE?')  # 执行前面命令指定的立即示波器测量
        str_positive_pulse_width = self.inst.read()
        str_positive_pulse_width = str_positive_pulse_width[str_positive_pulse_width.rfind(' ')]
        positive_pulse_width = float(str_positive_pulse_width)
        positive_pulse_width = '%.2f' % positive_pulse_width
        print('实测正脉冲宽度为:', positive_pulse_width)

    def negative_pulse_width_measure(self):
        self.inst.write('MEASU:IMMED:TYPE NWIDTH')  # 设置为测量负脉冲宽度
        self.inst.write('MEASU:IMMED:VALUE?')  # 执行前面命令指定的立即示波器测量
        str_negative_pulse_width = self.inst.read()
        str_negative_pulse_width = str_negative_pulse_width[str_negative_pulse_width.rfind(' ')]
        negative_pulse_width = float(str_negative_pulse_width)
        negative_pulse_width = '%.2f' % negative_pulse_width
        print('实测负脉冲宽度:', negative_pulse_width)

    def basic_set(self):
        self.inst.write('*ESR?')  # 查询标准状态寄存器的内容
        # print(self.inst.read())
        self.inst.write('ALLEV?')  # 使示波器返回所有事件及其消息
        # print(self.inst.read())
        self.inst.write('WFMPRE?')  # 查询波形数据的编码类型
        # print(self.inst.read())

    def waveform_save(self):
        self.inst.write('RECALL:WAVEFORM' 'D:\TST-PRD\TST-01.CSV')
        self.inst.write('SELECT:REFC')

    def get_screen(self):
        self.inst.write('SAVE:IMAGE "D:/waveform_screen.bmp"')
        time.sleep(1)
        self.inst.write('FILESYSTEM:READFILE "D:/waveform_screen.bmp"')
        img = self.inst.read_raw()
        dt = datetime.now()
        fileName = dt.strftime("%Y%m%d_%H%M%S.bmp")  # 以当前时间建立文件名
        imgFile = open('./waveform/' + fileName, "wb")  # 打开图片文件,如果没有就会新建一个
        imgFile.write(img)
        imgFile.close()
        self.inst.write('FILESYSTEM:DELETE "D:/waveform_screen.bmp"')

def oscilloscoper():
    rm = Tektronix_MSO64()
    rm.set_horizontal(2.0, 10)
    # rm.operate_set()
    rm.period_measure()
    rm.frequency_measure()
    rm.duty_measure()
    rm.basic_set()
    rm.close()

if __name__ == "__main__":
    oscill = Tektronix_MSO64()
    oscill.set_horizontal(2.0, 1)
    # oscill.operate_set()
    oscill.period_measure()
    oscill.frequency_measure()
    oscill.duty_measure()
    # oscill.waveform_save()
    oscill.basic_set()
    # oscill.get_screen()