Source code for qcodes_contrib_drivers.drivers.Tektronix.Keithley_2700

# Keithley_2700.py driver for Keithley 2700 DMM
#
# Pieter Eendebak <pieter.eendebak@gmail.com>, 2016 (adapt to Qcodes framework)
# Pieter de Groot <pieterdegroot@gmail.com>, 2008
# Martijn Schaafsma <qtlab@mcschaafsma.nl>, 2008
# Reinier Heeres <reinier@heeres.eu>, 2008
#
# Update december 2009:
# Michiel Jol <jelle@michieljol.nl>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import logging
from functools import partial

from qcodes.instrument.visa import VisaInstrument
from qcodes.utils.validators import Strings as StringValidator
from qcodes.utils.validators import Ints as IntsValidator
from qcodes.utils.validators import Numbers as NumbersValidator


# %% Helper functions


[docs] def bool_to_str(val): ''' Function to convert boolean to 'ON' or 'OFF' ''' if val: return "ON" else: return "OFF"
# %% Driver for Keithley_2700
[docs] def parseint(v): logging.debug('parseint: %s -> %d' % (v, int(v))) return int(v)
[docs] def parsebool(v): r = bool(int(v)) logging.debug('parsetobool: %s -> %d' % (v, r)) return r
[docs] def parsestr(v): return v.strip().strip('"')
[docs] class Keithley_2700(VisaInstrument): ''' This is the qcodes driver for the Keithley_2700 Multimeter Usage: Initialize with:: <name> = = Keithley_2700(<name>, address='<GPIB address>', reset=<bool>, change_display=<bool>, change_autozero=<bool>) Status: beta-version. This driver will most likely work for multiple Keithley SourceMeters. This driver does not contain all commands available, but only the ones most commonly used. ''' def __init__(self, name, address, reset=False, **kwargs): super().__init__(name, address, **kwargs) self._modes = ['VOLT:AC', 'VOLT:DC', 'CURR:AC', 'CURR:DC', 'RES', 'FRES', 'TEMP', 'FREQ'] # self._change_display = change_display # self._change_autozero = change_autozero self._averaging_types = ['MOV', 'REP'] self._trigger_sent = False # Add parameters to wrapper self.add_parameter('mode', get_cmd=':CONF?', get_parser=parsestr, set_cmd=':CONF:{}', vals=StringValidator()) self.add_parameter('trigger_count', get_cmd=self._mode_par('INIT', 'CONT'), get_parser=int, set_cmd=self._mode_par_value('INIT', 'CONT', '{}'), vals=IntsValidator(), unit='#') self.add_parameter('trigger_delay', get_cmd=self._mode_par('TRIG', 'DEL'), get_parser=float, set_cmd=self._mode_par_value('TRIG', 'DEL', '{}'), vals=NumbersValidator(min_value=0, max_value=999999.999), unit='s') self.add_parameter('trigger_continuous', get_cmd=self._mode_par('INIT', 'CONT'), get_parser=parsebool, set_cmd=self._mode_par_value('INIT', 'CONT', '{}'), set_parser=bool_to_str) self.add_parameter('display', get_cmd=self._mode_par('DISP', 'ENAB'), get_parser=parsebool, set_cmd=self._mode_par_value('DISP', 'ENAB', '{}'), set_parser=bool_to_str) self.add_parameter('averaging', get_cmd=partial(self._current_mode_get, 'AVER:STAT', parser=parsebool), set_cmd=partial(self._current_mode_set, par='AVER:STAT'), set_parser=bool_to_str) self.add_parameter('digits', get_cmd=partial(self._current_mode_get, 'DIG', parser=int), set_cmd=partial(self._current_mode_set, par='DIG')) self.add_parameter('nplc', get_cmd=partial(self._current_mode_get, 'NPLC', parser=float), set_cmd=partial(self._current_mode_set, par='NPLC', mode=None), unit='APER', docstring=('Get integration time in Number of ' 'PowerLine Cycles.\n' 'To get the integrationtime in seconds, ' 'use get_integrationtime().')) self.add_parameter('range', get_cmd=partial(self._current_mode_get, 'RANG', parser=float), set_cmd=partial(self._current_mode_set, par='RANG'), unit='RANG', docstring=('Sets the measurement range.\n' 'Note that not only a discrete set of ' 'ranges can be set (see the manual for ' 'details).')) self.add_parameter('integrationtime', get_cmd=partial(self._current_mode_get, 'APER', parser=float), set_cmd=partial(self._current_mode_set, par='APER', mode=None), unit='s', vals=NumbersValidator(min_value=2e-4, max_value=1.), docstring=('Get integration time in seconds.\n' 'To get the integrationtime as a Number ' 'of PowerLine Cycles, use get_nplc().')) # add functions self.add_parameter('amplitude', unit='arb.unit', label=name, get_cmd=':DATA:FRESH?', get_parser=float) self.add_parameter('readnext', unit='arb.unit', label=name, get_cmd=':DATA:FRESH?', get_parser=float) if reset: self.reset() else: self.get_all() self.set_defaults() self.connect_message()
[docs] def get_all(self): ''' Reads all relevant parameters from instrument Input: None Output: None ''' logging.info('Get all relevant data from device') for p in ['mode', 'trigger_count', 'trigger_continuous', 'averaging', 'digits', 'nplc', 'integrationtime', 'range', 'display']: logging.debug('get %s' % p) par = getattr(self, p) par.get()
# self.get_trigger_delay() # self.get_trigger_source() # self.get_trigger_timer() # self.get_autozero() # self.get_averaging_window() # self.get_averaging_count() # self.get_averaging_type() # self.get_autorange() def _current_mode_get(self, par, mode=None, parser=None): cmd = self._mode_par(mode, par) r = self.ask(cmd) if parser is not None: r = parser(r) return r def _current_mode_set(self, value, par, mode=None): cmd = self._mode_par_value(mode, par, value) return self.write(cmd) # -------------------------------------- # functions # --------------------------------------
[docs] def set_mode_volt_dc(self): ''' Set mode to DC Voltage Input: None Output: None ''' logging.debug('Set mode to DC Voltage') self.mode.set('VOLT:DC')
[docs] def set_defaults(self): ''' Set to driver defaults: Output=data only Mode=Volt:DC Digits=7 Trigger=Continous Range=10 V NPLC=1 Averaging=off ''' self.write('SYST:PRES') self.write(':FORM:ELEM READ') # Sets the format to only the read out, all options are: # READing = DMM reading, UNITs = Units, # TSTamp = Timestamp, RNUMber = Reading number, # CHANnel = Channel number, LIMits = Limits reading self.set_mode_volt_dc() self.digits.set(7) self.trigger_continuous.set(True) self.range.set(10) self.nplc.set(1) self.averaging.set(False) return
def _determine_mode(self, mode): ''' Return the mode string to use. If mode is None it will return the currently selected mode. ''' logging.debug('Determine mode with mode=%s' % mode) if mode is None: mode = self.mode.get_latest() # _mode(query=False) if mode not in self._modes and mode not in ('INIT', 'TRIG', 'SYST', 'DISP'): logging.warning('Invalid mode %s, assuming current' % mode) mode = self.mode.get_latest() logging.debug('Determine mode: mode=%s' % mode) return mode
[docs] def set_mode(self, mode): ''' Set the mode to the specified value Input: mode (string) : mode to be set. Choose from self._modes Output: None ''' logging.debug('Set mode to %s', mode) if mode in self._modes: string = ':CONF:%s' % mode self._visainstrument.write(string) if mode.startswith('VOLT'): self._change_units('V') elif mode.startswith('CURR'): self._change_units('A') elif mode.startswith('RES'): self._change_units('Ohm') elif mode.startswith('FREQ'): self._change_units('Hz') else: logging.error('invalid mode %s' % mode) # Get all values again because some parameters depend on mode self.get_all()
def _mode_par_value(self, mode, par, val): ''' For internal use only!! Create command string based on current mode Input: mode (string) : The mode to use par (string) : Parameter val (depends) : Value Output: None ''' mode = self._determine_mode(mode) string = ':%s:%s %s' % (mode, par, val) return string def _mode_par(self, mode, par): ''' For internal use only!! Create command string based on current mode Input: mode (string) : The mode to use par (string) : Parameter val (depends) : Value Output: None ''' mode = self._determine_mode(mode) string = ':%s:%s?' % (mode, par, ) return string
[docs] def reset(self): ''' Resets instrument to default values Input: None Output: None ''' logging.debug('Resetting instrument') self._visainstrument.write('*RST') self.get_all()