示例#1
0
    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))
示例#3
0
    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()
示例#4
0
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
示例#5
0
    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)
示例#6
0
    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()
示例#7
0
    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})
示例#8
0
    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()
示例#9
0
    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
        )
示例#10
0
    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()
示例#11
0
    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,
        )
示例#12
0
    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")
        )
示例#13
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))
示例#15
0
    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()
示例#17
0
文件: E8527D.py 项目: tyqh03/Qcodes
    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()
示例#18
0
    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()
示例#19
0
    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()
示例#20
0
    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."
        )
示例#21
0
    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.")
示例#22
0
    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.")
示例#23
0
    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()
示例#24
0
    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()
示例#25
0
    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()
示例#26
0
    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()
示例#27
0
    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.")
示例#28
0
    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.")
示例#29
0
    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')