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 = { '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 = { '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.)