class Measurement(MeasurementBase): params = { 'Vgs': Sweep([0.]), 'Vchucks': Sweep([0.]), 'Rg': 100e3, 'stabilise_time': 5., 'stab_chuck_time': 5., 'comment': String(''), 'data_dir': Folder(r'D:\MeasurementJANIS\Holger\test'), 'use_vna': Boolean( True ), # when switched off, this script is basically just a leak test 'init_bilt': Boolean( False ), # when switched on, the Bilt sources will be initialised, this might be dangerous for the sample } observables = ['Vg', 'Vchuck', 'Vgm', 'Ileak'] alarms = [['np.abs(Ileak) > 1e-8', MeasurementBase.ALARM_CALLCOPS]] def measure(self, data_dir, Vgs, Vchucks, Rg, comment, stabilise_time, stab_chuck_time, use_vna, init_bilt, **kwargs): print("===================================") print("Starting acquisition script...") chuck_string = '' vna_string = '' # initialise instruments print("Setting up DC sources and voltmeters...") bilt = Bilt('TCPIP0::192.168.0.2::5025::SOCKET') if init_bilt: # source (bilt, channel, range, filter, slope in V/ms, label): self.sourceVg = sourceVg = BiltVoltageSource( bilt, "I1", "12", "1", 0.005, "Vg") else: self.sourceVg = sourceVg = BiltVoltageSource(bilt, "I1", initialise=False) # voltmeter (bilt, channel, filt, label=None) self.meterVg = meterVg = BiltVoltMeter(bilt, "I5;C1", "2", "Vgm") print("DC sources and voltmeters are set up.") print("Setting up Yokogawa for chuck voltage...") # connect to the Yoko without initialising, this will lead to # an exception if the Yoko is not properly configured (voltage # source, range 30V, output ON) self.yoko = yoko = Yoko7651('GPIB::3::INSTR', initialise=False, rang=30, slope=1.) print("Yokogawa is set up.") if use_vna: print("Setting up VNA...") vna = AnritsuVNA('GPIB::6::INSTR') sweeptime = vna.get_sweep_time() if vna.get_sweep_type() != 'FSEGM': raise Exception('Please use segmented frequency sweep') # check if the RF power is the same on both ports and for all # frequency segments count = int(vna.query(':SENS:FSEGM:COUN?')) vna_pow = None for i in range(1, count + 1): port1pow = float( vna.query(':SENS:FSEGM{}:POW:PORT1?'.format(i))) port2pow = float( vna.query(':SENS:FSEGM{}:POW:PORT2?'.format(i))) if vna_pow is None and port1pow == port2pow: vna_pow = port1pow elif vna_pow is not None and port1pow == port2pow and port1pow == vna_pow: continue else: raise Exception( "Please select the same power for all ports and frequency segments" ) port1att = vna.get_source_att(1) port2att = vna.get_source_att(2) if port1att == port2att: vna_pow -= port1att else: raise Exception( "Please select the same attenuators for both ports") vna_string = '_pwr={:.0f}'.format(vna_pow) print("VNA is set up.") # prepare saving DC data timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') filename = timestamp + vna_string + ('_' + comment if comment else '') self.prepare_saving(os.path.join(data_dir, filename + '.txt')) if use_vna: # prepare saving RF data spectra_fol = os.path.join(data_dir, filename) create_path(spectra_fol) # save segmented frequency sweep data to file with open(os.path.join(spectra_fol, 'VNAconfig'), 'w') as f: vna.dump_freq_segments(f) for Vchuck in Vchucks: print("Setting Vchuck = {}".format(Vchuck)) # set Vchuck yoko.set_voltage(Vchuck) # wait time.sleep(stab_chuck_time) for Vg in Vgs: if self.flags['quit_requested']: print("Stopping acquisition.") return locals() print("Setting Vg = {}".format(Vg)) # set Vg sourceVg.set_voltage(Vg) # wait time.sleep(stabilise_time) # read voltages Vgm = meterVg.get_voltage() # do calculations Ileak = (Vg - Vgm) / Rg # save DC data self.save_row(locals()) if use_vna: # save VNA data print("Getting VNA spectra...") vna.single_sweep(wait=False) # display sweep progress progressbar_wait(sweeptime) # make sure sweep is really done while not vna.is_sweep_done(): time.sleep(0.5) table = vna.get_table([1, 2, 3, 4]) timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp + '_Vg={:.3f}_Vchuck={:.1f}.txt'.format( Vg, Vchuck) np.savetxt(os.path.join(spectra_fol, spectrum_file), np.transpose(table)) print("Acquisition done.") return locals() def tidy_up(self): self.end_saving() print("Driving all voltages back to zero...") self.sourceVg.set_voltage(0.) self.yoko.set_voltage(0.)
class Measurement(MeasurementBase): params = { 'Vgs': Sweep([0.]), 'stabilise_time': 0.3, 'init': Boolean(True), 'use_vna': Boolean(True), 'comment': String(''), 'data_dir': Folder(r'D:\MeasurementJANIS\Holger\test') } observables = ['Vg', 'Ileak'] alarms = [ ['np.abs(Ileak) > 1e-8', MeasurementBase.ALARM_CALLCOPS] # is applied between the two gates ] def measure(self, Vgs, stabilise_time, init, use_vna, data_dir, comment, **kwargs): print("===================================") print("Starting acquisition script...") vna_string = '' # initialise instruments try: print("----------------------------------------") print("Setting up Keithley DC sources...") self.sourceVg = sourceVg = K2400('GPIB::24::INSTR', sourcemode='v', vrang=200, irang=10e-6, slope=1, initialise=init) print("DC sources are set up.") except: print("There has been an error setting up DC sources.") raise if use_vna: print("Setting up VNA...") vna = AnritsuVNA('GPIB::6::INSTR') sweeptime = vna.get_sweep_time() if vna.get_sweep_type() != 'FSEGM': raise Exception('Please use segmented frequency sweep') # check if the RF power is the same on both ports and for all # frequency segments count = int(vna.query(':SENS:FSEGM:COUN?')) vna_pow = None for i in range(1,count+1): port1pow = float(vna.query(':SENS:FSEGM{}:POW:PORT1?'.format(i))) port2pow = float(vna.query(':SENS:FSEGM{}:POW:PORT2?'.format(i))) if vna_pow is None and port1pow == port2pow: vna_pow = port1pow elif vna_pow is not None and port1pow == port2pow and port1pow == vna_pow: continue else: raise Exception("Please select the same power for all ports and frequency segments") port1att = vna.get_source_att(1) port2att = vna.get_source_att(2) if port1att == port2att: vna_pow -= port1att else: raise Exception("Please select the same attenuators for both ports") vna_string = '_pwr={:.0f}'.format(vna_pow) print("VNA is set up.") # define name timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') filename = timestamp + vna_string + ('_'+comment if comment else '') # prepare saving RF data spectra_fol = os.path.join(data_dir, filename) create_path(spectra_fol) # prepare saving DC data self.prepare_saving(os.path.join(data_dir, filename + '.txt')) if use_vna: # prepare saving RF data spectra_fol = os.path.join(data_dir, filename) create_path(spectra_fol) # save segmented frequency sweep data to file with open(os.path.join(spectra_fol, 'VNAconfig'), 'w') as f: vna.dump_freq_segments(f) # loop for Vg in Vgs: if self.flags['quit_requested']: return locals() print('Setting Vg='+str(Vg)+' V...') sourceVg.set_voltage(Vg) time.sleep(stabilise_time) # measure Vgm = sourceVg.get_voltage() Ileak = sourceVg.get_current() # save data self.save_row(locals()) # save VNA data if use_vna: # save VNA data print("Getting VNA spectra...") vna.single_sweep(wait=False) # display sweep progress progressbar_wait(sweeptime) # make sure sweep is really done while not vna.is_sweep_done(): time.sleep(0.5) table = vna.get_table([1,2,3,4]) timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp+'_Vg={:.3f}.txt'.format(Vg) np.savetxt(os.path.join(spectra_fol, spectrum_file), np.transpose(table)) print("Acquisition done.") return locals() def tidy_up(self): self.end_saving() print("Driving all voltages back to zero...") self.sourceVg.set_voltage(0.)
class Measurement(MeasurementBase): params = { 'Vgs': Sweep([0.]), 'Rg': 100e3, 'stabilise_time': 0.3, 'comment': String(''), 'data_dir': Folder(r'D:\MeasurementJANIS\Holger\test'), 'use_vna': Boolean(True), 'use_chuck': Boolean( True ), # we are not controlling the chuck here, just recording the value of the chuck voltage 'init_bilt': Boolean(False) } observables = ['Vg', 'Vgm', 'Ileak'] alarms = [['np.abs(Ileak) > 1e-8', MeasurementBase.ALARM_CALLCOPS]] def measure(self, data_dir, Vgs, Rg, comment, stabilise_time, use_vna, use_chuck, init_bilt, **kwargs): print("===================================") print("Starting acquisition script...") chuck_string = '' vna_string = '' # initialise instruments print("Setting up DC sources and voltmeters...") bilt = Bilt('TCPIP0::192.168.0.2::5025::SOCKET') if init_bilt: # source (bilt, channel, range, filter, slope in V/ms, label): self.sourceVg = sourceVg = BiltVoltageSource( bilt, "I1", "12", "1", 0.005, "Vg") else: self.sourceVg = sourceVg = BiltVoltageSource(bilt, "I1", initialise=False) # voltmeter (bilt, channel, filt, label=None) self.meterVg = meterVg = BiltVoltMeter(bilt, "I5;C1", "2", "Vgm") print("DC sources and voltmeters are set up.") if use_chuck: print("Setting up Yokogawa for chuck voltage...") # connect to the Yoko without initialising, this will lead to # an exception if the Yoko is not properly configured (voltage # source, range 30V, output ON) yoko = Yoko7651('GPIB::3::INSTR', initialise=False, rang=30) chuck_string = '_Vchuck={:.1f}'.format(yoko.get_voltage()) print("Yokogawa is set up.") if use_vna: print("Setting up VNA") self.vna = vna = RohdeSchwarzVNA() vna.open('GPIB', '20') c1 = vna.channel(1) sweeptime = c1.total_sweep_time_ms c1.manual_sweep = True c1.s_parameter_group = c1.to_logical_ports((1, 2)) # cf: https://www.rohde-schwarz.com/webhelp/webhelp_zva/program_examples/basic_tasks/typical_stages_of_a_remote_control_program.htm#Command_Synchronization vna.write("*SRE 32") vna.write("*ESE 1") if not c1.sweep_type == 'SEGM': # need to use not == because != is not implemented in Rohde Schwarz library raise Exception('Please use segmented frequency sweep') # check if the RF power is the same on both ports and for all # frequency segments count = int(vna.query(':SENS:SEGM:COUN?').strip()) vna_pow = None for i in range(1, count + 1): seg_pow = float(vna.query(':SENS:SEGM{}:POW?'.format(i))) if vna_pow is None: vna_pow = seg_pow elif vna_pow is not None and seg_pow == vna_pow: continue else: raise Exception( "Please select the same power for all ports and frequency segments" ) port1autoatt = int(vna.query(':SOUR:POW1:ATT:AUTO?').strip()) port2autoatt = int(vna.query(':SOUR:POW2:ATT:AUTO?').strip()) if port1autoatt or port2autoatt: raise Exception("Please do not use automatic attenuators") port1att = float(vna.query(':SOUR:POW1:ATT?').strip()) port2att = float(vna.query(':SOUR:POW2:ATT?').strip()) if port1att == port2att: vna_pow -= port1att else: raise Exception( "Please select the same attenuators for both ports") vna_string = '_pwr={:.0f}'.format(vna_pow) print("VNA is set up.") # prepare saving DC data timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') filename = timestamp + vna_string + chuck_string + ('_' + comment if comment else '') self.prepare_saving(os.path.join(data_dir, filename + '.txt')) if use_vna: # prepare saving RF data spectra_fol = os.path.join(data_dir, filename) create_path(spectra_fol) with open(os.path.join(spectra_fol, 'VNAconfig'), 'w') as f: f.write( '# Frequency based segmented sweep setup of Rohde&Schwarz ZVA 67\n' ) f.write('# Attenuator Port 1: {}\n'.format(port1att)) f.write('# Attenuator Port 2: {}\n'.format(port2att)) f.write('# Seg no.\tfstart\tfstop\tpoints\tbwidth\tpow\n') count = int(vna.query(':SENS:SEGM:COUN?').strip()) for i in range(1, count + 1): seg_pow = float( vna.query(':SENS:SEGM{}:POW?'.format(i)).strip()) bwidth = float( vna.query(':SENS:SEGM{}:BWID?'.format(i)).strip()) fstart = float( vna.query(':SENS:SEGM{}:FREQ:STAR?'.format(i)).strip()) fstop = float( vna.query(':SENS:SEGM{}:FREQ:STOP?'.format(i)).strip()) points = int( vna.query(':SENS:SEGM{}:SWE:POIN?'.format(i)).strip()) f.write('{:d}\t{:f}\t{:f}\t{:d}\t{:f}\t{:f}\n'.format( i, fstart, fstop, points, bwidth, seg_pow)) for Vg in Vgs: if self.flags['quit_requested']: print("Stopping acquisition.") return locals() print("Setting Vg = {}".format(Vg)) # set Vg sourceVg.set_voltage(Vg) # wait time.sleep(stabilise_time) # read voltages Vgm = meterVg.get_voltage() # do calculations Ileak = (Vg - Vgm) / Rg # save DC data self.save_row(locals()) if use_vna: # save VNA data print("Getting VNA spectra...") vna.write("INIT1:IMM; *OPC") # display sweep progress progressbar_wait(sweeptime / 1e3) # make sure sweep is really done while not int(vna.query("*ESR?").strip()): time.sleep(0.5) timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp + '_Vg=%2.4f' % (Vg) #vna.channel(1).save_measurement_locally(os.path.join(spectra_fol, spectrum_file), (1,2)) spectrum_file = os.path.join(spectra_fol, spectrum_file + '.s2p') unique_filename = unique_alphanumeric_string() + '.s2p' scpi = ":MMEM:STOR:TRAC:PORT {0},'{1}',{2},{3}" scpi = scpi.format(1, \ unique_filename, \ 'COMP', \ '1,2') vna.write(scpi) # this saves the file on the ZVA in the folder # C:\Rohde&Schwarz\Nwa\ vna.pause(5000) vna.file.download_file(unique_filename, spectrum_file) vna.file.delete(unique_filename) print("Acquisition done.") return locals() def tidy_up(self): self.vna.close() self.end_saving() print("Driving all voltages back to zero...") self.sourceVg.set_voltage(0.)
class Measurement(MeasurementBase): params = { 'Vgs': Sweep([0.]), 'Rg': 100e3, 'stabilise_time': 0.3, 'comment': String(''), 'data_dir': Folder(r'D:\MeasurementJANIS\Holger\test'), 'use_vna': Boolean(True), 'use_chuck': Boolean( True ), # we are not controlling the chuck here, just recording the value of the chuck voltage 'init_bilt': Boolean(False) } observables = ['Vg', 'Vgm', 'Ileak'] alarms = [['np.abs(Ileak) > 1e-8', MeasurementBase.ALARM_CALLCOPS]] def measure(self, data_dir, Vgs, Rg, comment, stabilise_time, use_vna, use_chuck, init_bilt, **kwargs): print("===================================") print("Starting acquisition script...") chuck_string = '' vna_string = '' # initialise instruments print("Setting up DC sources and voltmeters...") bilt = Bilt('TCPIP0::192.168.0.5::5025::SOCKET') if init_bilt: # source (bilt, channel, range, filter, slope in V/ms, label): self.sourceVg = sourceVg = BiltVoltageSource( bilt, "I3;C1", "12", "1", 0.005, "Vg") else: self.sourceVg = sourceVg = BiltVoltageSource(bilt, "I3;C1", initialise=False) # voltmeter (bilt, channel, filt, label=None) self.meterVg = meterVg = BiltVoltMeter(bilt, "I1;C1", "2", "Vgm") print("DC sources and voltmeters are set up.") if use_chuck: print("Setting up Yokogawa for chuck voltage...") # connect to the Yoko without initialising, this will lead to # an exception if the Yoko is not properly configured (voltage # source, range 30V, output ON) yoko = Yoko7651('GPIB::10::INSTR', initialise=False, rang=30) chuck_string = '_Vchuck={:.1f}'.format(yoko.get_voltage()) print("Yokogawa is set up.") if use_vna: print("Setting up VNA") self.vna = vna = RohdeSchwarzVNA() vna.open('TCPIP', '192.168.0.3') c1 = vna.channel(1) sweeptime = c1.total_sweep_time_ms c1.init_nonblocking_sweep((1, 2)) if not c1.is_corrected(): raise Exception('Please calibrate or switch on correction.') if c1.sweep_type != 'SEGM': raise Exception('Please use segmented frequency sweep') # check if the RF power is the same on both ports and for all # frequency segments vna_pow = np.unique(np.asarray(c1.get_frequency_segments())[:, 5]) if len(vna_pow) > 1: raise Exception( "Please select the same power for all ports and frequency segments" ) vna_pow = vna_pow[0] if c1.is_auto_attenuator(1) or c1.is_auto_attenuator(2): raise Exception("Please do not use automatic attenuators") port1att = c1.get_attenuator(1) if port1att == c1.get_attenuator(2): vna_pow -= port1att else: raise Exception( "Please select the same attenuators for both ports") vna_string = '_pwr={:.0f}'.format(vna_pow) print("VNA is set up.") # prepare saving DC data timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') filename = timestamp + vna_string + chuck_string + ('_' + comment if comment else '') self.prepare_saving(os.path.join(data_dir, filename + '.txt')) if use_vna: # prepare saving RF data spectra_fol = os.path.join(data_dir, filename) create_path(spectra_fol) c1.save_frequency_segments(os.path.join(spectra_fol, 'VNAconfig')) for Vg in Vgs: if self.flags['quit_requested']: print("Stopping acquisition.") return locals() print("Setting Vg = {}".format(Vg)) # set Vg sourceVg.set_voltage(Vg) # wait time.sleep(stabilise_time) # read voltages Vgm = meterVg.get_voltage() # do calculations Ileak = (Vg - Vgm) / Rg # save DC data self.save_row(locals()) if use_vna: # save VNA data print("Getting VNA spectra...") c1.start_nonblocking_sweep() # display sweep progress progressbar_wait(sweeptime / 1e3) # make sure sweep is really done while not c1.isdone_nonblocking_sweep(): time.sleep(0.5) timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp + '_Vg=%2.4f' % (Vg) spectrum_file = os.path.join(spectra_fol, spectrum_file + '.s2p') c1.save_nonblocking_sweep(spectrum_file, (1, 2)) print("Acquisition done.") return locals() def tidy_up(self): self.vna.close() self.end_saving() print("Driving all voltages back to zero...") self.sourceVg.set_voltage(0.)
class Measurement(MeasurementBase): params = { 'src_Vds': Select(['Bilt_1', 'Bilt_2', 'Bilt_3', 'Bilt_4', 'K2400', 'K2600']), 'Vdss': Sweep([0.0]), 'Rds_Bilt_Only': 9.86e3, 'src_Vg': Select(['Bilt_3', 'Bilt_4', 'Bilt_1', 'Bilt_2', 'K2400', 'K2600']), 'Vgs': Sweep([0.0]), 'Rg_Bilt_Only': 29.9e3, 'src_Vchuck': Select(['None', 'Yoko', 'K2400', 'K2600']), 'Vchucks': Sweep([0.0]), #'use_vna' : Boolean(True), 'src_vna': Select(['None', 'zva67', 'anritsu']), 'sweep_type': Select([ 'initialise_instruments', 'give_time', 'fix_Vg_sweep_Vds', 'fix_Vds_sweep_Vg' ]), 'mesurement_station': Select(['None', 'JANIS', 'Cascade']), 'comment': String(''), 'data_dir': Folder(r''), 'WxL': 100, #um² 'max_pwr': 2e-3, 'max_Ileak': 1e-7, 'stabilise_time': 1, 'slope_vg_vd': 0.005, 'slope_vchuck': 1 } observables = [ 'Vg', 'Vgm', 'Ileak', 'Vds', 'Vdsm', 'Ids', 'Rs', 'pwr', 'Ta', 'Tb', 'Vchuck', 'sweeptime_min', 'remain_time_min', 'progress_percent' ] alarms = [ ['np.abs(Ileak) > max_Ileak', MeasurementBase.ALARM_CALLCOPS], ['pwr > max_pwr', MeasurementBase.ALARM_CALLCOPS], ] def measure(self, sweep_type, src_Vg, src_Vds, src_Vchuck, src_vna, data_dir, comment, mesurement_station, Vdss, Vgs, Vchucks, Rg_Bilt_Only, Rds_Bilt_Only, WxL, max_pwr, max_Ileak, stabilise_time, slope_vg_vd, slope_vchuck, **kwargs): print("****************************************") print("===================================") print("Starting acquisition script") self.sourceVchuck = None vna_string = '' temp_string = '' if (mesurement_station == 'None'): print("Please chose a mesurement station first") raise #initialise instruments if (sweep_type == 'initialise_instruments'): init_instruments = True else: init_instruments = False # #select correct vna # if (use_vna == 'True' and mesurement_station == 'JANIS'): # src_vna = 'anritsu' # elif (use_vna == 'True' and mesurement_station == 'Cascade'): # src_vna = 'zva67' # else: # src_vna = 'None' #------------------------------------------------------------------------# #------------------------------------------------------------------------# #set instruments if (mesurement_station == 'JANIS'): yoko_address = 'GPIB::3::INSTR' k2000_address = 'GPIB::20::INSTR' bilt_address = 'TCPIP0::192.168.0.2::5025::SOCKET' anritsu_address = 'GPIB::6::INSTR' temperature_address = 'GPIB::14::INSTR' position_source_bilt = "I" position_meter_bilt = "I5;C" if (mesurement_station == 'Cascade'): yoko_address = 'GPIB::10::INSTR' k2000_address = 'GPIB::15::INSTR' bilt_address = 'TCPIP0::192.168.0.5::5025::SOCKET' zva67_address = '192.168.0.3' temperature_address = 'ASRL5::INSTR' position_source_bilt = "I3;C" position_meter_bilt = "I1;C" k2400_address = 'GPIB::24::INSTR' k2600_address = 'GPIB::24::INSTR' #------------------------------------------------------------------------# #------------------------------------------------------------------------# # initialise SI9700 temperature controler if (mesurement_station == 'JANIS'): try: print("----------------------------------------") print("Setting up SI9700 temperature controller...") tc = SI9700(temperature_address) temp_string = '_T={:.1f}'.format( (tc.get_temp('a') + tc.get_temp('b')) / 2) print("Temperature controller SI9700 is set up.") except: print( "There has been an error setting up the SI9700 temperature controller." ) raise elif (mesurement_station == 'Cascade'): try: print("----------------------------------------") print("Setting up TIC500 temperature controller...") tc = TIC500(temperature_address) temp_string = '_T={:.1f}'.format(tc.get_temp('Chuck')) print("Temperature controller TIC500 is set up.") except: print( "There has been an error setting up the TIC500 temperature controller." ) raise # initialise K2400 if (src_Vg == 'K2400' or src_Vds == 'K2400' or src_Vchuck == 'K2400'): try: print("----------------------------------------") print("Setting up K2400 DC source...") if src_Vg == 'K2400': self.sourceVg = sourceVg = K2400( k2400_address, sourcemode='v', vrang=200, irang=100e-3, slope=slope_vg_vd, initialise=init_instruments) if src_Vds == 'K2400': self.sourceVds = sourceVds = K2400( k2400_address, sourcemode='v', vrang=200, irang=100e-3, slope=slope_vg_vd, initialise=init_instruments) if src_Vchuck == 'K2400': self.sourceVchuck = sourceVchuck = K2400( k2400_address, sourcemode='v', vrang=200, irang=100e-3, slope=slope_vchuck, initialise=init_instruments) print("K2400 DC source are set up.") except: print("There has been an error setting up K2400 DC sources.") raise # initialise K2600 if (src_Vg == 'K2600' or src_Vds == 'K2600' or src_Vchuck == 'K2600'): try: print("----------------------------------------") print("Setting up K2600 DC source...") if src_Vg == 'K2600': self.sourceVg = sourceVg = K2600( k2600_address, slope=slope_vg_vd, initialise=init_instruments) if src_Vds == 'K2600': self.sourceVds = sourceVds = K2600( k2600_address, slope=slope_vg_vd, initialise=init_instruments) if src_Vchuck == 'K2600': self.sourceVchuck = sourceVchuck = K2600( k2600_address, slope=slope_vchuck, initialise=init_instruments) print("K2600 DC source are set up.") except: print("There has been an error setting up K2600 DC sources.") raise # initialise YOKO if (src_Vchuck == 'Yoko'): try: print("----------------------------------------") print("Setting up Yokogawa DC source...") self.sourceVchuck = sourceVchuck = Yoko7651( yoko_address, initialise=init_instruments, rang=30, slope=slope_vchuck) print("Yokogawa DC source are set up.") except: print("There has been an error setting up the chuck voltage.") raise # initialise BILT if (src_Vg[0:4] == 'Bilt' or src_Vds[0:4] == 'Bilt'): try: print("----------------------------------------") print("Setting up BILT DC sources and voltmeters...") bilt = Bilt(bilt_address) if (src_Vg[0:4] == 'Bilt'): src_Vg, port_Vg = src_Vg.split('_') self.sourceVg = sourceVg = BiltVoltageSource( bilt, position_source_bilt + port_Vg, rang="12", filt="1", slope=slope_vg_vd, label=None, initialise=init_instruments) self.meterVg = meterVg = BiltVoltMeter( bilt, position_meter_bilt + port_Vg, filt="2", label="Vgm") if (src_Vds[0:4] == 'Bilt'): src_Vds, port_Vds = src_Vds.split('_') self.sourceVds = sourceVds = BiltVoltageSource( bilt, position_source_bilt + port_Vds, rang="12", filt="1", slope=slope_vg_vd, label=None, initialise=init_instruments) self.meterVds = meterVds = BiltVoltMeter( bilt, position_meter_bilt + port_Vds, filt="2", label="Vdsm") print("BILT DC sources and voltmeters are set up.") except: print( "There has been an error setting up BILT DC sources and voltmeters." ) raise # initialise VNA ZVA67 if src_vna == 'zva67': print("Setting up VNA") self.vna = vna = RohdeSchwarzVNA() vna.open('TCPIP', '192.168.0.3') c1 = vna.channel(1) sweeptime = c1.total_sweep_time_ms c1.init_nonblocking_sweep((1, 2)) if not c1.is_corrected(): raise Exception('Please calibrate or switch on correction.') if c1.sweep_type != 'SEGM': raise Exception('Please use segmented frequency sweep') # check if the RF power is the same on both ports and for all # frequency segments vna_pow = np.unique(np.asarray(c1.get_frequency_segments())[:, 5]) if len(vna_pow) > 1: raise Exception( "Please select the same power for all ports and frequency segments" ) vna_pow = vna_pow[0] if c1.is_auto_attenuator(1) or c1.is_auto_attenuator(2): raise Exception("Please do not use automatic attenuators") port1att = c1.get_attenuator(1) if port1att == c1.get_attenuator(2): vna_pow -= port1att else: raise Exception( "Please select the same attenuators for both ports") vna_string = '_pwr={:.0f}'.format(vna_pow) print("VNA is set up.") # initialise VNA ANRITSU if (src_vna == 'anritsu'): try: print("----------------------------------------") print("Setting up ANRITSU VNA") vna = AnritsuVNA(anritsu_address) sweeptime = vna.get_sweep_time() if vna.get_sweep_type() != 'FSEGM': raise Exception('Please use segmented frequency sweep') # check if the RF power is the same on both ports and for all # frequency segments count = int(vna.query(':SENS:FSEGM:COUN?')) vna_pow = None for i in range(1, count + 1): port1pow = float( vna.query(':SENS:FSEGM{}:POW:PORT1?'.format(i))) port2pow = float( vna.query(':SENS:FSEGM{}:POW:PORT2?'.format(i))) if vna_pow is None and port1pow == port2pow: vna_pow = port1pow elif vna_pow is not None and port1pow == port2pow and port1pow == vna_pow: continue else: raise Exception( "Please select the same power for all ports and frequency segments" ) port1att = vna.get_source_att(1) port2att = vna.get_source_att(2) if port1att == port2att: vna_pow -= port1att else: raise Exception( "Please select the same attenuators for both ports") vna_string = '_pwr={:.0f}'.format(vna_pow) print("ANRITSU VNA is set up.") except: print("There has been an error setting up the ANRITSU VNA.") raise print("----------------------------------------") #------------------------------------------------------------------------# #------------------------------------------------------------------------# # define name timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') filename = timestamp + vna_string + temp_string + ('_' + comment if comment else '') # prepare saving DC data self.prepare_saving(os.path.join(data_dir, filename + '.txt')) # prepare saving RF data if src_vna != 'None': spectra_fol = os.path.join(data_dir, filename) create_path(spectra_fol) # save config if src_vna == 'zva67': # prepare saving RF data spectra_fol = os.path.join(data_dir, filename) create_path(spectra_fol) c1.save_frequency_segments(os.path.join(spectra_fol, 'VNAconfig')) sweeptime_min = len(Vgs) * len(Vdss) * len( Vchucks) * stabilise_time * (c1.total_sweep_time_ms * 1e3 if src_vna == 'zva67' else 1) / 60 remain_time_min = sweeptime_min progress_percent = 0 if (sweep_type == 'give_time' or sweep_type == 'initialise_instruments'): # save data self.save_row(locals()) # stop return locals() #------------------------------------------------------------------------# #------------------------------------------------------------------------# # loops print("........................................") print("Starting mesurement") print("++++++++++++++++++++++++++++++++++++++++") for Vchuck in Vchucks: if src_Vchuck != "None": sourceVchuck.set_voltage(Vchuck) if (sweep_type == 'fix_Vds_sweep_Vg'): for Vds in Vdss: sourceVds.set_voltage(Vds) for Vg in Vgs: sourceVg.set_voltage(Vg) # quit request if self.flags['quit_requested']: return locals() # stabilise time.sleep(stabilise_time) # measure & calculate if (src_Vds == 'K2400' or src_Vds == 'K2600'): #mesure current directly Ids = sourceVds.get_current() if (src_Vds[0:4] == 'Bilt'): #mesure current and convert in tension with resistor Vdsm = meterVds.get_voltage() Rs = Rds_Bilt_Only * Vdsm / (Vds - Vdsm) Ids = Vds / Rs if (src_Vg == 'K2400' or src_Vg == 'K2600'): #mesure current directly Ileak = sourceVg.get_current() if (src_Vg[0:4] == 'Bilt'): #mesure current and convert in tension with resistor Vgm = meterVg.get_voltage() Ileak = (Vg - Vgm) / Rg_Bilt_Only pwr = (Vds * Ids) / (WxL) # get temp if (mesurement_station == 'JANIS'): Ta = tc.get_temp('a') Tb = tc.get_temp('b') elif (mesurement_station == 'Cascade'): Ta = tc.get_temp('Chuck') Tb = tc.get_temp('Chuck') # save data self.save_row(locals()) #print print("Getting mesurement Vg = {}".format(Vg) + " and Vds = {}".format(Vds)) # save VNA data if src_vna == 'zva67': # save VNA data print("Getting VNA spectra...") c1.start_nonblocking_sweep() # make sure sweep is really done # display sweep progress progressbar_wait(sweeptime / 1e3) # make sure sweep is really done while not c1.isdone_nonblocking_sweep(): time.sleep(0.5) timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp + '_Vg=%2.4f' % ( Vg) + '_Vds=%2.4f' % (Vds) spectrum_file = os.path.join( spectra_fol, spectrum_file + '.s2p') c1.save_nonblocking_sweep(spectrum_file, (1, 2)) if src_vna == 'Anritsu': vna.single_sweep() table = vna.get_table(range(1, 4)) timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp + '_Vg=%2.4f' % ( Vg) + '_Vds=%2.4f' % (Vds) + '.txt' np.savetxt( os.path.join(spectra_fol, spectrum_file), np.transpose(table)) #mesure time remain_time_min = remain_time_min - ( stabilise_time * (c1.total_sweep_time_ms * 1e3 if src_vna == 'zva67' else 1) / 60) progress_percent = (sweeptime_min - remain_time_min ) / sweeptime_min * 100 if (sweep_type == 'fix_Vg_sweep_Vds'): for Vg in Vgs: sourceVg.set_voltage(Vg) first_pass = True for Vds in Vdss: #check power limit if first_pass: pwr = 0 else: pwr = (Vds * Ids) / (WxL) if (pwr > max_pwr): pwr_limit = True elif (pwr < max_pwr): pwr_limit = False if not pwr_limit: sourceVds.set_voltage(Vds) #quit request if self.flags['quit_requested']: return locals() # stabilise time.sleep(stabilise_time) # measure & calculate if (src_Vds == 'K2400' or src_Vds == 'K2600'): #mesure current directly Ids = sourceVds.get_current() if (src_Vds[0:4] == 'Bilt'): #mesure current and convert in tension with resistor Vdsm = meterVds.get_voltage() Rs = Rds_Bilt_Only * Vdsm / (Vds - Vdsm) Ids = Vds / Rs if (src_Vg == 'K2400' or src_Vg == 'K2600'): #mesure current directly Ileak = sourceVg.get_current() if (src_Vg[0:4] == 'Bilt'): #mesure current and convert in tension with resistor Vgm = meterVg.get_voltage() Ileak = (Vg - Vgm) / Rg_Bilt_Only pwr = (Vds * Ids) / (WxL) # get temp if (mesurement_station == 'JANIS'): Ta = tc.get_temp('a') Tb = tc.get_temp('b') elif (mesurement_station == 'Cascade'): Ta = tc.get_temp('Chuck') Tb = tc.get_temp('Chuck') # do calculations Ileak = (Vg - Vgm) / Rg_Bilt_Only # save data self.save_row(locals()) #print print("Getting mesurement Vg = {}".format(Vg) + " and Vds = {}".format(Vds)) # save VNA data if src_vna == 'zva67': # save VNA data print("Getting VNA spectra...") c1.start_nonblocking_sweep() # display sweep progress progressbar_wait(sweeptime / 1e3) # make sure sweep is really done while not c1.isdone_nonblocking_sweep(): time.sleep(0.5) timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp + '_Vg=%2.4f' % ( Vg) + '_Vds=%2.4f' % (Vds) spectrum_file = os.path.join( spectra_fol, spectrum_file + '.s2p') c1.save_nonblocking_sweep(spectrum_file, (1, 2)) if src_vna == 'Anritsu': vna.single_sweep() table = vna.get_table(range(1, 4)) timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp + '_Vg=%2.4f' % ( Vg) + '_Vds=%2.4f' % (Vds) + '.txt' np.savetxt( os.path.join(spectra_fol, spectrum_file), np.transpose(table)) #mesure time remain_time_min = remain_time_min - ( stabilise_time * (c1.total_sweep_time_ms * 1e3 if src_vna == 'zva67' else 1) / 60) progress_percent = (sweeptime_min - remain_time_min ) / sweeptime_min * 100 first_pass = False print("++++++++++++++++++++++++++++++++++++++++") print("Stopping measurement") print("........................................") return locals() def tidy_up(self): self.end_saving() print("Setting all voltages to zero") self.sourceVds.set_voltage(0.) self.sourceVg.set_voltage(0.) if self.sourceVchuck is not None: self.sourceVchuck.set_voltage(0.) print("===================================") print("Ending acquisition script") print("****************************************")
class Measurement(MeasurementBase): params = { 'Vgs': Sweep([0.]), 'stabilise_time': 0.3, 'init': Boolean(True), 'use_vna': Boolean(True), 'comment': String(''), 'data_dir': Folder(r'D:\MeasurementJANIS\David M') } observables = ['Vg', 'Ileak'] alarms = [['np.abs(Ileak) > 1e-8', MeasurementBase.ALARM_CALLCOPS ] # is applied between the two gates ] def measure(self, Vgs, stabilise_time, init, use_vna, data_dir, comment, **kwargs): print("===================================") print("Starting acquisition script...") vna_string = '' # initialise instruments try: print("----------------------------------------") print("Setting up Keithley DC sources...") self.sourceVg = sourceVg = K2400('GPIB::24::INSTR', sourcemode='v', vrang=200, irang=10e-6, slope=1, initialise=init) print("DC sources are set up.") except: print("There has been an error setting up DC sources.") raise if use_vna: try: print("----------------------------------------") print("Setting up VNA") self.vna = vna = RohdeSchwarzVNA() vna.open('TCPIP', '192.168.0.3') c1 = vna.channel(1) #check if we used a segmented sweep c1.manual_sweep = True c1.s_parameter_group = c1.to_logical_ports((1, 2)) vna.write("*SRE 32") vna.write("*ESE 1") if not c1.sweep_type == 'SEGM': raise Exception('Please use segmented frequency sweep') # check if the RF power is the same on both ports and for all frequency segments count = int(vna.query(':SENS:SEGM:COUN?').strip()) vna_pow = None for i in range(1, count + 1): seg_pow = float(vna.query(':SENS:SEGM{}:POW?'.format(i))) if vna_pow is None: vna_pow = seg_pow elif vna_pow is not None and seg_pow == vna_pow: continue else: raise Exception( "Please select the same power for all ports and frequency segments" ) port1autoatt = int(vna.query(':SOUR:POW1:ATT:AUTO?').strip()) port2autoatt = int(vna.query(':SOUR:POW2:ATT:AUTO?').strip()) if port1autoatt or port2autoatt: raise Exception("Please do not use automatic attenuators") port1att = float(vna.query(':SOUR:POW1:ATT?').strip()) port2att = float(vna.query(':SOUR:POW2:ATT?').strip()) if port1att == port2att: vna_pow -= port1att else: raise Exception( "Please select the same attenuators for both ports") vna_string = '_pwr={:.0f}'.format(vna_pow) print("VNA is set up.") except: print("There has been an error setting up the VNA.") raise # define name timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') filename = timestamp + vna_string + ('_' + comment if comment else '') # prepare saving RF data spectra_fol = os.path.join(data_dir, filename) create_path(spectra_fol) # prepare saving DC data self.prepare_saving(os.path.join(data_dir, filename + '.txt')) # save config if use_vna: try: with open(os.path.join(spectra_fol, 'VNAconfig'), 'w') as f: f.write( '# Frequency based segmented sweep setup of Rohde&Schwarz ZVA 67\n' ) f.write('# Attenuator Port 1: {}\n'.format(port1att)) f.write('# Attenuator Port 2: {}\n'.format(port2att)) f.write('# Seg no.\tfstart\tfstop\tpoints\tbwidth\tpow\n') count = int(vna.query(':SENS:SEGM:COUN?').strip()) for i in range(1, count + 1): seg_pow = float( vna.query(':SENS:SEGM{}:POW?'.format(i)).strip()) bwidth = float( vna.query(':SENS:SEGM{}:BWID?'.format(i)).strip()) fstart = float( vna.query( ':SENS:SEGM{}:FREQ:STAR?'.format(i)).strip()) fstop = float( vna.query( ':SENS:SEGM{}:FREQ:STOP?'.format(i)).strip()) points = int( vna.query( ':SENS:SEGM{}:SWE:POIN?'.format(i)).strip()) f.write('{:d}\t{:f}\t{:f}\t{:d}\t{:f}\t{:f}\n'.format( i, fstart, fstop, points, bwidth, seg_pow)) except: print("There has been an error setting up the VNA.") raise # loop for Vg in Vgs: if self.flags['quit_requested']: return locals() print('Setting Vg=' + str(Vg) + ' V...') sourceVg.set_voltage(Vg) time.sleep(stabilise_time) # measure Vgm = sourceVg.get_voltage() Ileak = sourceVg.get_current() # save data self.save_row(locals()) # save VNA data if use_vna: print("Getting VNA spectra...") #save data timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp + '_Vg=%2.4f' % (Vg) c1.save_measurement_locally( os.path.join(spectra_fol, spectrum_file), (1, 2)) print("Acquisition done.") return locals() def tidy_up(self): self.end_saving() print("Driving all voltages back to zero...") self.sourceVg.set_voltage(0.)
class Measurement(MeasurementBase): params = { 'Vg1s': Sweep([0.0]), 'Vg2s': Sweep([0.0]), 'commongate': Boolean(False), 'Rg1': 100e3, 'Rg2': 100e3, 'Rds': 2.2e3, 'stabilise_time': 0.5, 'comment': String(''), 'data_dir': Folder(r'D:\meso\Desktop\testdata') } observables = [ 'Vg1', 'Vg1m', 'Ileak1', 'Vg2', 'Vg2m', 'Ileak2', 'Vds', 'Vdsm', 'Vdsm_std', 'Rs' ] alarms = [ ['np.abs(Ileak1) > 1e-8', MeasurementBase.ALARM_CALLCOPS], ['np.abs(Ileak2) > 1e-8', MeasurementBase.ALARM_CALLCOPS], ['np.abs(Vg1-Vg2)', MeasurementBase.ALARM_SHOWVALUE ] # useful if we just want to know how much voltage # is applied between the two gates ] def measure(self, data_dir, Vg1s, Vg2s, commongate, Rg1, Rg2, Rds, stabilise_time, **kwargs): print("===================================") print("Starting acquisition script...") # initialise instruments try: print("Setting up DC sources and voltmeters...") bilt = Bilt('TCPIP0::192.168.0.2::5025::SOCKET') self.sourceVg1 = sourceVg1 = BiltVoltageSource( bilt, "I2", "12", "1", 0.01, "Vg1") self.sourceVg2 = sourceVg2 = BiltVoltageSource( bilt, "I3", "12", "1", 0.01, "Vg2") self.meterVg1 = meterVg1 = BiltVoltMeter(bilt, "I5;C2", "2", "Vg1m") self.meterVg2 = meterVg2 = BiltVoltMeter(bilt, "I5;C3", "2", "Vg2m") print("DC sources and voltmeters are set up.") except: print( "There has been an error setting up DC sources and voltmeters." ) raise try: print("Setting up lock-in amplifier") self.lockin = lockin = ZILockin() print("Lock in amplifier is set up.") except: print("There has been an error setting up the lock-in amplifier.") raise timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') # save lock in settings (in case we need to check something later) lockin.save_settings( os.path.join(data_dir, 'ZIsettings', timestamp + '.ZIsettings.txt')) # prepare saving data filename = timestamp + '.txt' self.prepare_saving(os.path.join(data_dir, filename)) # loops Vds = lockin.rms_amp for Vg2 in Vg2s: sourceVg2.set_voltage(Vg2) for Vg1 in Vg1s: if self.flags['quit_requested']: return locals() sourceVg1.set_voltage(Vg1) # stabilise time.sleep(stabilise_time) # measure Vg1m = meterVg1.get_voltage() Vg2m = meterVg2.get_voltage() Vdsm, Vdsm_std = lockin.poll_data() # do calculations Ileak1 = (Vg1 - Vg1m) / Rg1 Ileak2 = (Vg2 - Vg2m) / Rg2 Rs = Rds * Vdsm / (Vds - Vdsm) # save data self.save_row(locals()) print("Acquisition done.") return locals() def tidy_up(self): self.end_saving() print("Driving all voltages back to zero...") self.sourceVg1.set_voltage(0.) self.sourceVg2.set_voltage(0.) self.lockin.tidy_up()
class Measurement(MeasurementBase): params = { 'Vgs': Sweep([0.0]), 'Vds': 0.01, 'Rg': 100e3, 'Rds': 2.2e3, 'stabilise_time': 0.3, 'comment': String(''), 'data_dir': Folder(r'D:\meso\Desktop\testdata') } observables = ['Vg', 'Vgm', 'Ileak', 'Vds', 'Vdsm', 'Rs'] alarms = [['np.abs(Ileak) > 1e-8', MeasurementBase.ALARM_CALLCOPS]] def measure(self, data_dir, Vgs, Vds, Rg, Rds, comment, stabilise_time, **kwargs): print("===================================") print("Starting acquisition script...") # initialise instruments try: print("Setting up DC sources and voltmeters...") bilt = Bilt('TCPIP0::192.168.0.2::5025::SOCKET') # source (bilt, channel, range, filter, slope in V/ms, label): self.sourceVg = sourceVg = BiltVoltageSource( bilt, "I2", "12", "1", 0.005, "Vg") self.sourceVds = sourceVds = BiltVoltageSource( bilt, "I3", "1.2", "1", 0.005, "Vds") # voltmeter (bilt, channel, filt, label=None) self.meterVg = meterVg = BiltVoltMeter(bilt, "I5;C2", "2", "Vgm") self.meterVds = meterVds = BiltVoltMeter(bilt, "I5;C3", "2", "Vdsm") print("DC sources and voltmeters are set up.") except: print( "There has been an error setting up DC sources and voltmeters." ) raise try: print("Setting up VNA") vna = AnritsuVNA('GPIB::6::INSTR') self.freqs = vna.get_freq_list() # get frequency list print("VNA is set up.") except: print("There has been an error setting up the VNA.") raise timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') # prepare saving DC data filename = timestamp + ('_' + comment if comment else '') self.prepare_saving(os.path.join(data_dir, filename + '.txt')) # prepare saving RF data spectra_fol = os.path.join(data_dir, filename) try: os.makedirs(spectra_fol) except OSError as e: if e.errno != errno.EEXIST: raise sourceVds.set_voltage(Vds) for Vg in Vgs: if self.flags['quit_requested']: print("Stopping acquisition.") return locals() print("Setting Vg = {}".format(Vg)) # set Vg1 and 2 sourceVg.set_voltage(Vg) # wait time.sleep(stabilise_time) # read voltages Vgm = meterVg.get_voltage() Vdsm = meterVds.get_voltage() # do calculations Ileak = (Vg - Vgm) / Rg Rs = Rds * Vdsm / (Vds - Vdsm) # save DC data self.save_row(locals()) # save VNA data print("Getting VNA spectra...") vna.single_sweep() table = vna.get_table([1, 2, 3, 4]) timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp + '_Vg1_%2.4f' % (Vg) + '_Vds_%2.4f' % ( Vds) + '.txt' np.savetxt(os.path.join(spectra_fol, spectrum_file), np.transpose(table)) print("Acquisition done.") return locals() def tidy_up(self): self.end_saving() print("Driving all voltages back to zero...") self.sourceVg.set_voltage(0.) self.sourceVds.set_voltage(0.)
class Measurement(MeasurementBase): params = { 'Vds': 10e-3, 'Vgs': Sweep([0.]), 'Rg': 100e3, 'stabilise_time': 0.05, 'init': Boolean(True), 'comment': String(''), 'data_dir': Folder('D:\Manip13\Desktop\Holger') } observables = ['Vg', 'Vgm', 'Ileak', 'Vds', 'Vdsm', 'Ids', 'Rds'] alarms = [['np.abs(Ileak) > 1e-8', MeasurementBase.ALARM_CALLCOPS ] # is applied between the two gates ] def measure(self, Vds, Vgs, Rg, stabilise_time, init, data_dir, comment, **kwargs): print("===================================") print("Starting acquisition script...") # initialise instruments try: print("Setting up DC sources...") self.sourceVg = sourceVg = K2400('GPIB::24::INSTR', sourcemode='v', vrang=200, irang=10e-6, slope=1, initialise=init) self.sourceVds = sourceVds = K2600('GPIB::26::INSTR', slope=0.005, initialise=init) print("DC sources and voltmeters are set up.") except: print( "There has been an error setting up DC sources and voltmeters." ) raise timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') # prepare saving data filename = timestamp + '_' + (comment if comment else '') + '.txt' self.prepare_saving(os.path.join(data_dir, filename)) # loop sourceVds.set_voltage(Vds) for Vg in Vgs: if self.flags['quit_requested']: return locals() print('Setting Vg=' + str(Vg) + ' V...') sourceVg.set_voltage(Vg) time.sleep(stabilise_time) # measure Vgm = sourceVg.get_voltage() Ileak = sourceVg.get_current() Vdsm = sourceVds.get_voltage() Ids = sourceVds.get_current() # do calculations Rds = Vds / Ids # save data self.save_row(locals()) print("Acquisition done.") return locals() def tidy_up(self): self.end_saving() print("Driving all voltages back to zero...") self.sourceVds.set_voltage(0.) self.sourceVg.set_voltage(0.)
class Measurement(MeasurementBase): params = { 'data_dir': Folder('/home/holger'), 'Vg1s': Sweep(np.linspace(-1., 1., 101)), 'Vg2s': Sweep([0.]), 'Vds': 10e-3, 'commongate': Boolean(False), 'Rg1': 100e3, 'Rg2': 100e3, 'Rds': 2.2e3, 'stabilise_time': 5, 'comment': String('comment') } observables = [ 'Vg1', 'Vg1m', 'Ileak1', 'Vg2', 'Vg2m', 'Ileak2', 'Vds', 'Vdsm', 'Rs' ] alarms = [ ['np.abs(Ileak1) > 1e-8', MeasurementBase.ALARM_CALLCOPS], ['np.abs(Ileak2) > 1e-8', MeasurementBase.ALARM_CALLCOPS], ['np.abs(Vg1-Vg2)', MeasurementBase.ALARM_SHOWVALUE ] # useful if we just want to know how much voltage # is applied between the two gates ] def __init__(self, redirect_console=False, parent=None): super(Measurement, self).__init__(redirect_console=redirect_console, parent=parent) time.sleep(0.5) # take some time to load def measure(self, data_dir, Vg1s, Vg2s, Vds, commongate, Rg1, Rg2, Rds, stabilise_time, **kwargs): print("Starting acquisition script...") print( "Because I need to save my data somewhere, I will save it in the following directory:" ) print(data_dir) # initialise instruments try: self.sourceVg1 = sourceVg1 = VoltageSource( ) # here we should add safety limits self.sourceVg2 = sourceVg2 = VoltageSource() self.sourceVds = sourceVds = VoltageSource() self.meterVg1 = meterVg1 = VoltMeter() self.meterVg2 = meterVg2 = VoltMeter() self.meterVds = meterVds = VoltMeter() except: print("There has been an error setting up one of the instruments.") raise # prepare saving data filename = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') + '.txt' self.prepare_saving('testdata/' + filename) # loops sourceVds.set_voltage(Vds) for Vg2 in Vg2s: sourceVg2.set_voltage(Vg2) for Vg1 in Vg1s: if self.flags['quit_requested']: return locals() sourceVg1.set_voltage(Vg1) # stabilise progressbar_wait(stabilise_time) # measure Vg1m = meterVg1.get_voltage() Vg2m = meterVg2.get_voltage() Vdsm = meterVds.get_voltage() # do calculations Ileak1 = (Vg1 - Vg1m) / Rg1 Ileak2 = (Vg2 - Vg2m) / Rg2 Rs = Rds * Vdsm / (Vds - Vdsm) # save data self.save_row(locals()) print("Acquisition done.") return locals() def tidy_up(self): self.end_saving() print("Driving all voltages back to zero...") self.sourceVg1.set_voltage(0.) self.sourceVg2.set_voltage(0.) self.sourceVds.set_voltage(0.)
class Measurement(MeasurementBase): params = { 'Vdss': Sweep([10e-3]), 'Vg1s': Sweep([0.1]), 'Vg2s': Sweep([0.]), 'commongate': Boolean(False), 'Rg2': 100e3, 'Rds': 2.2e3, 'stabilise_time': 0.05, 'comment': String(''), 'data_dir': Folder(r'D:\MeasurementJANIS\Holger\test'), 'useVNA': Boolean(False), } observables = [ 'Vg1', 'Vg2', 'Vg2m', 'Ileak2', 'Vds', 'Vdsm', 'Rs', 'Ta', 'Tb' ] alarms = [ ['np.abs(Ileak2) > 1e-8', MeasurementBase.ALARM_CALLCOPS], ['np.abs(Vg1-Vg2)', MeasurementBase.ALARM_SHOWVALUE ] # useful if we just want to know how much voltage # is applied between the two gates ] def measure(self, data_dir, comment, Vdss, Vg1s, Vg2s, commongate, Rg2, Rds, stabilise_time, useVNA, **kwargs): print("===================================") print("Starting acquisition script...") # initialise instruments try: print("Setting up DC sources and voltmeters...") bilt = Bilt('TCPIP0::192.168.0.2::5025::SOCKET') self.sourceVds = sourceVds = BiltVoltageSource(bilt, "I1", initialise=False) self.sourceVg1 = sourceVg1 = BiltVoltageSource(bilt, "I2", initialise=False) self.sourceVg2 = sourceVg2 = BiltVoltageSource(bilt, "I3", initialise=False) self.meterVds = meterVds = BiltVoltMeter(bilt, "I5;C1", "2", "Vdsm") self.meterVg2 = meterVg2 = BiltVoltMeter(bilt, "I5;C3", "2", "Vg2m") print("DC sources and voltmeters are set up.") except: print( "There has been an error setting up DC sources and voltmeters." ) raise if useVNA: try: print("Setting up VNA") vna = AnritsuVNA('GPIB::6::INSTR') self.freqs = vna.get_freq_list() # get frequency list print("VNA is set up.") except: print("There has been an error setting up the VNA.") raise try: print("Setting up temperature controller...") tc = SI9700('GPIB::14::INSTR') print("Temperature controller is set up.") except: print( "There has been an error setting up the temperature controller." ) raise timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') # prepare saving DC data filename = timestamp + ('_' + comment if comment else '') self.prepare_saving(os.path.join(data_dir, filename + '.txt')) # prepare saving RF data if useVNA: spectra_fol = os.path.join(data_dir, filename) try: os.makedirs(spectra_fol) except OSError as e: if e.errno != errno.EEXIST: raise # loops for Vds in Vdss: sourceVds.set_voltage(Vds) for Vg2 in Vg2s: if not commongate: sourceVg2.set_voltage(Vg2) for Vg1 in Vg1s: if self.flags['quit_requested']: return locals() sourceVg1.set_voltage(Vg1) if commongate: Vg2 = Vg1 sourceVg2.set_voltage(Vg1) # stabilise time.sleep(stabilise_time) # measure Vdsm = meterVds.get_voltage() Vg2m = meterVg2.get_voltage() Ta = tc.get_temp('a') Tb = tc.get_temp('b') # do calculations Ileak2 = (Vg2 - Vg2m) / Rg2 Rs = Rds * Vdsm / (Vds - Vdsm) # save data self.save_row(locals()) # save VNA data if useVNA: print("Getting VNA spectra...") vna.single_sweep() table = vna.get_table(range(1, 5)) timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp + '_Vg1=%2.4f' % ( Vg1) + '_Vg2=%2.4f' % (Vg2) + '_Vds=%2.4f' % ( Vds) + '.txt' np.savetxt(os.path.join(spectra_fol, spectrum_file), np.transpose(table)) print("Acquisition done.") return locals() def tidy_up(self): self.end_saving() print("Driving all voltages back to zero...") self.sourceVds.set_voltage(0.) self.sourceVg1.set_voltage(0.) self.sourceVg2.set_voltage(0.)
class Measurement(MeasurementBase): params = { 'Vgs': Sweep([0.]), 'Vg0': 0., 'Vchuck0': 10., 'Vchuckmax': 30., 'CapaRatio': 10., 'Rg': 100e3, 'stabilise_time': 0.3, 'comment': String(''), 'data_dir': Folder(r''), 'use_vna': Boolean(True), 'init_bilt': Boolean(False), 'init_yoko': Boolean(False) } observables = ['Vg', 'Vgm', 'Vchuck', 'Ileak'] alarms = [ ['np.abs(Ileak) > 1e-8', MeasurementBase.ALARM_CALLCOPS] ] def measure(self, data_dir, Vgs, Vg0, Vchuck0, Vchuckmax, CapaRatio, Rg, comment, stabilise_time, use_vna, init_bilt, init_yoko, **kwargs): print("===================================") print("Starting acquisition script...") # initialise instruments try: print("Setting up DC sources and voltmeters...") bilt = Bilt('TCPIP0::192.168.0.2::5025::SOCKET') if init_bilt: # source (bilt, channel, range, filter, slope in V/ms, label): self.sourceVg = sourceVg = BiltVoltageSource(bilt, "I1", "12", "1", 0.005, "Vg") else: self.sourceVg = sourceVg = BiltVoltageSource(bilt, "I1", initialise=False) # voltmeter (bilt, channel, filt, label=None) self.meterVg = meterVg = BiltVoltMeter(bilt, "I5;C1", "2", "Vgm") # voltage source for chuck self.yoko = yoko = Yoko7651("GPIB::3::INSTR", func="VOLT", rang=30., slope=1., initialise=init_yoko, verbose=True) print("DC sources and voltmeters are set up.") except: print("There has been an error setting up DC sources and voltmeters:") raise try: print("Setting up VNA...") vna = AnritsuVNA('GPIB::6::INSTR') sweeptime = vna.get_sweep_time() print("VNA is set up.") except: print("There has been an error setting up the VNA:") raise timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') # prepare saving DC data filename = timestamp + ('_'+comment if comment else '') self.prepare_saving(os.path.join(data_dir, filename+'.txt')) if use_vna: # prepare saving RF data spectra_fol = os.path.join(data_dir, filename) try: os.makedirs(spectra_fol) except OSError as e: if e.errno != errno.EEXIST: raise if vna.get_sweep_type() == 'FSEGM': with open(os.path.join(spectra_fol, 'VNAconfig'), 'w') as f: vna.dump_freq_segments(f) for Vg in Vgs: if self.flags['quit_requested']: print("Stopping acquisition.") return locals() print("Setting Vg = {}".format(Vg)) # calculate new chuck voltage to keep field constant # set Vg sourceVg.set_voltage(Vg) Vchuck = Vchuck0+CapaRatio*(Vg-Vg0) if np.abs(Vchuck) <= Vchuckmax: print("Set chuck voltage:", Vchuck) yoko.set_voltage(Vchuck) else: print("Chuck voltage too high:", Vchuck) print("Not changing chuck voltage.") Vchuck = yoko.get_voltage() # wait time.sleep(stabilise_time) # read voltages Vgm = meterVg.get_voltage() # do calculations Ileak = (Vg-Vgm)/Rg # save DC data self.save_row(locals()) if use_vna: # save VNA data print("Getting VNA spectra...") vna.single_sweep(wait=False) # display sweep progress progressbar_wait(sweeptime) # make sure sweep is really done while not vna.is_sweep_done(): time.sleep(0.5) table = vna.get_table([1,2,3,4]) timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp+'_Vg=%2.4f_Vchuck=%2.4f'%(Vg, Vchuck)+'.txt' np.savetxt(os.path.join(spectra_fol, spectrum_file), np.transpose(table)) print("Acquisition done.") return locals() def tidy_up(self): self.end_saving() print("Driving all voltages back to zero...") self.sourceVg.set_voltage(0.) self.yoko.set_voltage(0.)
class Measurement(MeasurementBase): params = { 'Vdss': Sweep([0.0]), 'Vg1s': Sweep([0.0]), 'Vg2s': Sweep([0.0]), 'commongate': Boolean(False), 'Rg1': 100e3, 'Rg2': 100e3, 'Rds': 22e3, 'stabilise_time': 0.05, 'comment': String(''), 'data_dir': Folder(r'D:\MeasurementJANIS\Holger\KTW H5 2x3\2017-11-09 LHe') } observables = [ 'Vg1', 'Vg1m', 'Ileak1', 'Vg2', 'Vg2m', 'Ileak2', 'Vds', 'Vdsm', 'Rs' ] alarms = [ ['np.abs(Ileak1) > 1e-8', MeasurementBase.ALARM_CALLCOPS], ['np.abs(Ileak2) > 1e-8', MeasurementBase.ALARM_CALLCOPS], ['np.abs(Vg1-Vg2)', MeasurementBase.ALARM_SHOWVALUE ] # useful if we just want to know how much voltage # is applied between the two gates ] def measure(self, data_dir, comment, Vdss, Vg1s, Vg2s, commongate, Rg1, Rg2, Rds, stabilise_time, **kwargs): print("===================================") print("Starting acquisition script...") # initialise instruments try: print("Setting up DC sources and voltmeters...") bilt = Bilt('TCPIP0::192.168.0.2::5025::SOCKET') self.sourceVds = sourceVds = BiltVoltageSource(bilt, "I1", initialise=False) self.sourceVg1 = sourceVg1 = BiltVoltageSource(bilt, "I2", initialise=False) self.sourceVg2 = sourceVg2 = BiltVoltageSource(bilt, "I3", initialise=False) self.meterVds = meterVds = BiltVoltMeter(bilt, "I5;C1", "2", "Vdsm") self.meterVg1 = meterVg1 = BiltVoltMeter(bilt, "I5;C2", "2", "Vg1m") self.meterVg2 = meterVg2 = BiltVoltMeter(bilt, "I5;C3", "2", "Vg2m") print("DC sources and voltmeters are set up.") except: print( "There has been an error setting up DC sources and voltmeters." ) raise timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') # prepare saving data filename = timestamp + '_' + (comment if comment else '') + '.txt' self.prepare_saving(os.path.join(data_dir, filename)) # loops for Vds in Vdss: sourceVds.set_voltage(Vds) for Vg2 in Vg2s: if not commongate: sourceVg2.set_voltage(Vg2) for Vg1 in Vg1s: if self.flags['quit_requested']: return locals() sourceVg1.set_voltage(Vg1) if commongate: Vg2 = Vg1 sourceVg2.set_voltage(Vg1) # stabilise time.sleep(stabilise_time) # measure Vdsm = meterVds.get_voltage() Vg1m = meterVg1.get_voltage() Vg2m = meterVg2.get_voltage() # do calculations Ileak1 = (Vg1 - Vg1m) / Rg1 Ileak2 = (Vg2 - Vg2m) / Rg2 Rs = Rds * Vdsm / (Vds - Vdsm) # save data self.save_row(locals()) print("Acquisition done.") return locals() def tidy_up(self): self.end_saving() print("Driving all voltages back to zero...") self.sourceVds.set_voltage(0.) self.sourceVg1.set_voltage(0.) self.sourceVg2.set_voltage(0.)
class Measurement(MeasurementBase): params = { 'sweep': Boolean(False), 'startpoint': 0., 'direction': 1., 'step': 1., 'Ithresh': 3e-7, 'Vmax': 30, 'stabilise_time': 10, 'init': Boolean(True), 'use_vna': Boolean(True), 'comment': String(''), 'data_dir': Folder(r'D:\MeasurementJANIS\Holger\test') } observables = ['Vg', 'Vgm', 'Ileak'] alarms = [] def measure(self, step, startpoint, direction, Ithresh, Vmax, sweep, stabilise_time, init, use_vna, data_dir, comment, **kwargs): print("===================================") print("Starting acquisition script...") vna_string = '' # initialise instruments try: print("----------------------------------------") print("Setting up Keithley DC sources...") self.sourceVg = sourceVg = K2400('GPIB::24::INSTR', sourcemode='v', vrang=200, irang=10e-6, slope=1, initialise=init) print("DC sources are set up.") except: print("There has been an error setting up DC sources.") raise if use_vna: print("Setting up VNA...") vna = AnritsuVNA('GPIB::6::INSTR') sweeptime = vna.get_sweep_time() if vna.get_sweep_type() != 'FSEGM': raise Exception('Please use segmented frequency sweep') # check if the RF power is the same on both ports and for all # frequency segments count = int(vna.query(':SENS:FSEGM:COUN?')) vna_pow = None for i in range(1, count + 1): port1pow = float( vna.query(':SENS:FSEGM{}:POW:PORT1?'.format(i))) port2pow = float( vna.query(':SENS:FSEGM{}:POW:PORT2?'.format(i))) if vna_pow is None and port1pow == port2pow: vna_pow = port1pow elif vna_pow is not None and port1pow == port2pow and port1pow == vna_pow: continue else: raise Exception( "Please select the same power for all ports and frequency segments" ) port1att = vna.get_source_att(1) port2att = vna.get_source_att(2) if port1att == port2att: vna_pow -= port1att else: raise Exception( "Please select the same attenuators for both ports") vna_string = '_pwr={:.0f}'.format(vna_pow) print("VNA is set up.") # define name timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') filename = timestamp + vna_string + ('_' + comment if comment else '') # prepare saving RF data spectra_fol = os.path.join(data_dir, filename) create_path(spectra_fol) # prepare saving DC data self.prepare_saving(os.path.join(data_dir, filename + '.txt')) if use_vna: # prepare saving RF data spectra_fol = os.path.join(data_dir, filename) create_path(spectra_fol) # save segmented frequency sweep data to file with open(os.path.join(spectra_fol, 'VNAconfig'), 'w') as f: vna.dump_freq_segments(f) Vg = startpoint def measure_point(Ithresh=np.inf): print('Setting Vg=' + str(Vg) + ' V...') sourceVg.set_voltage(Vg) print('Stabilising...') progressbar_wait(stabilise_time) # measure Vgm = sourceVg.get_voltage() Ileak = sourceVg.get_current() # save data self.save_row(locals()) # save VNA data if use_vna: # save VNA data print("Getting VNA spectra...") vna.single_sweep(wait=False) # display sweep progress progressbar_wait(sweeptime) # make sure sweep is really done while not vna.is_sweep_done(): time.sleep(0.5) table = vna.get_table([1, 2, 3, 4]) timestamp = time.strftime('%Y-%m-%d_%Hh%Mm%Ss') spectrum_file = timestamp + '_Vg={:.3f}.txt'.format(Vg) np.savetxt(os.path.join(spectra_fol, spectrum_file), np.transpose(table)) return np.abs(Ileak) > Ithresh # measure at 0 V measure_point() # sweep if requested #╦direction = 1. # up if direction not in [1., -1.]: raise Exception("select valid direction 1. or -1.") back_to_zero = False decimals = int(max(1., -np.log10(step) + 1.)) while sweep: if self.flags['quit_requested']: return locals() Vg = np.around(Vg + step * direction, decimals) if np.abs(Vg) > Vmax: print("Reached maximum voltage! Inverting sweep direction.") if direction < 0. and Vg < 0.: back_to_zero = True direction = -direction continue leak = measure_point(Ithresh) if leak: if direction * Vg < 0.: continue if direction < 0. and Vg < 0.: back_to_zero = True direction = -direction if np.abs(Vg) < 1e-12 and back_to_zero: break print("Acquisition done.") return locals() def tidy_up(self): self.end_saving() print("Driving all voltages back to zero...") self.sourceVg.set_voltage(0.)