Skip to content
Extraits de code Groupes Projets
hp4145.py 5,31 ko
Newer Older
  • Learn to ignore specific revisions
  • Nicolas Roisin's avatar
    Nicolas Roisin a validé
    import equipment
    import pyvisa
    import time
    import numpy as np
    
    class HP4145(equipment.Equipment):
        
        """Class to control HP4145 semiconductor analyzer"""
        model="HP4145"
        company="Keysight"
        link="https://www.keysight.com/dk/en/assets/9018-07935/service-manuals/9018-07935.pdf"
        
        def initialize_sweep(self, mode="voltage sweep",number_channel=4,smu_bias={"SMU2":0,"SMU3":0,"SMU4":0},
                      smu_compliance={"SMU1":1e-6,"SMU2":1e-6,"SMU3":1e-6,"SMU4":1e-6},sweep_param={"start":0,"stop":0,"step":0},
                      integration_mode="IT1",delay_time=0,hold_time=0):
            
            
            """
            mode:
                - "voltage sweep": voltage sweep with SMU1 and current measurements on all the SMUs
            """
            self.mode=mode
            self.number_channel=number_channel
            self.sweep_param=sweep_param
            self.smu_compliance=smu_compliance
            self.smu_bias=smu_bias
            self.integration_mode=integration_mode
            self.delay_time=delay_time
            self.hold_time=hold_time
            
            self.set_connection_parameter_dic({"timeout":10e3,"write_termination":'\r\n',"read_termination":'\r\n',"send_end":True})
        
            try:
                self.pyvisa_resource.write("BC") # clear all buffer.
                self.pyvisa_resource.write("DR1") # This command enables or disables service request for data ready when communications is set to GPIB.
                self.pyvisa_resource.write("EC 1") # This command sets the condition to exit the test if compliance is reached.
                
                if mode =="voltage sweep":
                    
                    self.length_data=int(abs((sweep_param["stop"]-sweep_param["start"])/sweep_param["step"]))
                    self.pyvisa_resource.write("DE") # DE: Accesses SMU channel definition page.
    
                    self.pyvisa_resource.write("CH1, 'V1', 'I1', 1, 1") # 1/2/3: voltage/current/Common 1/2/3: VAR1/VAR2/constant
                    
                    for i in range(number_channel-1):
                        self.pyvisa_resource.write("CH%d, 'V%d', 'I%d', 1, 3"%(i+2,i+2,i+2)) 
    
                    self.pyvisa_resource.write("SS")# Accesses source setup page
                    self.pyvisa_resource.write("VR1, %s, %s, %s, %s"%(sweep_param["start"],sweep_param["stop"],sweep_param["step"],sweep_param["compliance"])) # VR1 for linear sweep of VAR1 source function, vmin, vmax,vstep, compliance
                    self.pyvisa_resource.write("VC2, %.2f, %s"%(smu_bias[0],smu_compliance[0]))
                    self.pyvisa_resource.write("VC3, %.2f, %s"%(smu_bias[1],smu_compliance[1]))
                    self.pyvisa_resource.write("VC4, %.2f, %s"%(smu_bias[2],smu_compliance[2]))
                
                    self.pyvisa_resource.write("HT %f"%hold_time) # Sets a hold time that delays the start of a sweep
                    self.pyvisa_resource.write("DT %f"%delay_time) # delay time: Sets the time to wait between when the output voltage is set and when the measurement is made in a sweep.
                    self.pyvisa_resource.write(integration_mode) # integration time, IT1/IT2/IT3 : short/medium/long
        
                    self.pyvisa_resource.write("SM")
                    self.pyvisa_resource.write("DM2")
                    self.pyvisa_resource.write("LI 'I1','I2','I3','I4'")
                # self.pyvisa_resource.write("DM1")
                # self.pyvisa_resource.write("XN 'V1', 1, %.1f, %.1f"%(v_sweep_param["start"],v_sweep_param["stop"]))
                # self.pyvisa_resource.write("YA 'I1',2, 1E-15, 1E-12")
            except pyvisa.VisaIOError:
                print("/!\ VisaIOError : timeout expired")
                self.pyvisa_resource.close()
            
            return {"mode":mode, "number_channels":number_channel, "sweep_param":sweep_param}
        
        def launch_measurements(self):
            
            N_v=self.length_data
            data={}
            
            if self.integration_mode=="IT1":
                Nmax=50
            elif self.integration_mode=="IT2":
                Nmax=30
            elif self.integration_mode=="IT3":
                Nmax=10
                
                
            if self.mode=="voltage sweep":
                
                v_list=np.round(np.arange(self.sweep_param["start"],self.sweep_param["stop"]+self.sweep_param["step"],self.sweep_param["step"]),6)
    
                data=np.zeros((N_v,self.number_channel))
                data[:,0]=v_list
                
                iteration=int(N_v/Nmax)+1
                index=0
                j=0
                while iteration>0:
                    v_start=v_list[index]
                    if index+Nmax>N_v:
                        v_end=v_list[-1]
                    else:
                        v_end=v_list[index+Nmax-1]
                        
                    self.pyvisa_resource.write("MD") # This command controls measurements.
                    self.pyvisa_resource.write("ME1") # Run a single trigger test and store readings in a cleared buffer: 1
                    time.sleep(10)
    
                    N=int(abs((v_end-v_start)/self.sweep_param["step"]))+1
                    
                    for i in range(self.number_channel):
                        data_list=self.pyvisa_resource.query("DO 'I%d'"%(i+1))# Read measurements
                        for  data_i in data_list.split(","):
                            data[j,i+1]=float(data_i[1:])
                            if i==0:
                                j+=1
                                
                    index+=Nmax
                    iteration-=1  
                    j+=1
                
            return data