Source code for pylab_ml.dmm.keithley.keithley2000

"""Measuremet-Unit (SMU) Keithley2000.

:Date: |today|
:Author: Semi-ATE <info@Semi-ATE.org>

"""
from pylab_ml.base_instrument import logger
from pylab_ml.collate_instrument import Interface
from pylab_ml.smu.keithley.base_keithley import Keithley


[docs] class Keithley2000(Keithley): """ Interface to the Measuremet-Unit (SMU) Keithley2000. The Keithley2000 can measure voltage and current precisely :Date: |today| :Author: Semi-ATE <info@Semi-ATE.org> .. image:: ../_static/kethley2000.jpg """ interchoices = [Interface.usbserial, Interface.gpib]
[docs] def __init__(self, addr=None, interface=None, backend=None, identify=True, instName=None, **kwargs): """ Connect and initialize the Keithley2000. Parameters ---------- addr (int): Interface address interface (Interface): GPIB, USBSerial backend (str): visa backend is either '@ni' for NI-Library or '@py' for pure python pyvisa-py backend. On default it uses '@ni' on win32 and '@py' on other platforms. instName (string): Instance Name from parent. Example: Initialization >>> vdd = Keithley2000(addr=24) # GPIB or USB address >>> vdd.init() # connect and initialize instrument Example: Current measurement >>> i = vdd.current # measure (supply) current Example: Voltage measurement >>> v = vdd.voltage # measure voltage """ kwargs = {"addr": addr, "interface": interface, "backend": backend, "identify": identify, "instName": instName, **kwargs} super().__init__(**kwargs) logger.debug("Class {}".format(self.__class__.__name__)) self.msg_row_col = (1, 12)
[docs] def setup_inst(self): """Start setup instrument settings, called from class instruments.""" super().setup_inst() self._nplc = 1.0 self.per_threshold = 1.0 self.per_aperture = 1.0 self.freq_threshold = 1.0 self.freq_aperture = 1.0 if self.inst: if self.interface == Interface.gpib: self.inst.read_termination = '\n' self.inst.write_termination = '\n' else: self.inst.read_termination = '\r' self.inst.write_termination = '\r'
[docs] def error_list(self): """List of instrument errors.""" self.budget.set_slack(self) errorlist = [] while True: errormsg = self.inst.query(':SYST:ERR?') if errormsg is None or errormsg == "": break (c, m) = errormsg.split(",") print("{} : {}".format(c, m)) errorlist.append((c, m)) if errormsg == '0, "No error"': break return errorlist
@property def nplc(self): """ Set the conversion number of power line cycles accuracy, for all converters. For a PLC of 1, conversion rate is 1/50s = 20ms, max 10, min 0.1 accuracy """ val = self._nplc return float(val) @nplc.setter def nplc(self, cycles): # cycles are number of power line cycles for conversion self._nplc = cycles self.budget.set_slack(self) # in Keithley 2000 each measurement has separate accuracy in reality self.inst.write(':SENS:VOLT:NPLC {}'.format(cycles)) self.inst.write(':SENS:CURR:NPLC {}'.format(cycles)) self.inst.write(':SENS:VOLT:AC:NPLC {}'.format(cycles)) self.inst.write(':SENS:CURR:AC:NPLC {}'.format(cycles)) self.inst.write(':SENS:RES:NPLC {}'.format(cycles)) self.inst.write(':SENS:FRES:NPLC {}'.format(cycles)) self.inst.write(':SENS:TEMP:NPLC {}'.format(cycles)) @property def v_autorange(self): """Autorange voltage measurement on or off.""" self.budget.set_slack(self) res = self.inst.query(':SENS:VOLT:RANG:AUTO?') return (float(res) != 0) @v_autorange.setter def v_autorange(self, on): self.budget.set_slack(self) if on: self.inst.write(':SENS:VOLT:RANG:AUTO ON') else: self.inst.write(':SENS:VOLT:RANG:AUTO OFF') @property def i_autorange(self): """Autorange current measurement on or off.""" self.budget.set_slack(self) res = self.inst.query(':SENS:CURR:RANG:AUTO?') return (float(res) != 0) @i_autorange.setter def i_autorange(self, on): self.budget.set_slack(self) if on: self.inst.write(':SENS:CURR:RANG:AUTO ON') else: self.inst.write(':SENS:CURR:RANG:AUTO OFF') @property def vac_autorange(self): """Autorange AC voltage measurement on or off.""" self.budget.set_slack(self) res = self.inst.query(':SENS:VOLT:AC:RANG:AUTO?') return (float(res) != 0) @vac_autorange.setter def vac_autorange(self, on): self.budget.set_slack(self) if on: self.inst.write(':SENS:VOLT:AC:RANG:AUTO ON') else: self.inst.write(':SENS:VOLT:AC:RANG:AUTO OFF') @property def iac_autorange(self): """Autorange AC current measurement on or off.""" self.budget.set_slack(self) res = self.inst.query(':SENS:CURR:AC:RANG:AUTO?') return (float(res) != 0) @iac_autorange.setter def iac_autorange(self, on): self.budget.set_slack(self) if on: self.inst.write(':SENS:CURR:AC:RANG:AUTO ON') else: self.inst.write(':SENS:CURR:AC:RANG:AUTO OFF') @property def r_autorange(self): """Autorange resistance measurement on or off.""" self.budget.set_slack(self) res = self.inst.query(':SENS:RES:RANG:AUTO?') return (float(res) != 0) @r_autorange.setter def r_autorange(self, on): self.budget.set_slack(self) if on: self.inst.write(':SENS:RES:RANG:AUTO ON') else: self.inst.write(':SENS:RES:RANG:AUTO OFF') @property def fr_autorange(self): """Autorange 4-wire resistance measurement on or off.""" self.budget.set_slack(self) res = self.inst.query(':SENS:FRES:RANG:AUTO?') return (float(res) != 0) @fr_autorange.setter def fr_autorange(self, on): self.budget.set_slack(self) if on: self.inst.write(':SENS:FRES:RANG:AUTO ON') else: self.inst.write(':SENS:FRES:RANG:AUTO OFF') @property def v_range(self): """Set the voltage measurement range.""" self.budget.set_slack(self) val = self.inst.query(':SENS:VOLT:RANG?') return float(val) @v_range.setter def v_range(self, vmax): # vmax in V self._v_range = vmax self.budget.set_slack(self) self.inst.write(':SENS:VOLT:RANG {}'.format(vmax)) @property def i_range(self): """Set the current measurement range.""" self.budget.set_slack(self) val = self.inst.query(':SENS:CURR:RANG?') return float(val) @i_range.setter def i_range(self, imax): # imax in I self._i_range = imax self.budget.set_slack(self) self.inst.write(':SENS:CURR:RANG {}'.format(imax)) @property def vac_range(self): """Set the AC voltage measurement range.""" self.budget.set_slack(self) val = self.inst.query(':SENS:VOLT:AC:RANG?') return float(val) @vac_range.setter def vac_range(self, vmax): # vmax in V self._vac_range = vmax self.budget.set_slack(self) self.inst.write(':SENS:VOLT:AC:RANG {}'.format(vmax)) @property def iac_range(self): """Set the AC current measurement range.""" self.budget.set_slack(self) val = self.inst.query(':SENS:CURR:AC:RANG?') return float(val) @iac_range.setter def iac_range(self, imax): # imax in A self._iac_range = imax self.budget.set_slack(self) self.inst.write(':SENS:CURR:AC:RANG {}'.format(imax)) @property def r_range(self): """Set the resistance measurement range.""" self.budget.set_slack(self) val = self.inst.query(':SENS:RES:RANG?') return float(val) @r_range.setter def r_range(self, rmax): # rmax in Ohms self._r_range = rmax self.budget.set_slack(self) self.inst.write(':SENS:RES:RANG {}'.format(rmax)) @property def fr_range(self): """Set voltage 4-wire resistance range.""" self.budget.set_slack(self) val = self.inst.query(':SENS:FRES:RANG?') return float(val) @fr_range.setter def fr_range(self, rmax): # rmax in Ohms self._fr_range = rmax self.budget.set_slack(self) self.inst.write(':SENS:FRES:RANG {}'.format(rmax)) @property def voltage(self): """Get voltage.""" self.budget.set_slack(self) self.inst.write(':SENS:FUNC "VOLT"') value = self.inst.query(':READ?') logger.measure("{!r} voltage == {}".format(self.instName, float(value))) return float(value) @property def current(self): """Get current.""" self.budget.set_slack(self) self.inst.write(':SENS:FUNC "CURR"') value = self.inst.query(':READ?') logger.measure("{!r} current == {}".format(self.instName, float(value))) return float(value) @property def ac_voltage(self): """Get AC voltage.""" self.budget.set_slack(self) self.inst.write(':SENS:FUNC "VOLT:AC"') value = self.inst.query(':READ?') logger.measure("{!r} ac_voltage == {}".format(self.instName, float(value))) return float(value) @property def ac_current(self): """Get AC current.""" self.budget.set_slack(self) self.inst.write(':SENS:FUNC "CURR:AC"') value = self.inst.query(':READ?') logger.measure("{!r} ac_current == {}".format(self.instName, float(value))) return float(value) @property def resistance(self): """Get resistance.""" self.budget.set_slack(self) self.inst.write(':SENS:FUNC "RES"') value = self.inst.query(':READ?') logger.measure("{!r} resistance == {}".format(self.instName, float(value))) return float(value) @property def fresistance(self): """Get 4-wire resistance.""" self.budget.set_slack(self) self.inst.write(':SENS:FUNC "FRES"') value = self.inst.query(':READ?') logger.measure("{!r} fresistance == {}".format(self.instName, float(value))) return float(value) @property def period(self): """Get period, set (threshold,aperture).""" self.budget.set_slack(self, self.per_aperture) self.inst.write(':SENS:FUNC "PER"') value = self.inst.query(':READ?') logger.measure("{!r} period == {}".format(self.instName, float(value))) self.budget.set_slack(self) return float(value) @period.setter def period(self, threshold_aperture): self.per_threshold, self.per_aperture = threshold_aperture self.budget.set_slack(self) self.inst.write(':SENS:PER:THR:VOLT:RANG {}'.format(self.per_threshold)) self.inst.write(':SENS:PER:APER {}'.format(self.per_aperture)) @property def frequency(self): """Get frequency, set (threshold,aperture).""" self.budget.set_slack(self, self.freq_aperture) self.inst.write(':SENS:FUNC "FREQ"') value = self.inst.query(':READ?') logger.measure("{!r} frequency == {}".format(self.instName, float(value))) self.budget.set_slack(self) return float(value) @frequency.setter def frequency(self, threshold_aperture): self.freq_threshold, self.freq_aperture = threshold_aperture self.budget.set_slack(self) self.inst.write(':SENS:FREQ:THR:VOLT:RANG {}'.format(self.freq_threshold)) self.inst.write(':SENS:FREQ:APER {}'.format(self.freq_aperture))
[docs] def temporal_tuple(self, threshold, aperture): """ Wrapper for tuple assignment to period & frequency. Parameters ---------- threshold : float Threshold voltage for period or frequency measurement. aperture : float Aperture time for period or frequency measurement. Returns ------- tuple Returns a tuple of (threshold, aperture) for period or frequency measurement. """ return threshold, aperture