Ejemplo n.º 1
0
 def __init__(self, devices, pcb, structures, ivcurves_max_bias=150, max_current=5e-6):
     self.iv = IVscan(devices=devices, max_current=max_current, live=False)
     self.relay = Silab_relay()
     
     #dut_fridge = Dut('binder.yaml')
     #dut_fridge.init()
     #self.fridge = dut_fridge['Climatechamber']
     
     self.devices = devices
     self.pcb = pcb
     self.structures = structures
     self.nchan = len(self.structures)
     self.ivcurves_max_bias = ivcurves_max_bias
     self.data = []
Ejemplo n.º 2
0
class automated_scans(object):
    '''
    Class of fully automated IV and source scans using the SilabRelay and qMCA setups.
    '''
    def __init__(self, devices, pcb, structures, ivcurves_max_bias=150, max_current=5e-6):
        self.iv = IVscan(devices=devices, max_current=max_current, live=False)
        self.relay = Silab_relay()
        
        #dut_fridge = Dut('binder.yaml')
        #dut_fridge.init()
        #self.fridge = dut_fridge['Climatechamber']
        
        self.devices = devices
        self.pcb = pcb
        self.structures = structures
        self.nchan = len(self.structures)
        self.ivcurves_max_bias = ivcurves_max_bias
        self.data = []
        
        #self.iv.reset()
    
    def _get_current(self, device, channel='all', fast=False):
        '''
        Gets a current measurement for a specific channel or all channels using the IVScan.measure_current method.
        '''
        if type(channel) == int:
            self.relay.switch_to(channel)
            if fast:
                return self.iv.get_current_reading(device)
            else:
                return self.iv.measure_current(device)
        else:
            data = []
            for c in range(0, self.nchan):
                self.relay.switch_to(c)
                if fast:
                    current = self.iv.get_current_reading(device)
                else:
                    current = self.iv.measure_current(device)
                data.append(current)
            return data
            
    def _go_to_temperature(self, temp, wait_for=600, timeout=1800):
        '''
        Sets new temperature target value and wait for reported just value to reach target value. Then wait an additional time to let DUT cool to air temperature.
        '''
        logging.info('Setting temperature to %iC' % temp)
        self.fridge.set_temperature(temp)
        timeout = int(timeout/5)
        count = 0
        logging.debug('Starting loop')
        while True:
            count += 1
            time.sleep(5)
            just = float(self.fridge.get_temperature())
            logging.debug('Target value is %1.2f, just value is %1.2f' % (temp, just))
            if just == temp or (just < temp and just > (temp - 0.05*temp)) or (just > temp and just < (temp + 0.05*temp)):
                logging.debug('Target value reached!')
                time.sleep(wait_for)
                return True
            if count >= timeout:
                logging.debug('Target value not reached but ran into timeout!')
                return False
            
    def _take_source_scan(self, qmca_channel, threshold=3000, duration=600, file_name='', max_events=1000000, adc_differential_voltage=1.5):
        '''
            Take a single source scan using qMCA setup / class
        '''
        if not file_name:
            file_name = 'source_scan_%s' % (self.pcb)
        elif file_name.split('.')[-1] == 'h5':
            file_name = file_name.split('.')[:-1]
            
        
        with qmca.qmca(channel=qmca_channel,
                                threshold=threshold,
                                adc_differential_voltage=adc_differential_voltage) as my_qmca:
        
            start_time = time.time()
            actual_time = start_time
            
            my_qmca.start(out_filename=file_name)
            while ((actual_time < (start_time + duration)) and (my_qmca.event_count <= max_events)):
                if self.pbar.currval < 100:
                    self.pbar.update(self.pbar.currval + 0.5)
                actual_time = time.time()
                time.sleep(1)
        
        
    def take_ivcurve(self, device='auto', channel='all', file_name=''):
        '''
        Take simple IV curve for either one specific channel or all connected channels
        '''
        if type(device) == str and device == 'auto':
            device = self.devices[self.devices.keys()[0]]

        if type(channel) == int:
            if not file_name:
                file_name = 'ivcurve_%s_structure%s_nwellFloating.csv' % (self.pcb, self.structures[channel])
            elif not file_name.split('.')[-1] == 'csv':
                file_name = file_name + '.csv'
                
            logging.debug('Switching to channel %i' % channel)
            self.relay.switch_to(channel)
            logging.info('Take IV curve for structure%s' % self.structures[channel])
            self.iv.scan_iv(file_name=file_name, max_bias_voltage=self.ivcurves_max_bias)
        elif channel == 'all' or channel == 'All':
            for c in range(0, self.nchan):
                if not file_name:
                    file_name_set = 'ivcurve_%s_structure%s_nwellFloating.csv' % (self.pcb, self.structures[c])
                elif not file_name.split('.')[-1] == 'csv':
                    file_name_set = '%s_structure%s.csv' % (file_name, self.structures[c])
                elif file_name.split('.')[-1] == 'csv':
                    file_name_set = '%s_structure%s.csv' % (file_name.split('.')[:-1], self.structures[c])

                logging.debug('Switching to channel %i' % c)
                self.relay.switch_to(c)
                logging.info('Take IV curve for structure%s' % self.structures[c])
                self.iv.scan_iv(file_name=file_name_set, max_bias_voltage=self.ivcurves_max_bias)
                
                
    def take_iv_with_nwell(self, device='auto', channel='all', file_name='', source_bias=False):
        '''
        Take simple IV curve for either one specific channel or all connected channels
        '''
        if type(device) == str and device == 'auto':
            device = self.devices[self.devices.keys()[0]]

        if type(channel) == int:
            if not file_name:
                file_name = 'ivcurve_%s_structure%s_nwell=HV.csv' % (self.pcb, self.structures[channel])
            elif not file_name.split('.')[-1] == 'csv':
                file_name = file_name + '.csv'
                
            logging.debug('Switching to channel %i' % channel)
            self.relay.switch_to(channel)
            logging.info('Take IV curve for structure%s' % self.structures[channel])
            self.iv.scan_iv_with_nwell(file_name=file_name, max_bias_voltage=self.ivcurves_max_bias, max_nwell_voltage=-1, source_bias=source_bias)
        elif channel == 'all' or channel == 'All':
            for c in range(0, self.nchan):
                if not file_name:
                    file_name_set = 'ivcurve_%s_structure%s_nwell=HV.csv' % (self.pcb, self.structures[c])
                elif not file_name.split('.')[-1] == 'csv':
                    file_name_set = '%s_structure%s.csv' % (file_name, self.structures[c])
                elif file_name.split('.')[-1] == 'csv':
                    file_name_set = '%s_structure%s.csv' % (file_name.split('.')[:-1], self.structures[c])

                logging.debug('Switching to channel %i' % c)
                self.relay.switch_to(c)
                logging.info('Take IV curve for structure%s' % self.structures[c])
                self.iv.scan_iv_with_nwell(file_name=file_name_set, max_bias_voltage=self.ivcurves_max_bias, max_nwell_voltage=-1, source_bias=source_bias)
                
                
    def take_ivcurve_with_potential(self, potential_name, potential_device_name, device='auto', channel='all', file_name=''):
        '''
        Take simple IV curve with additional potential for either one specific channel or all connected channels
        '''
        if type(device) == str and device == 'auto':
            device = self.devices[self.devices.keys()[0]]

        print device

        if type(channel) == int:
            if not file_name:
                file_name = 'ivcurve_%s_structure%s_nwellFloating.csv' % (self.pcb, self.structures[channel])
            elif not file_name.split('.')[-1] == 'csv':
                file_name = file_name + '.csv'
                
            logging.debug('Switching to channel %i' % channel)
            self.relay.switch_to(channel)
            logging.info('Take IV curve for structure%s' % self.structures[channel])
            self.iv.scan_iv_with_potential(file_name=file_name, max_bias_voltage=self.ivcurves_max_bias, potential_name=potential_name, potential_device_name=potential_device_name)
        elif channel == 'all' or channel == 'All':
            for c in range(0, self.nchan):
                if not file_name:
                    file_name_set = 'ivcurve_%s_structure%s_nwellFloating.csv' % (self.pcb, self.structures[c])
                elif not file_name.split('.')[-1] == 'csv':
                    file_name_set = '%s_structure%s.csv' % (file_name, self.structures[c])
                elif file_name.split('.')[-1] == 'csv':
                    file_name_set = '%s_structure%s.csv' % (file_name.split('.')[:-1], self.structures[c])

                logging.debug('Switching to channel %i' % c)
                self.relay.switch_to(c)
                logging.info('Take IV curve for structure%s' % self.structures[c])
                self.iv.scan_iv_with_potential(file_name=file_name_set, max_bias_voltage=self.ivcurves_max_bias, potential_name=potential_name, potential_device_name=potential_device_name)
    
    
    def anneal(self, device, voltage=3, annealing_time=60*80, temperature=60, t_reset=-20, file_name=''):
        '''
        Set fridge to annealing temperature and record warmup currents.
        Stay at annealing temperature for specified time and record currents of all structures every minute.
        Then go back to rest temperature and record cooldown currents.
        '''
        if not file_name:
            file_name_warmup = 'annealing_%s_HV=%i_t=%i_T=%i_warmup.csv' % (self.pcb, voltage, annealing_time, temperature)
            file_name_cooldown = 'annealing_%s_HV=%i_t=%i_T=%i_cooldown.csv' % (self.pcb, voltage, annealing_time, temperature)
            file_name = 'annealing_%s_HV=%i_t=%i_T=%i.csv' % (self.pcb, voltage, annealing_time, temperature)
        elif not file_name.split('.')[-1] == 'csv':
            file_name_warmup = file_name + '_warmup.csv'
            file_name_cooldown = file_name + '_cooldown.csv'
            file_name = file_name + '.csv'
        
        '''Warmup'''
        logging.info('Start warmup phase. Set temperature to %iC, apply %iV and record current every minute.' % (temperature, voltage))
        with open(file_name_warmup, 'wb') as outfile:
            f = csv.writer(outfile ,quoting=csv.QUOTE_NONNUMERIC)
            header = ['Timestamp', 'Temperature [C]']
            for s in self.structures:
                header.append('Strucutre %s [A]' % s)
            f.writerow(header)
             
            self.fridge.set_temperature(temperature)
            device.set_voltage(voltage)
            device.on()
            count, wait = 0, 600
            while True:
                count += 1
                time.sleep(1)
                just = float(self.fridge.get_temperature())
                logging.debug('Target value is %1.2f, just value is %1.2f' % (temperature, just))
                 
                if (count % 60) == 0:
                    row = [time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), just]
                    row.extend(self._get_current(device, fast=True))
                    f.writerow(row)
                    outfile.flush()
                     
                if just >= (temperature - (temperature * 0.05)):
                    wait -= 1
                     
                if wait == 0:
                    break
         
        '''Annealing'''
        logging.info('Target temperature of %iC reached, start annealing for %imin, apply %iV and record current every minute.' % (temperature, annealing_time/60, voltage))
        with open(file_name, 'wb') as outfile:
            f = csv.writer(outfile ,quoting=csv.QUOTE_NONNUMERIC)
            header = ['Timestamp', 't [min]']
            for s in self.structures:
                header.append('Strucutre %s [A]' % s)
            f.writerow(header)
            row = [time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), 0]
            row.extend(self._get_current(device))
            f.writerow(row)
            
            start_time = time.time()
            actual_time = start_time
            last_measure_time = start_time
            while True:
                time.sleep(1)
                actual_time = time.time()
                if (actual_time - last_measure_time) >= 60:
                    just = float(self.fridge.get_temperature())
                    logging.debug('Target value is %1.2f, just value is %1.2f' % (temperature, just))
                     
                    row = [time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), int(count/60)]
                    row.extend(self._get_current(device))
                    f.writerow(row)
                    outfile.flush()
                    last_measure_time = time.time()
                 
                if (actual_time-start_time) >= annealing_time:
                    break
            
            row = [time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), int(count/60)]
            row.extend(self._get_current(device))
            f.writerow(row)
            outfile.flush()
                
        
        '''Cooldown'''
        logging.info('Annealing done! Start cooldown phase. Set temperature to %iC, apply %iV and record current every minute.' % (t_reset, voltage))
        with open(file_name_cooldown, 'wb') as outfile:
            f = csv.writer(outfile ,quoting=csv.QUOTE_NONNUMERIC)
            header = ['Timestamp', 'Temperature [C]']
            for s in self.structures:
                header.append('Strucutre %s [A]' % s)
            f.writerow(header)
            
            self.fridge.set_temperature(t_reset)
            count, wait = 0, 600
            while True:
                count += 1
                time.sleep(1)
                just = float(self.fridge.get_temperature())
                logging.debug('Target value is %1.2f, just value is %1.2f' % (temperature, just))
                
                if (count % 60) == 0:
                    row = [time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()), just]
                    row.extend(self._get_current(device, fast=True))
                    f.writerow(row)
                    outfile.flush()
                    
                if just <= (t_reset + (t_reset * 0.05)):
                    wait -= 1
                    
                if wait == 0:
                    break
    
    def measure_arrhenius(self, device='auto', voltage=20, temp_range=range(-30, 61, 5), file_name=''):
        '''
        Apply constant voltage and measure current of all structures for different temperatures
        '''
        logging.info('Measure Arrhenius plot at %iV bias from %i to %iC' % (voltage, min(temp_range), max(temp_range)))
        pbar = progressbar.ProgressBar(widgets=['', progressbar.Percentage(), ' ', progressbar.Bar(marker='*', left='|', right='|'), ' ', progressbar.AdaptiveETA()], maxval=len(temp_range), poll=10, term_width=80).start()
        if type(device) == str and device == 'auto':
            device = self.devices[self.devices.keys()[0]]
        
        if not file_name:
            file_name = 'arrhenius_%s_HV=%i.csv' % (self.pcb, voltage)
        elif not file_name.split('.')[-1] == 'csv':
            file_name = file_name + '.csv'
        
        self.iv.ramp_to(device, voltage)
        
        with open(file_name, 'wb') as outfile:
            f = csv.writer(outfile ,quoting=csv.QUOTE_NONNUMERIC)
            header = ['Temperature [C]']
            for s in self.structures:
                header.append('Strucutre %s [A]' % s)
            f.writerow(header)
            outfile.flush()
            logging.info('Start Arrhenius measurement')
            for temp in temp_range:
                self._go_to_temperature(temp)
                row = [temp]
                row.extend(self._get_current(device))
                f.writerow(row)
                outfile.flush()
                pbar.update(pbar.currval + 1)
                
        
    def source_scan_temp_sweep(self, qmca_channel, bias_device, structure, source, t_range=range(-30, 41, 10), bias=10, threshold=3000, duration=600, max_events=1000000):
        if (not type(bias) == int and not type(bias) == list) or (type(bias) == list and not len(bias) == len(t_range)):
            raise ValueError('bias has to be either constant int or list with same length as t_range')
        
        if type(bias) == int:
            bias_value = bias 
            bias = []
            for _ in range(len(t_range)):
                bias.append(bias_value)
        
        print t_range
        print bias
        
        bias_device.on()
        
        self.pbar = progressbar.ProgressBar(widgets=['', progressbar.Percentage(), ' ', progressbar.Bar(marker='*', left='|', right='|'), ' ', progressbar.AdaptiveETA()],
                                       maxval=duration*len(t_range),
                                       poll=10,
                                       term_width=80).start()        
        
        with open('source_scan_temp_sweep_bias_currents_structure%s.csv' % structure, 'wb') as outfile:
            f = csv.writer(outfile ,quoting=csv.QUOTE_NONNUMERIC)
            header = ['Temperature [C]', 'Bias Current [A]']
            f.writerow(header)
        
            for self.i, t in enumerate(t_range):
                file_name = 'source_scan_%s_%s_structure%s_HV=%i_T=%i' % (source, self.pcb, structure, bias[self.i], t)
                self._go_to_temperature(t)
                print "_got_to_temperature returned True..."
                self.iv.ramp_to(bias_device, bias[self.i])
                f.writerow([t, self.iv.measure_current(bias_device)])
                outfile.flush()
                self._take_source_scan(qmca_channel=qmca_channel, threshold=threshold, duration=duration, file_name=file_name, max_events=max_events)
            
            self.pbar.finish()