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.)
Beispiel #2
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.)
Beispiel #3
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.)
Beispiel #4
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()
Beispiel #5
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.)
Beispiel #6
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 = {
        '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.)
Beispiel #8
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.)
Beispiel #9
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.)
Beispiel #11
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.)
Beispiel #12
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.)