文章目录

  • 前言
  • 一、软硬件准备
  • 二、使用步骤
  • 1.引入库
  • 2.连接仪器、配置使用代码
  • 总结


前言

本文主要介绍逆变器测试常用仪器恒河功率计的基于pyvisa控制使用。


一、软硬件准备

开始前,计算机安装python开发环境,如Anaconda、VS code。
使用pip 指令安装pyvisa 库。
到横河功率计官网下载安装USB驱动,

二、使用步骤

1.引入库

代码如下(示例):

import pyvisa as visa
import time

2.连接仪器、配置使用代码

代码如下(示例):

# -*- coding: utf-8 -*-
"""
Created on Wed Jun 16 14:02:18 2021

@author: USER
"""
import pyvisa as visa
import time
def Error_Record(e):
    with open(r'D:\ATE\Error_Record.txt','r+') as f:
        old = f.read()  # 先读取内容保存一份
        f.seek(0)  # 将光标定位到起始位置
        f.writelines(time.strftime('%Y.%m.%d %H:%M:%S', time.localtime(time.time()))+'\n')
        f.writelines('Error occured in: ' + str(e)+'\n')
        f.writelines("\n*******************\n")
        f.write(old)
        f.close()

class WT():
    name="YOKOGAWA,WT"
    chan="element1,element2,element3,element4,element5,element6"
    answer=""             #存储最近发指令,仪器回复的结果
    Reconnect_Resource=0
    Save_Stop=False
    Function1={
                "Urms":"Urms",
                "Irms":"Irms",
                "Udc":"Udc",
                "Idc":"Idc",
                "Uac":"Uac",
                "Iac":"Iac",
                "P":"P",
                "S":"S",
                "Q":"Q",
                "PF":"Lambda",
                "FreqU":"FU",
                "FreqI":"FI",
                "Ithd":"Ithd",
                "Uthd":"Uthd",
                "U(k)":"Uk",
                "I(k)":"Ik",
                "Uhdf(k)":"Uhdfk",
                "Ihdf(k)":"Ihdfk",
                "Q(k)":"Qk",
                "P(k)":"Pk",
                "S(k)":"Sk",
                "PF(k)":"Lambdak",
        }
    
    Function2={
                "η1":"ETA1",
                "η2":"ETA2",
                "η3":"ETA3",
                "η4":"ETA4",
                "η5":"ETA5",
                "η6":"ETA6",
                "F1":"F1",
                "F2":"F2",
                "F3":"F3",
                "F4":"F4",
                "F5":"F5",
                "F6":"F6",
                "F7":"F7",
                "F8":"F8",
                "F9":"F9",
                "F10":"F10",
                "F11":"F11",
                "F12":"F12",
                "F13":"F13",
                "F14":"F14",
                "F15":"F15",
                "F16":"F16",
                "F17":"F17",
                "F18":"F18",
                "F19":"F19",
                "F20":"F20"
        }
    SaveItem=[]
    SavePath=r"D:\ATE\Testdata"
    SaveUpdate=200           #200ms更新速率,注意单位
    SaveLine=100000
    Thread_Stop=True
    PA=0
    Save_Name=""
    def __init__(self):
        rm = visa.ResourceManager('C:/Windows/System32/visa64.dll')
        if len(rm.list_resources())>0:
            for item in rm.list_resources():
                
                A = rm.open_resource(item)
                try:
                    self.answer=A.query('*IDN?')
                except Exception as e:
                    
                    error="函数WT_init:"

                if self.answer.find(self.name)!=-1:
                    print("横河功率计连接成功:  ",self.answer)
                    A.write(":communicate:remote on")   #设定远程控制,防止手动操作影响
                    A.write(":communicate:header 0") #设定回复不包括字头
                    A.write(":numeric:format ASCII")    #设定查询回复数据类型为ASCII
                    self.PA=A
                    self.Reconnect_Resource=item
                    if self.answer.find("WT5000")!=-1:
                        A.write(":scaling:STAte:all 1")
                        A.write(":scaling:ct:all 1000")    #设定查询回复数据类型为ASCII
                    break
                else:
                    A.close()
    def Reconnection(self):
        self.PA.close()
        rm = visa.ResourceManager('C:/Windows/System32/visa64.dll')
        if len(rm.list_resources())>0:
            for item in rm.list_resources():
                if item == self.Reconnect_Resource:
                    A = rm.open_resource(item)
                    try:
                        self.answer=A.query('*IDN?')
                    except Exception as e:
                        
                        error="函数WT_init:"

                    if self.answer.find(self.name)!=-1:
                        print("横河功率计重接成功:  ",self.answer)
                        self.PA=A
                        break
                    else:
                        A.close()
    def WT_Close(self):
        self.PA.write(":communicate:remote oFF\n")
        time.sleep(2)
        self.answer=self.PA.query(":communicate:remote?")
        if self.answer.lower().find("0") != -1:
            return True
        else:
            return False
    def WT_Range(self,Channel="all",Auto="",Type="Voltage",Range="",crest_factor=3):
        '''
        Parameters
        ----------
        Channel : string. 通道选择,全部选"all",其它输入"element1/element2/element3.../element6"
            DESCRIPTION. The default is "all".
        
        Type   : string, Voltage/Current,电压电流选择
        
        Range  : string, 量程设置,crest_factor=3时,
                 对于电流,可选档为1A,2A,5A,10A,20A,50A
                 对于电压,可选档为1.5V,3V,6V,10V,15V,30V,60V,100V,150V,300V,600V,1000V
                 crest_factor=6时,
                 对于电压,可选档为?
                 对于电流,可选档为?
        Auto : string, 自动量程开关,"1" 意为 auto range on, "0" 意为 auto range off.
        
        crest_factor : int, 3/6。预留参数,暂不支持修改
        Returns
        -------
        bool
            True,设置成功;False,设置失败
            回复值,请读取参数self.answer

        '''
        for Rei in range(0,5):
            try:
                if  Auto=="0" or Auto=="1":
                    command=":input:"+ Type +":auto:"+Channel+' '+Auto
                    self.PA.write(command)
                    command=":input:"+ Type +":auto?"
                    self.answer=self.PA.query(command).replace("\n","")
                    if Channel=="all":
                        if self.answer.count(" 1")!=6:
                            
                            return False
                        
                        return True
                    elif self.chan.find(Channel.lower()) !=-1:
                        if self.answer.split(";")[int(Channel.replace("element",""))-1].find(" 1")!=-1 :
                            
                            return True
                        else:
                            print(self.answer)
                            return False
                    else:
                        return False
                elif  Range!="":
                    a=float(Range.replace("A","" ).replace("V", ""))
                    command=":input:"+ Type +":range:"+Channel+' '+Range
                    self.PA.write(command)
                    command=":input:"+ Type +":range?"
                    self.answer=self.PA.query(command).replace("\n","")
                    if Channel=="all":
                        for item in self.answer.split(";"):
                            if float(item) != a:
                                return False
                        
                        return True
                    elif Channel=="element1" or Channel=="element2" or Channel=="element3" or Channel=="element4" or Channel=="element5" or Channel=="element6" :
                        if float(self.answer.split(";")[int(Channel.replace("element",""))-1])==a:
                            return True
                        else:
                            return False
                    
                    else:
                        return False
                else :
                    return None
            except Exception as e:
                self.Reconnection()
                error="函数WT_Range:"
                Error_Record(error+str(e))
                return False
        
    def WT_Filter(self,Channel="all",Type="freq",Range="",ON_OFF=""):
        for Rei in range(0,5):
            result=True
            try:
                if ON_OFF.upper()=="OFF" or ON_OFF.upper()=="ON"  :
                    command=":input:filter:"+Type+":"+Channel+" "+ON_OFF
                    self.PA.write(command)
                    
                    if self.chan.find(Channel.lower())!=-1:
                        command=":input:filter:"+Type+":"+Channel+"?"
                        self.answer=self.PA.query(command)
                        if ON_OFF.upper()=="OFF" and self.answer.find(ON_OFF.upper())==-1 :
                            result= False
                        elif ON_OFF.upper()=="ON" and self.answer.find("OFF")!=-1:
                            result= False
                    elif Channel.lower()=="all" :
                        command=":input:filter:"+Type+"?"
                        self.answer=self.PA.query(command)
                        if ON_OFF.upper()=="OFF" and self.answer.count("OFF")==6 :
                            pass
                        elif ON_OFF.upper()=="ON" and self.answer.count("OFF")==0:
                            pass
                        else:
                            result=False
                        
                if Range!="":
                    command=":input:filter:"+Type+":"+Channel+" "+Range
                    self.PA.write(command)
                    
                    command=":input:filter:"+Type+":"+Channel+"?"
                    self.answer=self.PA.query(command)
                
                return result
            except Exception as e:
                self.Reconnection()
                error="函数WT_Filter:"
                Error_Record(error+str(e))
                return False
            
    def WT_Update(self,t="200ms"):
        '''
        更新率设置
        Parameters
        ----------
        t : TYPE, optional
            DESCRIPTION. The default is "200ms".
            可选值,T=['50ms','100ms','200ms','500ms','1s','2s','5s','10s','20s',
                       '0.05s','0.1s','0.2s','0.5s','1000ms','2000ms','5000ms','10000ms','20000ms',
                     ]  
        Returns
        -------
        bool
            DESCRIPTION.

        '''
        for Rei in range(0,5):
            try:
                T=['50ms','100ms','200ms','500ms','1s','2s','5s','10s','20s',
                '0.05s','0.1s','0.2s','0.5s','1000ms','2000ms','5000ms','10000ms','20000ms',
                ]
                t=t.lower()
                if t in T :
                    
                        command=":Rate " + t
                        self.PA.write(command)
                        command=":Rate?"
                        self.answer=self.PA.query(command).replace("\n","")
                        re= float(self.answer.replace(":RATE ",""))
                        if t.find('ms') != -1 or t.find('MS') != -1:
                            t=float(t.replace("ms", "").replace("MS", ""))/1000
                        else:
                            t=float(t.replace("S", "").replace("s", ""))
                        
                        if t==re:
                            return True
                        else:
                            
                            return False
                                
                        
                    
                
                else:
                    return False
            except Exception as e:
                self.Reconnection()
                error="函数WT_Update:"
                Error_Record(error+str(e))
                return False
    
    def WT_Wiring(self,wiring="P1W2,P1W2,P1W2,P3W4"):
        '''
        接线设置
        Parameters
        ----------
        wiring : string, 常用值:"P1W2,P1W2,P1W2,P1W2,P1W2,P1W2","P1W2,P1W2,P1W2,P3W4"
            DESCRIPTION. The default is "P1W2,P1W2,P1W2,P3W4".

        Returns
        -------
        bool
            DESCRIPTION.

        '''
        for Rei in range(0,5):
            try:
                command = ":input:wiring?"
                re=self.PA.query(command).replace(":WIR ","").replace("\n","")
                if re==wiring.upper():
                    return True
                command = ":input:wiring "+wiring
                self.PA.write(command)
                command = ":input:wiring?"
                re=self.PA.query(command).replace(":WIR ","").replace("\n","")
                if re==wiring.upper():
                    return True 
                else:
                    return False
                
            except Exception as e:
                self.Reconnection()
                error="函数WT_Wiring:"
                Error_Record(error+str(e))
                return False

    def WT_Averaging(self,Counter=2,Type="EXP",State="OFF"):
        '''
        平均个数,平均类型,平均开关

        Parameters
        ----------
        counter : int,可选值2/4/8/16/32/64
            DESCRIPTION. The default is "2".
        Type : string,可选值EXP/Linear
            DESCRIPTION. The default is "EXP".
        State : string,可选值On/OFF
            DESCRIPTION. The default is "OFF".

        Returns
        -------
        bool
            DESCRIPTION.

        '''
        for Rei in range(0,5):
            try:
                command=":measure:averaging:state "+State
                l1=len(command)+2
                l2=self.PA.write(command)
                if l2!=l1 :
                    print(l1,l2)
                    return False
                
                command=":measure:averaging:type "+Type
                l1=len(command)+2
                l2=self.PA.write(command)
                if l2!=l1 :
                    print(l1,l2)
                    return False
                
                command=":measure:averaging:count "+str(Counter)
                l1=len(command)+2
                l2=self.PA.write(command)
                if l2!=l1 :
                    print(l1,l2)
                    return False
                return True
                
            except Exception as e:
                self.Reconnection()
                error="函数WT_Averaging:"
                Error_Record(error+str(e))
                return False
        
    def WT_SYNC(self,Channel="all",Source="U6"):
        '''
        

        Parameters
        ----------
        Channel : 设置对象,可选值 "all/element1/.../element6/SigmA/SigMB/sigmC"
            DESCRIPTION. The default is "all".
        Source : 同步源,可选值 I1~I6,U1~U6
            DESCRIPTION. The default is "U6".

        Returns
        -------
        bool
            DESCRIPTION.

        '''
        for Rei in range(0,5):
            try:
                command=":input:sync:"+Channel+" "+Source
                l1=len(command)+2
                l2=self.PA.write(command)
                if l2!=l1 :
                    print(l1,l2)
                    return False
                return  True
            except Exception as e:
                self.Reconnection()
                error="函数WT_SYNC:"
                Error_Record(error+str(e))
                return False

    def WT_UDF(self,Number,Expression,Name,Unit,ON_OFF=1):
        '''
        自定义参数功能,N
        umber int,对应F1~F20的数字号,
        Expression string,为表达式,
        Unit string,为单位,
        ON_OFF int,开关,1开0关

        Returns
        -------
        bool
            DESCRIPTION.

        '''
        for Rei in range(0,5):
            try:
                Expression='"'+Expression+'"'
                Name='"'+Name+'"'
                Unit='"'+Unit+'"'
                command=":measure:Function"+str(Number)+":Expression "+Expression
                self.PA.write(command)
                command=":measure:Function"+str(Number)+":Expression?"
                self.answer=self.PA.query(command)
                if self.answer.find(Expression)==-1 :
                    return False
                
                command=":measure:Function"+str(Number)+":Name "+Name
                self.PA.write(command)
                command=":measure:Function"+str(Number)+":Name?"
                self.answer=self.PA.query(command)
                if self.answer.find(Name)==-1 :
                    return False
                
                command=":measure:Function"+str(Number)+":Unit "+Unit
                self.PA.write(command)
                command=":measure:Function"+str(Number)+":Unit?"
                self.answer=self.PA.query(command)
                if self.answer.find(Unit)==-1 :
                    return False
                
                command=":measure:Function"+str(Number)+":Unit "+Unit
                self.PA.write(command)
                command=":measure:Function"+str(Number)+":Unit?"
                self.answer=self.PA.query(command)
                if self.answer.find(Unit)==-1 :
                    return False
                
                command=":measure:Function"+str(Number)+' '+str(ON_OFF)
                self.PA.write(command)
                
                return  True
            except Exception as  e:
                self.Reconnection()
                error="函数WT_UDF:"
                Error_Record(error+str(e))
                return False

    def WT_Integrate(self,Status="",Mode="",T1=0,T2=0,T3=0):
        '''
        
        
        该函数有三个功能,但同时只能设置一个功能,优先级为status>mode>time
        Parameters
        ----------
        Status : string, 可选值为“start/reset/stop”,控制积分开始/停止/结束
           
        Mode : 积分模式,只可设normal.
            
        T1 : int,积分时间H值设置,
          
        T2 : int,积分时间M值设置,
         
        T3 : int,积分时间S值设置,

        Returns
        -------
        bool
            DESCRIPTION.

        '''
        for Rei in range(0,5):
            try:
                if Status.lower()=="start":
                    command=":integrate:start"
                    l1=len(command)+2
                    l2=self.PA.write(command)
                    if l1==l2:
                        return True
                    else:
                        return False
                elif Status.lower()=="stop":
                    command=":integrate:stop"
                    l2=self.PA.write(command)
                    l1=len(command)+2
                    if l1==l2:
                        return True
                    else:
                        return False
                    
                elif Status.lower()=="reset":
                    command=":integrate:reset"
                    l2=self.PA.write(command)
                    l1=len(command)+2
                    if l1==l2:
                        return True
                    else:
                        return False
                    return True
                elif Mode.lower()=="normal":
                    command=":integrate:mode normal"
                    l2=self.PA.write(command)
                    l1=len(command)+2
                    if l1==l2:
                        return True
                    else:
                        return False
                    return True
                elif T1!=0 or T2!=0 or T3!=0:
                    command=":integrate:TMALL " + str(T1) + ',' + str(T2) + ',' + str(T3)
                    l2=self.PA.write(command)
                    l1=len(command)+2
                    if l1==l2:
                        return True
                    else:
                        
                        return False
                    return True
                else:
                    return False
            except Exception as e:
                self.Reconnection()
                error="函数WT_Integrate:"
                Error_Record(error+str(e))
                return False 
        
    def WT_HarSet(self,PLL,Order):
        '''
        

        Parameters
        ----------
        PLL : string, 可选值U1/U2/U3/U4/U5/U6
            谐波同步源. The default is "".
        Order : string, 输入形式"1,50"、"0,50"、"1,200".
            测量谐波次数

        Returns
        -------
        bool
            DESCRIPTION.

        '''
        for Rei in range(0,5):
            try:
                if PLL!="":
                    command=":harmonics1:PLLSOURCE " + PLL
                    l1=len(command)+2
                    l2=self.PA.write(command)
                    if l1!=l2:
                        return False
                if Order !=""  :
                    command=":harmonics1:order " + Order
                    l1=len(command)+2
                    l2=self.PA.write(command)
                    if l1==l2:
                        return True
                    else:
                        return False
                
            except Exception as e:
                self.Reconnection()
                error="函数WT_Harset:"
                Error_Record(error+str(e))
                return False
        
    def WT_ItemValue(self,Item="",Channel="",Order=""):
        for Rei in range(0,5):
            try:
                if Item.lower().find("(k)")==-1:
                    command=':numeric:normal:item1 '+self.Function1[Item]+','+Channel
                elif Item.lower().find("(k)")!=-1:
                    command=':numeric:normal:item1 '+self.Function1[Item]+','+Channel+','+Order
                l1=len(command)+2
                l2=self.PA.write(command)
                if l1!=l2:
                    return False
                command=":numeric:normal:number 1"
                l1=len(command)+2
                l2=self.PA.write(command)
                if l1!=l2:
                    return False
                command=":numeric:normal:value?"
                self.answer=self.PA.query(command).replace('\n','')
                inittime=time.time()
                while self.answer=="nan" or self.answer=="NAN" :
                    command=":numeric:normal:value?"
                    self.answer=self.PA.query(command).replace('\n','')
                    if time.time()-inittime>60:
                        break
                return float(self.answer)
                
                
            except Exception as e:
                self.Reconnection()
                error="函数WT_ItemValue:"+self.answer
                Error_Record(error+str(e))
                return False
            
    def WT_SaveSetting(self,Element,Item,Item2,Order):
        '''
        Parameters
        ----------
        Element : list,输入格式如[1,2,3]、[4,5,6]、[1,2,3,4,5,6].
            保存通道选择。
        Item : list, 输入格式如['Urms','Irms',...],
            注意,该项输入的是与通道选择有关的
        Item2 : list, 输入格式如['F1','η1','F2','η2',...],
            注意,该项输入的是与通道选择无关的
        Order : int,取值1~100,
            记录谐波最大次数

        Returns
        -------
        bool
            DESCRIPTION.

        '''
        for Rei in range(0,5):
            try:
                command=[]
                n_normal=0
                item_normal=['Date','Time']
                
                for item2 in Item:
                    if item2 in self.Function1 and item2.find('(k)')==-1:
                        for item1 in Element:
                            if item1>0 and item1 < 7 :
                                n_normal+=1
                                header=':numeric:normal:item'
                                command.append(header+str(n_normal)+' '+self.Function1[item2]+','+str(item1))
                                item_normal.append(item2+'-'+str(item1))
                                
                for item1 in Item2:
                    if item1 in self.Function2:
                        n_normal+=1
                        command.append(':numeric:normal:item'+str(n_normal)+' '+item1)
                        if item1.upper().find("F") !=-1:
                            mid1=item1[1:]
                            self.answer=self.PA.query(":measure:function"+mid1+":expression?").replace("\n","").replace('"','')
                            item_normal.append(self.answer)
                        else:
                            item_normal.append(item1)
                    else:
                        error="函数WT_SaveSetting:"
                        Error_Record("参数错误,既有信息无法找到此参数"+item2)
                        return False
                
                for item2 in Item:
                    if item2 in self.Function1 and item2.find('(k)')!=-1:
                        for item1 in Element:
                            if item1>0 and item1 < 7 :                            
                                header=':numeric:normal:item'
                                for i in range(1,Order+1):
                                    n_normal+=1
                                    command.append(header+str(n_normal)+' '+self.Function1[item2]+','+str(item1)+','+str(i))
                                    item_normal.append(item2+'-'+str(item1)+'-'+str(i))
                                    
                self.SaveItem=item_normal
                
                # self.PA.write(":numeric:normal:number "+str( n_normal))
                # self.PA.write(":numeric:list:order "+str(Order))
                command.append(":numeric:format ASCII")
                command.append(":numeric:normal:number "+str( n_normal))
                command.append(":numeric:list:order "+str(Order))
                for item in command:
                    l1=len(item)+2
                    l2=self.PA.write(item)
                    if l1==l2:
                        continue
                    else:
                        return False
                return True
            except Exception as e:
                self.Reconnection()
                error="函数WT_SaveSetting:"
                Error_Record(error+str(e))
                return False
            
    def WT_SaveFile(self,Time=60,Name=""):
        try:
            result=[]
            result.append(','.join(self.SaveItem))
            counter=int(Time * 60 / self.SaveUpdate *1000)+10
            if counter > 1:
                inittime=time.time()
                for i in range(0,counter):
                    
                    RX0=self.PA.query(":SYSTem:date?;:System:time?").replace("\n",'')
                    RX1=self.PA.query(":numeric:normal:value?")
                    RX=RX0+RX1
                    
                    if i>0 :
                        result.append(RX.replace('\n','').replace('";"',',').replace('"',',').replace(',','',1))
                    
                    if self.Save_Stop:
                        break
                    while time.time()-inittime < self.SaveUpdate/1000*(i+1):
                        pass
                    
            if Name=="" and self.Save_Name=="":
                Name=time.strftime('%Y.%m.%d %H:%M:%S', time.localtime(time.time())).replace(':','.')
            elif Name=="" and self.Save_Name!="":
                Name=self.Save_Name
            with open(self.SavePath+'\\'+Name+'.csv','w') as f:
                for item in result:
                    f.writelines(item+'\n')
                f.close()
        except Exception as e:
            error="函数WT_SaveFile:"
            Error_Record(error+str(e))
            return False
        
if __name__=="__main__" :
    WT=WT()
    if WT.answer.find("YOKOGAWA,WT")==-1 :
        exit(0)
    WT.WT_ItemValue(Item="Urms",Channel="2") 
    # Output_Channel=[4]
    # WT.WT_Integrate(Status="reset")
    # WT.WT_HarSet("U"+str(Output_Channel[0]), "1,1")
    # WT.WT_Range(Channel='all',Auto='1',Type="Voltage")
    # WT.WT_Range(Channel='all',Auto='1',Type="Current")
    # WT.WT_Update()
    # WT.SaveUpdate=200
    
    # WT_SaveItem1=["Urms","Irms","P","S","Q","PF","Idc","FreqU"]
    # WT_SaveItem2=["F1","F2","F3"]
    # WT.SavePath=r"D:\ATE\Testdata\\"
    # WT.WT_SaveSetting(Output_Channel, WT_SaveItem1, WT_SaveItem2, 1)
    # time.sleep(0.1)
    # WT.WT_SaveFile(Time=1,Name="4.4.2_Test_1")

总结

类WT的初始化函数,会自动检索查询横河功率计仪器,成功后会print 连接成功字样及ID。类的其它函数则是用来配置仪器、使用仪器。