def __init__( self, parent: VisaInstrument, name: str, ) -> None: super().__init__(parent, name) self.add_parameter( "open", set_cmd=":CORRection:OPEN", docstring="Executes OPEN correction based on all frequency points." ) self.add_parameter( "open_state", get_cmd=":CORRection:OPEN:STATe?", set_cmd=":CORRection:OPEN:STATe {}", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), docstring="Enables or disable OPEN correction" ) self.add_parameter( "short", set_cmd=":CORRection:SHORt", docstring="Executes SHORT correction based on all frequency points." ) self.add_parameter( "short_state", get_cmd=":CORRection:SHORt:STATe?", set_cmd=":CORRection:SHORt:STATe {}", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), docstring="Enables or disable SHORT correction." )
def __init__(self, parent: 'Keithley2460', name: str, proper_function: str) -> None: super().__init__(parent, name) self._proper_function = proper_function range_vals = self.function_modes[self._proper_function]["range_vals"] unit = self.function_modes[self._proper_function]["unit"] self.function = self.parent.sense_function self.add_parameter( "four_wire_measurement", set_cmd=f":SENSe:{self._proper_function}:RSENse {{}}", get_cmd=f":SENSe:{self._proper_function}:RSENse?", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0")) self.add_parameter( "range", set_cmd=f":SENSe:{self._proper_function}:RANGe {{}}", get_cmd=f":SENSe:{self._proper_function}:RANGe?", vals=range_vals, get_parser=float, unit=unit) self.add_parameter( "auto_range", set_cmd=f":SENSe:{self._proper_function}:RANGe:AUTO {{}}", get_cmd=f":SENSe:{self._proper_function}:RANGe:AUTO?", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0")) self.add_parameter(self._proper_function, get_cmd=self._measure, get_parser=float, unit=unit, snapshot_value=False) self.add_parameter("sweep", label=self._proper_function, get_cmd=self._measure_sweep, unit=unit, vals=Arrays(shape=(self.parent.npts, )), parameter_class=ParameterWithSetpoints) self.add_parameter( "nplc", get_cmd=f":SENSe:{self._proper_function}:NPLCycles?", set_cmd=f":SENSe:{self._proper_function}:NPLCycles {{}}", vals=Numbers(0.001, 10)) self.add_parameter('user_number', get_cmd=None, set_cmd=None, vals=Ints(1, 5)) self.add_parameter("user_delay", get_cmd=self._get_user_delay, set_cmd=self._set_user_delay, vals=Numbers(0, 1e4))
def __init__(self, name: str, address: str, terminator: str = '\n', **kwargs) -> None: """ Args: name: Name to use internally in QCoDeS address: VISA resource address """ super().__init__(name, address, terminator=terminator, **kwargs) self.add_parameter('channel_connect_rule', get_cmd=self._get_channel_connect_rule, set_cmd=self._set_channel_connect_rule, docstring=textwrap.dedent("""\ Controls the connection rule for closing and opening channels when using `exclusive_close` and `exclusive_slot_close` parameters. If it is set to break before make, it is ensured that all channels open before any channels close. If it is set to make before break, it is ensured that all channels close before any channels open. If it is off, channels open and close simultaneously."""), vals=vals.Enum('BREAK_BEFORE_MAKE', 'MAKE_BEFORE_BREAK', 'OFF')) self.add_parameter('gpib_enabled', get_cmd=self._get_gpib_status, set_cmd=self._set_gpib_status, docstring='Enables or disables GPIB connection.', val_mapping=create_on_off_val_mapping( on_val='true', off_val='false')) self.add_parameter('gpib_address', get_cmd=self._get_gpib_address, get_parser=int, set_cmd=self._set_gpib_address, docstring='Sets and gets the GPIB address.', vals=vals.Ints(1, 30)) self.add_parameter('lan_enabled', get_cmd=self._get_lan_status, set_cmd=self._set_lan_status, docstring='Enables or disables LAN connection.', val_mapping=create_on_off_val_mapping( on_val='true', off_val='false')) self.connect_message()
def test_create_on_off_val_mapping_for(on_val, off_val): """ Explicitly test ``create_on_off_val_mapping`` function by covering some of the edge cases of ``on_val`` and ``off_val`` """ val_mapping = create_on_off_val_mapping(on_val=on_val, off_val=off_val) values_list = list(set(val_mapping.values())) assert len(values_list) == 2 assert on_val in values_list assert off_val in values_list assert val_mapping[1] is on_val assert val_mapping[True] is on_val assert val_mapping['1'] is on_val assert val_mapping['ON'] is on_val assert val_mapping['On'] is on_val assert val_mapping['on'] is on_val assert val_mapping[0] is off_val assert val_mapping[False] is off_val assert val_mapping['0'] is off_val assert val_mapping['OFF'] is off_val assert val_mapping['Off'] is off_val assert val_mapping['off'] is off_val from qcodes.instrument.parameter import invert_val_mapping inverse = invert_val_mapping(val_mapping) assert inverse[on_val] is True assert inverse[off_val] is False
def test_on_off_val_mapping(self): instrument_value_for_on = 'on_' instrument_value_for_off = 'off_' parameter_return_value_for_on = True parameter_return_value_for_off = False p = Parameter('p', set_cmd=self.set_p, get_cmd=self.get_p, val_mapping=create_on_off_val_mapping( on_val=instrument_value_for_on, off_val=instrument_value_for_off)) test_data = [(instrument_value_for_on, parameter_return_value_for_on, ('On', 'on', 'ON', 1, True)), (instrument_value_for_off, parameter_return_value_for_off, ('Off', 'off', 'OFF', 0, False))] for instr_value, parameter_return_value, inputs in test_data: for inp in inputs: # Setting parameter with any of the `inputs` is allowed p(inp) # For any value from the `inputs`, what gets send to the # instrument is on_val/off_val which are specified in # `create_on_off_val_mapping` self.assertEqual(self._p, instr_value) # When getting a value of the parameter, only specific # values are returned instead of `inputs` self.assertEqual(p(), parameter_return_value)
def __init__(self, name, address, **kwargs): super().__init__(name, address, terminator="\r\n", **kwargs) self.by_slot = {} self.by_channel = {} self.by_kind = defaultdict(list) self._find_modules() self.add_parameter('autozero_enabled', unit='', label='Autozero enabled of the high-resolution ADC', set_cmd=self._set_autozero, get_cmd=None, val_mapping=create_on_off_val_mapping( on_val=True, off_val=False), docstring=textwrap.dedent(""" Enable or disable cancelling of the offset of the high-resolution A/D converter (ADC). Set the function to OFF in cases that the measurement speed is more important than the measurement accuracy. This roughly halves the integration time.""")) # Instrument is initialized with this setting having value of # `False`, hence let's set the parameter to this value since it is # not possible to request this value from the instrument. self.autozero_enabled.cache.set(False) self.connect_message()
def test_its_inverse_maps_only_to_booleans(self): from qcodes.instrument.parameter import invert_val_mapping inverse = invert_val_mapping( create_on_off_val_mapping(on_val='666', off_val='000')) self.assertDictEqual(inverse, {'666': True, '000': False})
def __init__(self, name: str, address: str, **kwargs: Any) -> None: super().__init__(name, address, terminator='\n', **kwargs) self._min_freq: float self._max_freq: float self._additional_wait: float = 1 self.add_parameter( name="mode", get_cmd=":INSTrument:SELect?", set_cmd=":INSTrument:SELect {}", vals=Enum(*self._available_modes()), docstring="Allows setting of different modes present and licensed " "for the instrument.") self.add_parameter( name="measurement", get_cmd=":CONFigure?", set_cmd=":CONFigure:{}", vals=Enum("SAN", "LPL"), docstring="Sets measurement type from among the available " "measurement types.") self.add_parameter( name="cont_meas", initial_value=False, get_cmd=":INITiate:CONTinuous?", set_cmd=self._enable_cont_meas, val_mapping=create_on_off_val_mapping(on_val="ON", off_val="OFF"), docstring="Enables or disables continuous measurement.") self.add_parameter(name="format", get_cmd=":FORMat:TRACe:DATA?", set_cmd=":FORMat:TRACe:DATA {}", val_mapping={ "ascii": "ASCii", "int32": "INTeger,32", "real32": "REAL,32", "real64": "REAL,64" }, docstring="Sets up format of data received") if "SA" in self._available_modes(): sa_mode = SpectrumAnalyzerMode(self, name="sa") self.add_submodule("sa", sa_mode) else: self.log.info("Spectrum Analyzer mode is not available on this " "instrument.") if "PNOISE" in self._available_modes(): pnoise_mode = PhaseNoiseMode(self, name="pn") self.add_submodule("pn", pnoise_mode) else: self.log.info("Phase Noise mode is not available on this " "instrument.") self.connect_message()
def __init__(self, parent: 'Keithley2450', name: str, proper_function: str) -> None: super().__init__(parent, name) self._proper_function = proper_function range_vals = self.function_modes[self._proper_function]["range_vals"] unit = self.function_modes[self._proper_function]["unit"] self.function = self.parent.source_function self._sweep_arguments: Dict[str, Union[float, int, str]] = {} self.add_parameter( "range", set_cmd=f":SOUR:{self._proper_function}:RANGe {{}}", get_cmd=f":SOUR:{self._proper_function}:RANGe?", vals=range_vals, get_parser=float, unit=unit ) self.add_parameter( "auto_range", set_cmd=f":SOURce:{self._proper_function}:RANGe:AUTO {{}}", get_cmd=f":SOURce:{self._proper_function}:RANGe:AUTO?", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0") ) limit_cmd = {"current": "VLIM", "voltage": "ILIM"}[self._proper_function] self.add_parameter( "limit", set_cmd=f"SOUR:{self._proper_function}:{limit_cmd} {{}}", get_cmd=f"SOUR:{self._proper_function}:{limit_cmd}?", get_parser=float, unit=unit ) self.add_parameter( "limit_tripped", get_cmd=f":SOUR:{self._proper_function}:{limit_cmd}:TRIPped?", val_mapping={True: 1, False: 0} ) self.add_parameter( self._proper_function, set_cmd=f"SOUR:{self._proper_function} {{}}", get_cmd=f"SOUR:{self._proper_function}?", get_parser=float, unit=unit, snapshot_value=False ) self.add_parameter( "sweep_axis", label=self._proper_function, get_cmd=self.get_sweep_axis, vals=Arrays(shape=(self.parent.npts,)), unit=unit )
def __init__(self, name: str, address: str, **kwargs) -> None: super().__init__(name, address, terminator='\n', **kwargs) if not self._has_correct_language_mode(): self.log.warning( f"The instrument is in an unsupported language mode. " f"Please run `instrument.set_correct_language()` and try to " f"initialize the driver again after an instrument power cycle. " f"No parameters/sub modules will be available on this driver " f"instance") return self.add_parameter( "source_function", set_cmd=self._set_source_function, get_cmd=":SOUR:FUNC?", val_mapping={ key: value["name"] for key, value in Source2450.function_modes.items() }) self.add_parameter( "sense_function", set_cmd=self._set_sense_function, get_cmd=":SENS:FUNC?", val_mapping={ key: value["name"] for key, value in Sense2450.function_modes.items() }) self.add_parameter("terminals", set_cmd="ROUTe:TERMinals {}", get_cmd="ROUTe:TERMinals?", vals=Enum("rear", "front")) self.add_parameter("output_enabled", initial_value="0", set_cmd=":OUTP {}", get_cmd=":OUTP?", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0")) # Make a source module for every source function ('current' and 'voltage') for proper_source_function in Source2450.function_modes: self.add_submodule( f"_source_{proper_source_function}", Source2450(self, "source", proper_source_function)) # Make a sense module for every sense function ('current', voltage' and 'resistance') for proper_sense_function in Sense2450.function_modes: self.add_submodule(f"_sense_{proper_sense_function}", Sense2450(self, "sense", proper_sense_function)) self.connect_message()
def __init__(self, name, address, **kwargs): super().__init__(name, address, terminator="\r\n", **kwargs) # self._MODES = { # 'dc_volts': 1, # 'dc_current': 5, # } self._VOLT_RANGES = { '10mV': 2, '100mV': 3, '1V': 4, '10V': 5, '100V': 6, } self._CURR_RANGES = { '1mA': 4, '10mA': 5, '100mA': 6, } self._ranges = list(self._VOLT_RANGES.keys()) + list( self._CURR_RANGES.keys()) # self.add_parameter( # 'mode', # get_cmd=self._get_mode, # set_cmd=self._set_mode, # val_mapping=self._MODES, # docstring='Selects the input mode' # ) self.add_parameter('range', get_cmd=self._get_range, set_cmd=self._set_range, vals=vals.Enum(*self._ranges), 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('output', get_cmd=self._get_output, set_cmd=self._set_output, val_mapping=create_on_off_val_mapping(on_val=1, off_val=0)) self.add_parameter( 'source', set_cmd=self._set_value, get_cmd=self._get_value, )
def __init__(self, *args, virtual=False, frequency_option="513", **kwargs): """Constructor. Arguments: virtual: Set it to True for virtual (mocked) device. frequency_option: Useful only if ``virtual=True``, this corresponds to the model variant (possible values: see :attr:`FREQUENCY_OPTIONS`). args, kwargs: Same arguments as the parent class, see :class:`qcodes.instrument_drivers.agilent.E8527D.Agilent_E8527D`. """ self.virtual = virtual # Sanity checks if self.virtual and kwargs.get("visalib", None) is not None: raise ValueError("The visalib should not be changed for the " "virtual E8527D.") if frequency_option not in self.FREQUENCY_OPTIONS: raise ValueError(f"Invalid parameter '{frequency_option=}'. " f"Possible values: {self.FREQUENCY_OPTIONS}.") if self.virtual: kwargs["visalib"] = "@sim" # Store dummy (string) values for virtual instrument self._virtual_parameters = { "DIAG:CPU:INFO:OPT:DET": frequency_option, "FREQ:CW": "250000", "PHASE": "0.0", "POW:AMPL": "-20.0", "OUTP": "0", "OUTP:MOD": "0", } super().__init__(*args, **kwargs) # Allow powers up to 25 dBm self._max_power = 25 self.power.vals = vals.Numbers(self._min_power, self._max_power) # Add parameter pulsemod_state self.add_parameter( "pulsemod_state", label="Pulse Modulation", get_cmd=":OUTP:MOD?", set_cmd="OUTP:MOD {}", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0") )
def __init__( self, parent: Instrument, name: str, measurement_number: int ) -> None: super().__init__(parent, name) self._measurement_number = measurement_number self._adjustment_time = time.perf_counter() self.add_parameter( "state", get_cmd=f"MEASUrement:MEAS{self._measurement_number}:STATe?", set_cmd=f"MEASUrement:MEAS{self._measurement_number}:STATe {{}}", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0") ) self.add_parameter( "type", get_cmd=f"MEASUrement:MEAS{self._measurement_number}:TYPe?", set_cmd=self._set_measurement_type, get_parser=str.lower, vals=Enum(*[m[0] for m in self.measurements]), docstring=textwrap.dedent( "Please see page 566-569 of the programmers manual " "for a detailed description of these arguments. " "http://download.tek.com/manual/077001022.pdf" ) ) for measurement, unit in self.measurements: self.add_parameter( name=measurement, unit=unit, parameter_class=TektronixDPOMeasurementParameter ) for src in [1, 2]: self.add_parameter( f"source{src}", get_cmd=f"MEASUrement:MEAS{self._measurement_number}:SOUrce" f"{src}?", set_cmd=partial(self._set_source, src), vals=Enum( *(TekronixDPOWaveform.valid_identifiers + ["HISTogram"]) ) )
def __init__(self, parent: Instrument, name: str, channel: str): super().__init__(parent, name) # validate the channel id PowerChannel.CHANNEL_NAMES.validate(channel) self._id_name = channel self._id_number = PowerChannel.CHANNEL_IDS[channel] # add parameters self.add_parameter('power_enabled', get_cmd=self._get_power_enabled, set_cmd=self._set_power_enabled, get_parser=int, val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), label='Power {}'.format(self._id_name))
def test_with_default_arguments(self): """ Due to the fact that `hash(True) == hash(1)`/`hash(False) == hash( 0)`, in this case of `on_val is True`/`off_val is False` the values of `1`/`0` are not added to the `val_mapping`. But this test only ensures that the inverted value mapping is equivalent to "passing boolean values through". """ val_mapping = create_on_off_val_mapping() values_set = set(list(val_mapping.values())) self.assertEqual(values_set, {True, False}) from qcodes.instrument.parameter import invert_val_mapping inverse = invert_val_mapping(val_mapping) assert inverse[True] is True assert inverse[False] is False
def __init__(self, name: str, address: str, **kwargs: Any): super().__init__(name, address, terminator="\r\n", **kwargs) self.by_slot: Dict[constants.SlotNr, B1500Module] = {} self.by_channel: Dict[constants.ChNr, B1500Module] = {} self.by_kind: Dict[constants.ModuleKind, List[B1500Module]] = defaultdict(list) self._find_modules() self.add_parameter('autozero_enabled', unit='', label='Autozero enabled of the high-resolution ADC', set_cmd=self._set_autozero, get_cmd=None, val_mapping=create_on_off_val_mapping( on_val=True, off_val=False), initial_cache_value=False, docstring=textwrap.dedent(""" Enable or disable cancelling of the offset of the high-resolution A/D converter (ADC). Set the function to OFF in cases that the measurement speed is more important than the measurement accuracy. This roughly halves the integration time.""")) self.add_parameter(name='run_iv_staircase_sweep', parameter_class=IVSweepMeasurement, docstring=textwrap.dedent(""" This is MultiParameter. Running the sweep runs the measurement on the list of source values defined using `setup_staircase_sweep` method. The output is a primary parameter (e.g. Gate current) and a secondary parameter (e.g. Source/Drain current) both of which use the same setpoints. Note you must `set_measurement_mode` and specify 2 channels as the argument before running the sweep. First channel (SMU) must be the channel on which you set the sweep ( WV) and second channel(SMU) must be the one which remains at constants voltage. """)) self.connect_message()
def __init__(self, name: str, address: str, step_attenuator: bool = False, **kwargs) -> None: super().__init__(name, address, **kwargs) self.add_parameter(name='frequency', label='Frequency', unit='Hz', get_cmd='FREQ:CW?', set_cmd='FREQ:CW' + ' {:.4f}', get_parser=float, set_parser=float, vals=vals.Numbers(1e5, 20e9)) self.add_parameter(name='phase', label='Phase', unit='deg', get_cmd='PHASE?', set_cmd='PHASE' + ' {:.8f}', get_parser=self.rad_to_deg, set_parser=self.deg_to_rad, vals=vals.Numbers(-180, 180)) min_power = -135 if step_attenuator else -20 self.add_parameter(name='power', label='Power', unit='dBm', get_cmd='POW:AMPL?', set_cmd='POW:AMPL' + ' {:.4f}', get_parser=float, set_parser=float, vals=vals.Numbers(min_power, 16)) self.add_parameter('status', get_cmd=':OUTP?', set_cmd='OUTP {}', val_mapping=create_on_off_val_mapping(on_val='1', off_val='0')) self.connect_message()
def __init__(self, name, address, baud_rate=115200, **kwargs): super().__init__(name, address, **kwargs) # set baud rate self.visa_handle.baud_rate = baud_rate # get instrument information self.model, _, self.firmware_version = self._query_versions() # add parameters self.add_parameter('power', get_cmd='*CVU', get_parser=float, label='Power', unit='W') def wavelength_get_parser(ans): return int(ans[4:]) self.add_parameter('wavelength', get_cmd='*GWL', set_cmd='*PWC{0:0>5}', get_parser=wavelength_get_parser, label='Wavelength', unit='nm') def zero_offset_get_parser(ans): return int(ans[5:]) self.add_parameter('zero_offset_enabled', get_cmd='*GZO', get_parser=zero_offset_get_parser, val_mapping=create_on_off_val_mapping(on_val=1, off_val=0), label='Zero offset enabled') # print connect message self.connect_message()
def __init__(self, name: str, address: str, **kwargs: Any) -> None: super().__init__(name, address, terminator='\n', **kwargs) self.add_parameter(name='frequency', label='Frequency', unit='Hz', get_cmd='SOUR:FREQ?', set_cmd='SOUR:FREQ {:.2f}', get_parser=float, vals=vals.Numbers(1e6, 20e9)) self.add_parameter(name='phase', label='Phase', unit='deg', get_cmd='SOUR:PHAS?', set_cmd='SOUR:PHAS {:.2f}', get_parser=float, vals=vals.Numbers(0, 360)) self.add_parameter(name='power', label='Power', unit='dBm', get_cmd='SOUR:POW?', set_cmd='SOUR:POW {:.2f}', get_parser=float, vals=vals.Numbers(-120, 25)) self.add_parameter('status', label='RF Output', get_cmd=':OUTP:STAT?', set_cmd=':OUTP:STAT {}', val_mapping=create_on_off_val_mapping(on_val='1', off_val='0')) self.add_parameter('IQ_state', label='IQ Modulation', get_cmd=':IQ:STAT?', set_cmd=':IQ:STAT {}', val_mapping=create_on_off_val_mapping(on_val='1', off_val='0')) self.add_parameter('pulsemod_state', label='Pulse Modulation', get_cmd=':SOUR:PULM:STAT?', set_cmd=':SOUR:PULM:STAT {}', val_mapping=create_on_off_val_mapping(on_val='1', off_val='0')) self.add_parameter('pulsemod_source', label='Pulse Modulation Source', get_cmd='SOUR:PULM:SOUR?', set_cmd='SOUR:PULM:SOUR {}', vals=vals.Enum('INT', 'EXT', 'int', 'ext')) self.add_parameter('ref_osc_source', label='Reference Oscillator Source', get_cmd='SOUR:ROSC:SOUR?', set_cmd='SOUR:ROSC:SOUR {}', vals=vals.Enum('INT', 'EXT', 'int', 'ext')) # Define LO source INT/EXT (Only with K-90 option) self.add_parameter('LO_source', label='Local Oscillator Source', get_cmd='SOUR:LOSC:SOUR?', set_cmd='SOUR:LOSC:SOUR {}', vals=vals.Enum('INT', 'EXT', 'int', 'ext')) # Define output at REF/LO Output (Only with K-90 option) self.add_parameter('ref_LO_out', label='REF/LO Output', get_cmd='CONN:REFL:OUTP?', set_cmd='CONN:REFL:OUTP {}', vals=vals.Enum('REF', 'LO', 'OFF', 'ref', 'lo', 'off', 'Off')) # Frequency mw_source outputs when used as a reference self.add_parameter('ref_osc_output_freq', label='Reference Oscillator Output Frequency', get_cmd='SOUR:ROSC:OUTP:FREQ?', set_cmd='SOUR:ROSC:OUTP:FREQ {}', vals=vals.Enum('10MHz', '100MHz', '1000MHz')) # Frequency of the external reference mw_source uses self.add_parameter('ref_osc_external_freq', label='Reference Oscillator External Frequency', get_cmd='SOUR:ROSC:EXT:FREQ?', set_cmd='SOUR:ROSC:EXT:FREQ {}', vals=vals.Enum('10MHz', '100MHz', '1000MHz')) # IQ impairments self.add_parameter('IQ_impairments', label='IQ Impairments', get_cmd=':SOUR:IQ:IMP:STAT?', set_cmd=':SOUR:IQ:IMP:STAT {}', val_mapping=create_on_off_val_mapping(on_val='1', off_val='0')) self.add_parameter('I_offset', label='I Offset', get_cmd='SOUR:IQ:IMP:LEAK:I?', set_cmd='SOUR:IQ:IMP:LEAK:I {:.2f}', get_parser=float, vals=vals.Numbers(-10, 10)) self.add_parameter('Q_offset', label='Q Offset', get_cmd='SOUR:IQ:IMP:LEAK:Q?', set_cmd='SOUR:IQ:IMP:LEAK:Q {:.2f}', get_parser=float, vals=vals.Numbers(-10, 10)) self.add_parameter('IQ_gain_imbalance', label='IQ Gain Imbalance', get_cmd='SOUR:IQ:IMP:IQR?', set_cmd='SOUR:IQ:IMP:IQR {:.2f}', get_parser=float, vals=vals.Numbers(-1, 1)) self.add_parameter('IQ_angle', label='IQ Angle Offset', get_cmd='SOUR:IQ:IMP:QUAD?', set_cmd='SOUR:IQ:IMP:QUAD {:.2f}', get_parser=float, vals=vals.Numbers(-8, 8)) self.add_function('reset', call_cmd='*RST') self.add_function('run_self_tests', call_cmd='*TST?') self.connect_message()
def __init__( self, parent: VisaInstrument, name: str, proper_function: str ) -> None: super().__init__(parent, name) self._proper_function = proper_function range_vals = self.function_modes[self._proper_function]["range_vals"] unit = self.function_modes[self._proper_function]["unit"] self.function = self.parent.sense_function self.add_parameter( self._proper_function, get_cmd=self._measure, get_parser=float, unit=unit, docstring="Make measurements, place them in a reading buffer, and " "return the last reading." ) self.add_parameter( "auto_range", get_cmd=f":SENSe:{self._proper_function}:RANGe:AUTO?", set_cmd=f":SENSe:{self._proper_function}:RANGe:AUTO {{}}", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), docstring="Determine if the measurement range is set manually or " "automatically for the selected measure function." ) self.add_parameter( "range", get_cmd=f":SENSe:{self._proper_function}:RANGe?", set_cmd=f":SENSe:{self._proper_function}:RANGe {{}}", vals=range_vals, get_parser=float, unit=unit, docstring="Determine the positive full-scale measure range." ) self.add_parameter( "nplc", get_cmd=f":SENSe:{self._proper_function}:NPLCycles?", set_cmd=f":SENSe:{self._proper_function}:NPLCycles {{}}", vals=Numbers(0.01, 10), get_parser=float, docstring="Set the time that the input signal is measured for the " "selected function.(NPLC = number of power line cycles)" ) self.add_parameter( "auto_delay", get_cmd=f":SENSe:{self._proper_function}:DELay:AUTO?", set_cmd=f":SENSe:{self._proper_function}:DELay:AUTO {{}}", val_mapping=create_on_off_val_mapping(on_val="ON", off_val="OFF"), docstring="Enable or disable the automatic delay that occurs " "before each measurement." ) self.add_parameter( 'user_number', get_cmd=None, set_cmd=None, vals=Ints(1, 5), docstring="Set the user number for user-defined delay." ) self.add_parameter( "user_delay", get_cmd=self._get_user_delay, set_cmd=self._set_user_delay, vals=Numbers(0, 1e4), unit='second', docstring="Set a user-defined delay that you can use in the " "trigger model." ) self.add_parameter( "auto_zero", get_cmd=f":SENSe:{self._proper_function}:AZERo?", set_cmd=f":SENSe:{self._proper_function}:AZERo {{}}", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), docstring="Enable or disable automatic updates to the internal " "reference measurements (autozero) of the instrument." ) self.add_parameter( "auto_zero_once", set_cmd=f":SENSe:AZERo:ONCE", docstring="Cause the instrument to refresh the reference and " "zero measurements once" ) self.add_parameter( "average", get_cmd=f":SENSe:{self._proper_function}:AVERage?", set_cmd=f":SENSe:{self._proper_function}:AVERage {{}}", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), docstring="Enable or disable the averaging filter for measurements " "of the selected function." ) self.add_parameter( "average_count", get_cmd=f":SENSe:{self._proper_function}:AVERage:COUNt?", set_cmd=f":SENSe:{self._proper_function}:AVERage:COUNt {{}}", vals=Numbers(1, 100), docstring="Set the number of measurements that are averaged when " "filtering is enabled." ) self.add_parameter( "average_type", get_cmd=f":SENSe:{self._proper_function}:AVERage:TCONtrol?", set_cmd=f":SENSe:{self._proper_function}:AVERage:TCONtrol {{}}", vals=Enum('REP', 'rep', 'MOV', 'mov'), docstring="Set the type of averaging filter that is used for the " "selected measure function when the measurement filter " "is enabled." )
def __init__(self, parent: "N9030B", name: str, *arg: Any, **kwargs: Any): super().__init__(parent, name, *arg, **kwargs) self._min_freq = -8e7 self._valid_max_freq: Dict[str, float] = { "503": 3.7e9, "508": 8.5e9, "513": 13.8e9, "526": 27e9, "544": 44.5e9 } opt: str for hw_opt_for_max_freq in self._valid_max_freq.keys(): if hw_opt_for_max_freq in self.root_instrument._options(): opt = hw_opt_for_max_freq self._max_freq = self._valid_max_freq[opt] self.add_parameter(name="start", unit="Hz", get_cmd=":SENSe:FREQuency:STARt?", set_cmd=self._set_start, get_parser=float, vals=Numbers(self._min_freq, self._max_freq - 10), docstring="start frequency for the sweep") self.add_parameter(name="stop", unit="Hz", get_cmd=":SENSe:FREQuency:STOP?", set_cmd=self._set_stop, get_parser=float, vals=Numbers(self._min_freq + 10, self._max_freq), docstring="stop frequency for the sweep") self.add_parameter(name="center", unit="Hz", get_cmd=":SENSe:FREQuency:CENTer?", set_cmd=self._set_center, get_parser=float, vals=Numbers(self._min_freq + 5, self._max_freq - 5), docstring="Sets and gets center frequency") self.add_parameter(name="span", unit="Hz", get_cmd=":SENSe:FREQuency:SPAN?", set_cmd=self._set_span, get_parser=float, vals=Numbers(10, self._max_freq - self._min_freq), docstring="Changes span of frequency") self.add_parameter(name="npts", get_cmd=":SENSe:SWEep:POINts?", set_cmd=self._set_npts, get_parser=int, vals=Ints(1, 20001), docstring="Number of points for the sweep") self.add_parameter(name="sweep_time", label="Sweep time", get_cmd=":SENSe:SWEep:TIME?", set_cmd=":SENSe:SWEep:TIME {}", get_parser=float, unit="s", docstring="gets sweep time") self.add_parameter(name="auto_sweep_time_enabled", get_cmd=":SENSe:SWEep:TIME:AUTO?", set_cmd=self._enable_auto_sweep_time, val_mapping=create_on_off_val_mapping( on_val="ON", off_val="OFF"), docstring="enables auto sweep time") self.add_parameter(name="auto_sweep_type_enabled", get_cmd=":SENSe:SWEep:TYPE:AUTO?", set_cmd=self._enable_auto_sweep_type, val_mapping=create_on_off_val_mapping( on_val="ON", off_val="OFF"), docstring="enables auto sweep type") self.add_parameter( name="sweep_type", get_cmd=":SENSe:SWEep:TYPE?", set_cmd=self._set_sweep_type, val_mapping={ "fft": "FFT", "sweep": "SWE", }, docstring="Sets up sweep type. Possible options are 'fft' and " "'sweep'.") self.add_parameter( name="freq_axis", label="Frequency", unit="Hz", start=self.start, stop=self.stop, npts=self.npts, vals=Arrays(shape=(self.npts.get_latest, )), parameter_class=FrequencyAxis, docstring="Creates frequency axis for the sweep from start, " "stop and npts values.") self.add_parameter(name="trace", label="Trace", unit="dB", number=1, vals=Arrays(shape=(self.npts.get_latest, )), setpoints=(self.freq_axis, ), parameter_class=Trace, docstring="Gets trace data.")
def __init__(self, parent: "N9030B", name: str, *arg: Any, **kwargs: Any): super().__init__(parent, name, *arg, **kwargs) self._min_freq = 1 self._valid_max_freq: Dict[str, float] = { "503": 3699999995, "508": 8499999995, "513": 13799999995, "526": 26999999995, "544": 44499999995 } opt: str for hw_opt_for_max_freq in self._valid_max_freq.keys(): if hw_opt_for_max_freq in self.root_instrument._options(): opt = hw_opt_for_max_freq self._max_freq = self._valid_max_freq[opt] self.add_parameter(name="npts", get_cmd=":SENSe:LPLot:SWEep:POINts?", set_cmd=":SENSe:LPLot:SWEep:POINts {}", get_parser=int, vals=Ints(601, 20001), docstring="Number of points for the sweep") self.add_parameter(name="start_offset", unit="Hz", get_cmd=":SENSe:LPLot:FREQuency:OFFSet:STARt?", set_cmd=self._set_start_offset, get_parser=float, vals=Numbers(self._min_freq, self._max_freq - 10), docstring="start frequency offset for the plot") self.add_parameter(name="stop_offset", unit="Hz", get_cmd=":SENSe:LPLot:FREQuency:OFFSet:STOP?", set_cmd=self._set_stop_offset, get_parser=float, vals=Numbers(self._min_freq + 99, self._max_freq), docstring="stop frequency offset for the plot") self.add_parameter( name="signal_tracking_enabled", get_cmd=":SENSe:FREQuency:CARRier:TRACk?", set_cmd=":SENSe:FREQuency:CARRier:TRACk {}", val_mapping=create_on_off_val_mapping(on_val="ON", off_val="OFF"), docstring="Gets/Sets signal tracking. When signal tracking is " "enabled carrier signal is repeatedly realigned. Signal " "Tracking assumes the new acquisition occurs repeatedly " "without pause.") self.add_parameter( name="freq_axis", label="Frequency", unit="Hz", start=self.start_offset, stop=self.stop_offset, npts=self.npts, vals=Arrays(shape=(self.npts.get_latest, )), parameter_class=FrequencyAxis, docstring="Creates frequency axis for the sweep from " "start_offset, stop_offset and npts values.") self.add_parameter(name="trace", label="Trace", unit="dB", number=3, vals=Arrays(shape=(self.npts.get_latest, )), setpoints=(self.freq_axis, ), parameter_class=Trace, docstring="Gets trace data.")
def __init__(self, name: str, address: str, **kwargs: Any): super().__init__(name, address, terminator='\n', **kwargs) self.add_parameter('rangev', get_cmd='SENS:VOLT:RANG?', get_parser=float, set_cmd='SOUR:VOLT:RANG {:f}', label='Voltage range') self.add_parameter('rangei', get_cmd='SENS:CURR:RANG?', get_parser=float, set_cmd='SOUR:CURR:RANG {:f}', label='Current range') self.add_parameter('compliancev', get_cmd='SENS:VOLT:PROT?', get_parser=float, set_cmd='SENS:VOLT:PROT {:f}', label='Voltage Compliance') self.add_parameter('compliancei', get_cmd='SENS:CURR:PROT?', get_parser=float, set_cmd='SENS:CURR:PROT {:f}', label='Current Compliance') self.add_parameter('volt', get_cmd=self._get_read_output_protected, get_parser=self._volt_parser, set_cmd=':SOUR:VOLT:LEV {:.8f}', label='Voltage', unit='V', docstring="Sets voltage in 'VOLT' mode. " "Get returns measured voltage if " "sensing 'VOLT' otherwise it returns " "setpoint value. " "Note that it is an error to read voltage with " "output off") self.add_parameter('ramp_voltage', get_cmd=self._get_read_output_protected, get_parser=self._volt_parser, set_cmd=self.ramp_voltage_to, label='Voltage', unit='V') self.add_parameter( 'ramp_voltage_step', label='Step size for ramp_voltage', unit='V', initial_value=10e-3, get_cmd=None, set_cmd=None, ) self.add_parameter( 'ramp_voltage_delay', label='Delay for ramp_voltage', unit='s', initial_value=0, get_cmd=None, set_cmd=None, ) self.add_parameter('curr', get_cmd=self._get_read_output_protected, get_parser=self._curr_parser, set_cmd=':SOUR:CURR:LEV {:.8f}', label='Current', unit='A', docstring="Sets current in 'CURR' mode. " "Get returns measured current if " "sensing 'CURR' otherwise it returns " "setpoint value. " "Note that it is an error to read current with " "output off") self.add_parameter('mode', vals=Enum('VOLT', 'CURR'), get_cmd=':SOUR:FUNC?', set_cmd=self._set_mode_and_sense, label='Mode') self.add_parameter('sense', vals=Strings(), get_cmd=':SENS:FUNC?', set_cmd=':SENS:FUNC "{:s}"', label='Sense mode') self.add_parameter('output', set_cmd=':OUTP:STAT {}', get_cmd=':OUTP:STAT?', val_mapping=create_on_off_val_mapping(on_val="1", off_val="0")) self.add_parameter('nplcv', get_cmd='SENS:VOLT:NPLC?', get_parser=float, set_cmd='SENS:VOLT:NPLC {:f}', label='Voltage integration time') self.add_parameter('nplci', get_cmd='SENS:CURR:NPLC?', get_parser=float, set_cmd='SENS:CURR:NPLC {:f}', label='Current integration time') self.add_parameter( 'resistance', get_cmd=self._get_read_output_protected, get_parser=self._resistance_parser, label='Resistance', unit='Ohm', docstring="Measure resistance from current and voltage " "Note that it is an error to read current " "and voltage with output off") self.write(':TRIG:COUN 1;:FORM:ELEM VOLT,CURR') # This line sends 2 commands to the instrument: # ":TRIG:COUN 1" sets the trigger count to 1 so that each READ? returns # only 1 measurement result. # ":FORM:ELEM VOLT,CURR" sets the output string formatting of the the # Keithley 2400 to return "{voltage}, {current}". # Default value on instrument reset is "VOLT, CURR, RES, TIME, STATUS"; # however, resistance, status, and time are unused in this driver and # so are omitted. # These commands do not reset the instrument but do the minimal amount # to ensure that voltage and current parameters can be read from the # instrument, in the event that output formatting of the instrument was # previously changed to some other unknown state. self.connect_message()
def __init__(self, name, address, step_attenuator=False, **kwargs): super().__init__(name, address, **kwargs) # Only listed most common spellings idealy want a # .upper val for Enum or string on_off_validator = vals.Enum('on', 'On', 'ON', 'off', 'Off', 'OFF') on_off_mapping = create_on_off_val_mapping(1, 0) self.add_parameter(name='frequency', label='Frequency', unit='Hz', get_cmd='FREQ:CW?', set_cmd='FREQ:CW' + ' {:.4f}', get_parser=float, set_parser=float, vals=vals.Numbers(1e5, 20e9), docstring='Adjust the RF output frequency') self.add_parameter(name='frequency_offset', label='Frequency offset', unit='Hz', get_cmd='FREQ:OFFS?', set_cmd='FREQ:OFFS {}', get_parser=float, vals=Numbers(min_value=-200e9, max_value=200e9)) self.add_parameter('frequency_mode', label='Frequency mode', set_cmd='FREQ:MODE {}', get_cmd='FREQ:MODE?', get_parser=lambda s: s.strip(), vals=vals.Enum('FIX', 'CW', 'SWE', 'LIST')) self.add_parameter(name='phase', label='Phase', unit='deg', get_cmd='PHASE?', set_cmd='PHASE' + ' {:.8f}', get_parser=self.rad_to_deg, set_parser=self.deg_to_rad, vals=vals.Numbers(-180, 180)) self.add_parameter(name='power', label='Power', unit='dBm', get_cmd='POW:AMPL?', set_cmd='POW:AMPL' + ' {:.4f}', get_parser=float, set_parser=float, vals=vals.Numbers(-130, 25)) self.add_parameter('status', get_cmd=':OUTP?', set_cmd='OUTP {}', get_parser=parse_on_off, vals=on_off_validator) self.add_parameter(name='modulation_rf_enabled', get_cmd='OUTP:MOD?', set_cmd='OUTP:MOD {}', val_mapping=on_off_mapping) self.add_parameter('IQmodulator_enabled', get_cmd='DM:STATe?', set_cmd='DM:STATe {}', val_mapping=on_off_mapping, docstring='Enables or disables the internal I/Q modulator. Source can be external or internal.') for source in [1, 2]: self.add_parameter(f'IQsource{source}', get_cmd=f'DM:SOUR{source}?', set_cmd=f'DM:SOUR{source} {{}}', get_parser=lambda s: s.strip(), vals=vals.Enum('OFF', 'EXT', 'EXT600', 'INT'), docstring=IQsource_docstring) self.add_parameter(f'IQadjustments_enabled', get_cmd=f'DM:IQADC?', set_cmd=f'DM:IQADC {{}}', val_mapping=on_off_mapping, docstring='Enable or disable IQ adjustments') IQoffset_parameters = dict(get_parser=float, set_parser=float, vals=vals.Numbers(-100,100)) self.add_parameter(f'I_offset', get_cmd=f'DM:IQAD:IOFF?', set_cmd=f'DM:IQAD:IOFF {{}}', **IQoffset_parameters, docstring='I channel offset in percentage') self.add_parameter(f'Q_offset', get_cmd=f'DM:IQAD:QOFF?', set_cmd=f'DM:IQAD:QOFF {{}}', **IQoffset_parameters, docstring='Q channel offset in percentage') self.add_parameter(f'IQ_quadrature', get_cmd=f'DM:IQAD:QSK?', set_cmd=f'DM:IQAD:QSK {{}}', get_parser=float, set_parser=float, docstring='IQ quadrature offset', unit='deg') self.add_parameter(f'pulse_modulation_enabled', get_cmd=f'AM:WID:STAT?', set_cmd=f'AM:WID:STAT {{}}', val_mapping=on_off_mapping, docstring='Enable or disable pulse modulation path') self.connect_message()
def __init__(self, name: str, address: str, model: Optional[str] = None, timeout: float = 5., HD: bool = True, terminator: str = '\n', **kwargs: Any) -> None: """ Args: name: name of the instrument address: VISA resource address model: The instrument model. For newer firmware versions, this can be auto-detected timeout: The VISA query timeout HD: Does the unit have the High Definition Option (allowing 16 bit vertical resolution) terminator: Command termination character to strip from VISA commands. """ super().__init__(name=name, address=address, timeout=timeout, terminator=terminator, **kwargs) # With firmware versions earlier than 3.65, it seems that the # model number can NOT be queried from the instrument # (at least fails with RTO1024, fw 2.52.1.1), so in that case # the user must provide the model manually. firmware_version_str = self.get_idn()["firmware"] if firmware_version_str is None: raise RuntimeError( "Could not determine firmware version of RTO1000.") firmware_version = version.parse(firmware_version_str) if firmware_version < version.parse("3"): log.warning("Old firmware version detected. This driver may " "not be compatible. Please upgrade your firmware.") if firmware_version >= version.parse("3.65"): # strip just in case there is a newline character at the end self.model = self.ask('DIAGnostic:SERVice:WFAModel?').strip() if model is not None and model != self.model: warnings.warn("The model number provided by the user " "does not match the instrument's response." " I am going to assume that this oscilloscope " f"is a model {self.model}") else: if model is None: raise ValueError('No model number provided. Please provide ' 'a model number (eg. "RTO1024").') else: self.model = model self.HD = HD # Now assign model-specific values self.num_chans = int(self.model[-1]) self.num_meas = 8 self._horisontal_divs = int(self.ask('TIMebase:DIVisions?')) self.add_parameter('display', label='Display state', set_cmd='SYSTem:DISPlay:UPDate {}', val_mapping={ 'remote': 0, 'view': 1 }) # Triggering self.add_parameter('trigger_display', label='Trigger display state', set_cmd='DISPlay:TRIGger:LINes {}', get_cmd='DISPlay:TRIGger:LINes?', val_mapping={ 'ON': 1, 'OFF': 0 }) # TODO: (WilliamHPNielsen) There are more available trigger # settings than implemented here. See p. 1261 of the manual # here we just use trigger1, which is the A-trigger self.add_parameter('trigger_source', label='Trigger source', set_cmd='TRIGger1:SOURce {}', get_cmd='TRIGger1:SOURce?', val_mapping={ 'CH1': 'CHAN1', 'CH2': 'CHAN2', 'CH3': 'CHAN3', 'CH4': 'CHAN4', 'EXT': 'EXT' }) self.add_parameter('trigger_mode', label='Trigger mode', set_cmd='TRIGger:MODE {}', get_cmd='TRIGger1:SOURce?', vals=vals.Enum('AUTO', 'NORMAL', 'FREERUN'), docstring='Sets the trigger mode which determines' ' the behaviour of the instrument if no' ' trigger occurs.\n' 'Options: AUTO, NORMAL, FREERUN.', unit='none') self.add_parameter('trigger_type', label='Trigger type', set_cmd='TRIGger1:TYPE {}', get_cmd='TRIGger1:TYPE?', val_mapping={ 'EDGE': 'EDGE', 'GLITCH': 'GLIT', 'WIDTH': 'WIDT', 'RUNT': 'RUNT', 'WINDOW': 'WIND', 'TIMEOUT': 'TIM', 'INTERVAL': 'INT', 'SLEWRATE': 'SLEW', 'DATATOCLOCK': 'DAT', 'STATE': 'STAT', 'PATTERN': 'PATT', 'ANEDGE': 'ANED', 'SERPATTERN': 'SERP', 'NFC': 'NFC', 'TV': 'TV', 'CDR': 'CDR' }) # See manual p. 1262 for an explanation of trigger types self.add_parameter('trigger_level', label='Trigger level', set_cmd=self._set_trigger_level, get_cmd=self._get_trigger_level) self.add_parameter('trigger_edge_slope', label='Edge trigger slope', set_cmd='TRIGger1:EDGE:SLOPe {}', get_cmd='TRIGger1:EDGE:SLOPe?', vals=vals.Enum('POS', 'NEG', 'EITH')) # Horizontal settings self.add_parameter('timebase_scale', label='Timebase scale', set_cmd=self._set_timebase_scale, get_cmd='TIMebase:SCALe?', unit='s/div', get_parser=float, vals=vals.Numbers(25e-12, 10000)) self.add_parameter('timebase_range', label='Timebase range', set_cmd=self._set_timebase_range, get_cmd='TIMebase:RANGe?', unit='s', get_parser=float, vals=vals.Numbers(250e-12, 100e3)) self.add_parameter('timebase_position', label='Horizontal position', set_cmd=self._set_timebase_position, get_cmd='TIMEbase:HORizontal:POSition?', get_parser=float, unit='s', vals=vals.Numbers(-100e24, 100e24)) # Acquisition # I couldn't find a way to query the run mode, so we manually keep # track of it. It is very important when getting the trace to make # sense of completed_acquisitions. self.add_parameter('run_mode', label='Run/acquisition mode of the scope', get_cmd=None, set_cmd=None) self.run_mode('RUN CONT') self.add_parameter('num_acquisitions', label='Number of single acquisitions to perform', get_cmd='ACQuire:COUNt?', set_cmd='ACQuire:COUNt {}', vals=vals.Ints(1, 16777215), get_parser=int) self.add_parameter('completed_acquisitions', label='Number of completed acquisitions', get_cmd='ACQuire:CURRent?', get_parser=int) self.add_parameter('sampling_rate', label='Sample rate', docstring='Number of averages for measuring ' 'trace.', unit='Sa/s', get_cmd='ACQuire:POINts:ARATe' + '?', get_parser=int) self.add_parameter('acquisition_sample_rate', label='Acquisition sample rate', unit='Sa/s', docstring='recorded waveform samples per second', get_cmd='ACQuire:SRATe' + '?', set_cmd='ACQuire:SRATe ' + ' {:.2f}', vals=vals.Numbers(2, 20e12), get_parser=float) # Data self.add_parameter('dataformat', label='Export data format', set_cmd='FORMat:DATA {}', get_cmd='FORMat:DATA?', vals=vals.Enum('ASC,0', 'REAL,32', 'INT,8', 'INT,16')) # High definition mode (might not be available on all instruments) if HD: self.add_parameter('high_definition_state', label='High definition (16 bit) state', set_cmd=self._set_hd_mode, get_cmd='HDEFinition:STAte?', val_mapping=create_on_off_val_mapping( on_val=1, off_val=0), docstring='Sets the filter bandwidth for the' ' high definition mode.\n' 'ON: high definition mode, up to 16' ' bit digital resolution\n' 'Options: ON, OFF\n\n' 'Warning/Bug: By opening the HD ' 'acquisition menu on the scope, ' 'this value will be set to "ON".') self.add_parameter('high_definition_bandwidth', label='High definition mode bandwidth', set_cmd='HDEFinition:BWIDth {}', get_cmd='HDEFinition:BWIDth?', unit='Hz', get_parser=float, vals=vals.Numbers(1e4, 1e9)) self.add_parameter('error_count', label='Number of errors in the error stack', get_cmd='SYSTem:ERRor:COUNt?', unit='#', get_parser=int) self.add_parameter('error_next', label='Next error from the error stack', get_cmd='SYSTem:ERRor:NEXT?', get_parser=str) # Add the channels to the instrument for ch in range(1, self.num_chans + 1): chan = ScopeChannel(self, f'channel{ch}', ch) self.add_submodule(f'ch{ch}', chan) for measId in range(1, self.num_meas + 1): measCh = ScopeMeasurement(self, f'measurement{measId}', measId) self.add_submodule(f'meas{measId}', measCh) self.add_function('stop', call_cmd='STOP') self.add_function('reset', call_cmd='*RST') self.add_parameter('opc', get_cmd='*OPC?') self.add_parameter('stop_opc', get_cmd='STOP;*OPC?') self.add_parameter('status_operation', get_cmd='STATus:OPERation:CONDition?', get_parser=int) self.add_function('run_continues', call_cmd='RUNContinous') # starts the shutdown of the system self.add_function('system_shutdown', call_cmd='SYSTem:EXIT') self.connect_message()
def __init__(self, name: str, address: str, options: str = "", dll_path: str = r"C:\Program Files\IVI " r"Foundation\IVI\Bin\KtM960x_64.dll", **kwargs: Any) -> None: super().__init__(name, **kwargs) self._address = bytes(address, "ascii") self._options = bytes(options, "ascii") self._session = ctypes.c_int(0) self._dll_loc = dll_path self._dll = ctypes.cdll.LoadLibrary(self._dll_loc) self.add_parameter( 'output', label="Source Output Enable", get_cmd=partial(self._get_vi_bool, KTM960X_ATTR_OUTPUT_ENABLED), set_cmd=partial(self._set_vi_bool, KTM960X_ATTR_OUTPUT_ENABLED), val_mapping=create_on_off_val_mapping(on_val=True, off_val=False)) self.add_parameter('voltage_level', label="Source Voltage Level", unit="Volt", get_cmd=partial(self._get_vi_real64, KTM960X_ATTR_OUTPUT_VOLTAGE_LEVEL), set_cmd=partial(self._set_vi_real64, KTM960X_ATTR_OUTPUT_VOLTAGE_LEVEL), vals=vals.Numbers(-210, 210)) self.add_parameter("current_range", label="Output Current Range", unit="Amp", vals=vals.Numbers(1e-9, 300e-3), get_cmd=partial(self._get_vi_real64, KTM960X_ATTR_OUTPUT_CURRENT_RANGE), set_cmd=partial(self._set_vi_real64, KTM960X_ATTR_OUTPUT_CURRENT_RANGE)) self.add_parameter( "measure_current_range", label="Current Measurement Range", unit="Amp", get_cmd=partial(self._get_vi_real64, KTM960X_ATTR_MEASUREMENT_CURRENT_RANGE), set_cmd=partial(self._set_vi_real64, KTM960X_ATTR_MEASUREMENT_CURRENT_RANGE), vals=vals.Numbers(1e-9, 300e-3), ) self.add_parameter( "measure_current_time", label="Current Measurement Integration Time", unit="Seconds", get_cmd=partial(self._get_vi_real64, KTM960X_ATTR_MEASUREMENT_CURRENT_APERTURE), set_cmd=partial(self._set_vi_real64, KTM960X_ATTR_MEASUREMENT_CURRENT_APERTURE), vals=vals.Numbers(800e-9, 2)) self.add_parameter("measure_data", parameter_class=Measure) self._get_driver_desc = partial( self._get_vi_string, KTM960X_ATTR_SPECIFIC_DRIVER_DESCRIPTION) self._get_driver_prefix = partial(self._get_vi_string, KTM960X_ATTR_SPECIFIC_DRIVER_PREFIX) self._get_driver_revision = partial( self._get_vi_string, KTM960X_ATTR_SPECIFIC_DRIVER_REVISION) self._get_firmware_revision = partial( self._get_vi_string, KTM960X_ATTR_INSTRUMENT_FIRMWARE_REVISION) self._get_model = partial(self._get_vi_string, KTM960X_ATTR_INSTRUMENT_MODEL) self._get_serial_number = partial(self._get_vi_string, KTM960X_ATTR_MODULE_SERIAL_NUMBER) self._get_manufacturer = partial(self._get_vi_string, KTM960X_ATTR_INSTRUMENT_MANUFACTURER) self._connect() self.connect_message()
def __init__(self, parent: 'Keithley2450', name: str, proper_function: str) -> None: super().__init__(parent, name) self._proper_function = proper_function range_vals = self.function_modes[self._proper_function]["range_vals"] unit = self.function_modes[self._proper_function]["unit"] self.function = self.parent.source_function self._sweep_arguments: Dict[str, Union[float, int, str]] = {} self.add_parameter("range", set_cmd=f":SOUR:{self._proper_function}:RANGe {{}}", get_cmd=f":SOUR:{self._proper_function}:RANGe?", vals=range_vals, get_parser=float, unit=unit) self.add_parameter( "auto_range", set_cmd=f":SOURce:{self._proper_function}:RANGe:AUTO {{}}", get_cmd=f":SOURce:{self._proper_function}:RANGe:AUTO?", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0")) limit_cmd = { "current": "VLIM", "voltage": "ILIM" }[self._proper_function] self.add_parameter( "limit", set_cmd=f"SOUR:{self._proper_function}:{limit_cmd} {{}}", get_cmd=f"SOUR:{self._proper_function}:{limit_cmd}?", get_parser=float, unit=unit) self.add_parameter( "limit_tripped", get_cmd=f":SOUR:{self._proper_function}:{limit_cmd}:TRIPped?", val_mapping={ True: 1, False: 0 }) self.add_parameter(self._proper_function, set_cmd=f"SOUR:{self._proper_function} {{}}", get_cmd=f"SOUR:{self._proper_function}?", get_parser=float, unit=unit, snapshot_value=False) self.add_parameter("sweep_axis", label=self._proper_function, get_cmd=self.get_sweep_axis, vals=Arrays(shape=(self.parent.npts, )), unit=unit) self.add_parameter( "delay", get_cmd=f":SOURce:{self._proper_function}:DELay?", set_cmd=f":SOURce:{self._proper_function}:DELay {{}}", vals=Numbers(0, 1e4)) self.add_parameter('user_number', get_cmd=None, set_cmd=None, vals=Ints(1, 5)) self.add_parameter("user_delay", get_cmd=self._get_user_delay, set_cmd=self._set_user_delay, vals=Numbers(0, 1e4)) self.add_parameter( "auto_delay", get_cmd=f":SOURce:{self._proper_function}:DELay:AUTO?", set_cmd=f":SOURce:{self._proper_function}:DELay:AUTO {{}}", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0")) self.add_parameter( "read_back_enabled", get_cmd=f":SOURce:{self._proper_function}:READ:BACK?", set_cmd=f":SOURce:{self._proper_function}:READ:BACK {{}}", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), docstring="This command determines if the instrument records the " "measured source value or the configured source value " "when making a measurement.")
def __init__(self, parent: 'Keithley2450', name: str, proper_function: str) -> None: super().__init__(parent, name) self._proper_function = proper_function range_vals = self.function_modes[self._proper_function]["range_vals"] unit = self.function_modes[self._proper_function]["unit"] self.function = self.parent.sense_function self.add_parameter( "four_wire_measurement", set_cmd=f":SENSe:{self._proper_function}:RSENse {{}}", get_cmd=f":SENSe:{self._proper_function}:RSENse?", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0")) self.add_parameter( "range", set_cmd=f":SENSe:{self._proper_function}:RANGe {{}}", get_cmd=f":SENSe:{self._proper_function}:RANGe?", vals=range_vals, get_parser=float, unit=unit) self.add_parameter( "auto_range", set_cmd=f":SENSe:{self._proper_function}:RANGe:AUTO {{}}", get_cmd=f":SENSe:{self._proper_function}:RANGe:AUTO?", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0")) self.add_parameter(self._proper_function, get_cmd=self._measure, get_parser=float, unit=unit, snapshot_value=False) self.add_parameter("sweep", label=self._proper_function, get_cmd=self._measure_sweep, unit=unit, vals=Arrays(shape=(self.parent.npts, )), parameter_class=ParameterWithSetpointsCustomized) self.add_parameter( "nplc", get_cmd=f":SENSe:{self._proper_function}:NPLCycles?", set_cmd=f":SENSe:{self._proper_function}:NPLCycles {{}}", vals=Numbers(0.001, 10)) self.add_parameter('user_number', get_cmd=None, set_cmd=None, vals=Ints(1, 5)) self.add_parameter("user_delay", get_cmd=self._get_user_delay, set_cmd=self._set_user_delay, get_parser=float, vals=Numbers(0, 1e4)) self.add_parameter( 'auto_zero_enabled', get_cmd=f":SENSe:{self._proper_function}:AZERo?", set_cmd=f":SENSe:{self._proper_function}:AZERo {{}}", val_mapping=create_on_off_val_mapping(on_val="1", off_val="0"), docstring="This command enables or disables automatic updates to" "the internal reference measurements (autozero) of the" "instrument.") self.add_parameter( 'count', get_cmd=":SENSe:COUNt?", set_cmd=":SENSe:COUNt {}", docstring="The number of measurements to make when a measurement " "is requested.")
def __init__(self, parent: Instrument, name: str, channel: str) -> None: """ Args: parent: The Instrument instance to which the channel is to be attached. name: The 'colloquial' name of the channel channel: The name used by the Keithley, i.e. either 'smua' or 'smub' """ if channel not in ['smua', 'smub']: raise ValueError('channel must be either "smub" or "smua"') super().__init__(parent, name) self.model = self._parent.model self._extra_visa_timeout = 5000 self._measurement_duration_factor = 2 # Ensures that we are always above # the expected time. vranges = self._parent._vranges iranges = self._parent._iranges vlimit_minmax = self.parent._vlimit_minmax ilimit_minmax = self.parent._ilimit_minmax self.add_parameter('volt', parameter_class=_MeasurementVoltageParameter, label='Voltage', unit='V', snapshot_get=False) self.add_parameter('ramp_voltage', get_cmd=f'{channel}.measure.v()', get_parser=float, set_cmd=self.ramp_voltage_to, label='Voltage', unit='V') self.add_parameter( 'ramp_voltage_step', label='Step size for ramp_voltage', unit='V', initial_value=10e-3, get_cmd=None, set_cmd=None, ) self.add_parameter( 'ramp_voltage_delay', label='Delay for ramp_voltage', unit='s', initial_value=0, get_cmd=None, set_cmd=None, ) self.add_parameter('curr', parameter_class=_MeasurementCurrentParameter, label='Current', unit='A', snapshot_get=False) self.add_parameter('ramp_current', get_cmd=f'{channel}.measure.i()', get_parser=float, set_cmd=self.ramp_current_to, label='Current', unit='A') self.add_parameter( 'ramp_current_step', label='Step size for ramp_current', unit='A', initial_value=0.3e-3, get_cmd=None, set_cmd=None, ) self.add_parameter( 'ramp_current_delay', label='Delay for ramp_current', unit='s', initial_value=10e-3, get_cmd=None, set_cmd=None, ) self.add_parameter('res', get_cmd=f'{channel}.measure.r()', get_parser=float, set_cmd=False, label='Resistance', unit='Ohm') self.add_parameter('mode', get_cmd=f'{channel}.source.func', get_parser=float, set_cmd=f'{channel}.source.func={{:d}}', val_mapping={ 'current': 0, 'voltage': 1 }, docstring='Selects the output source type. ' 'Can be either voltage or current.') self.add_parameter('output', get_cmd=f'{channel}.source.output', get_parser=float, set_cmd=f'{channel}.source.output={{:d}}', val_mapping=create_on_off_val_mapping(on_val=1, off_val=0)) self.add_parameter('linefreq', label='Line frequency', get_cmd='localnode.linefreq', get_parser=float, set_cmd=False, unit='Hz') self.add_parameter('nplc', label='Number of power line cycles', set_cmd=f'{channel}.measure.nplc={{}}', get_cmd=f'{channel}.measure.nplc', get_parser=float, docstring='Number of power line cycles, used ' 'to perform measurements', vals=vals.Numbers(0.001, 25)) # volt range # needs get after set (WilliamHPNielsen): why? self.add_parameter('sourcerange_v', label='voltage source range', get_cmd=f'{channel}.source.rangev', get_parser=float, set_cmd=self._set_sourcerange_v, unit='V', docstring='The range used when sourcing voltage ' 'This affects the range and the precision ' 'of the source.', vals=vals.Enum(*vranges[self.model])) self.add_parameter( 'source_autorange_v_enabled', label='voltage source autorange', get_cmd=f'{channel}.source.autorangev', get_parser=float, set_cmd=f'{channel}.source.autorangev={{}}', docstring='Set autorange on/off for source voltage.', val_mapping=create_on_off_val_mapping(on_val=1, off_val=0)) self.add_parameter('measurerange_v', label='voltage measure range', get_cmd=f'{channel}.measure.rangev', get_parser=float, set_cmd=self._set_measurerange_v, unit='V', docstring='The range to perform voltage ' 'measurements in. This affects the range ' 'and the precision of the measurement. ' 'Note that if you both measure and ' 'source current this will have no effect, ' 'set `sourcerange_v` instead', vals=vals.Enum(*vranges[self.model])) self.add_parameter( 'measure_autorange_v_enabled', label='voltage measure autorange', get_cmd=f'{channel}.measure.autorangev', get_parser=float, set_cmd=f'{channel}.measure.autorangev={{}}', docstring='Set autorange on/off for measure voltage.', val_mapping=create_on_off_val_mapping(on_val=1, off_val=0)) # current range # needs get after set self.add_parameter('sourcerange_i', label='current source range', get_cmd=f'{channel}.source.rangei', get_parser=float, set_cmd=self._set_sourcerange_i, unit='A', docstring='The range used when sourcing current ' 'This affects the range and the ' 'precision of the source.', vals=vals.Enum(*iranges[self.model])) self.add_parameter( 'source_autorange_i_enabled', label='current source autorange', get_cmd=f'{channel}.source.autorangei', get_parser=float, set_cmd=f'{channel}.source.autorangei={{}}', docstring='Set autorange on/off for source current.', val_mapping=create_on_off_val_mapping(on_val=1, off_val=0)) self.add_parameter('measurerange_i', label='current measure range', get_cmd=f'{channel}.measure.rangei', get_parser=float, set_cmd=self._set_measurerange_i, unit='A', docstring='The range to perform current ' 'measurements in. This affects the range ' 'and the precision of the measurement. ' 'Note that if you both measure and source ' 'current this will have no effect, set ' '`sourcerange_i` instead', vals=vals.Enum(*iranges[self.model])) self.add_parameter( 'measure_autorange_i_enabled', label='current autorange', get_cmd=f'{channel}.measure.autorangei', get_parser=float, set_cmd=f'{channel}.measure.autorangei={{}}', docstring='Set autorange on/off for measure current.', val_mapping=create_on_off_val_mapping(on_val=1, off_val=0)) # Compliance limit self.add_parameter('limitv', get_cmd=f'{channel}.source.limitv', get_parser=float, set_cmd=f'{channel}.source.limitv={{}}', docstring='Voltage limit e.g. the maximum voltage ' 'allowed in current mode. If exceeded ' 'the current will be clipped.', vals=vals.Numbers(vlimit_minmax[self.model][0], vlimit_minmax[self.model][1]), unit='V') # Compliance limit self.add_parameter('limiti', get_cmd=f'{channel}.source.limiti', get_parser=float, set_cmd=f'{channel}.source.limiti={{}}', docstring='Current limit e.g. the maximum current ' 'allowed in voltage mode. If exceeded ' 'the voltage will be clipped.', vals=vals.Numbers(ilimit_minmax[self.model][0], ilimit_minmax[self.model][1]), unit='A') self.add_parameter('fastsweep', parameter_class=LuaSweepParameter) self.add_parameter('timetrace_npts', initial_value=500, label='Number of points', get_cmd=None, set_cmd=None) self.add_parameter('timetrace_dt', initial_value=1e-3, label='Time resolution', unit='s', get_cmd=None, set_cmd=None) self.add_parameter(name='time_axis', label='Time', unit='s', snapshot_value=False, vals=vals.Arrays(shape=(self.timetrace_npts, )), parameter_class=TimeAxis) self.add_parameter('timetrace', vals=vals.Arrays(shape=(self.timetrace_npts, )), setpoints=(self.time_axis, ), parameter_class=TimeTrace) self.add_parameter('timetrace_mode', initial_value='current', get_cmd=None, set_cmd=self.timetrace._set_mode, vals=vals.Enum('current', 'voltage')) self.channel = channel
def __init__(self, parent: Instrument, name: str, channel: str) -> None: """ Args: parent: The Instrument instance to which the channel is to be attached. name: The 'colloquial' name of the channel channel: The name used by the Holzworth, i.e. either 'CH1' or 'CH2' """ super().__init__(parent, name) self.channel = channel self._min_f = self._parse_f_unit( self.ask_raw(':{}:Freq:MIN?'.format(channel))) self._max_f = self._parse_f_unit( self.ask_raw(':{}:Freq:MAX?'.format(channel))) self._min_pwr = self._parse_pwr_unit( self.ask_raw(':{}:PWR:MIN?'.format(channel))) self._max_pwr = self._parse_pwr_unit( self.ask_raw(':{}:PWR:MAX?'.format(channel))) self._min_phase = self._parse_phase_unit( self.ask_raw(':{}:PHASE:MIN?'.format(channel))) self._max_phase = self._parse_phase_unit( self.ask_raw(':{}:PHASE:MAX?'.format(channel))) self.add_parameter(name='state', label='State', get_parser=str, get_cmd=':{}:PWR:RF?'.format(self.channel), set_cmd=self._set_state, val_mapping=create_on_off_val_mapping( on_val='ON', off_val='OFF')) self.add_parameter(name='power', label='Power', get_parser=float, get_cmd=':{}:PWR?'.format(self.channel), set_cmd=self._set_pwr, unit='dBm', vals=Numbers(min_value=self._min_pwr, max_value=self._max_pwr)) self.add_parameter(name='frequency', label='Frequency', get_parser=float, get_cmd=self._get_f, set_cmd=self._set_f, unit='Hz', vals=Numbers(min_value=self._min_f, max_value=self._max_f)) self.add_parameter(name='phase', label='Phase', get_parser=float, get_cmd=':{}:PHASE?'.format(self.channel), set_cmd=self._set_phase, unit='deg', vals=Numbers(min_value=self._min_phase, max_value=self._max_phase)) self.add_parameter(name='temp', label='Temperature', get_parser=float, get_cmd=self._get_temp, unit='C')