Пример #1
0
    def __init__(self, name, address, num_chans=48, update_currents=True):
        """
        Instantiates the instrument.

        Args:
            name (str): The instrument name used by qcodes
            address (str): The VISA name of the resource
            num_chans (int): Number of channels to assign. Default: 48
            update_currents (bool): Whether to query all channels for their
                current current value on startup. Default: True.

        Returns:
            QDac object
        """
        super().__init__(name, address)
        handle = self.visa_handle

        # This is the baud rate on power-up. It can be changed later but
        # you must start out with this value.
        handle.baud_rate = 480600
        handle.parity = visa.constants.Parity(0)
        handle.data_bits = 8
        self.set_terminator('\n')
        # TODO: do we want a method for write termination too?
        handle.write_termination = '\n'
        # TODO: do we need a query delay for robust operation?
        self._write_response = ''

        # The following bool is used in self.write
        self.debugmode = False

        if self._get_firmware_version() < 0.170202:
            raise RuntimeError('''
                               Obsolete QDAC Software version detected.
                               QCoDeS only supports version 0.170202 or newer.
                               Contact [email protected] for an update.
                               ''')

        self.num_chans = num_chans

        # Assigned slopes. Entries will eventually be [chan, slope]
        self._slopes = []
        # Function generators (used in _set_voltage)
        self._fgs = set(range(1, 9))
        self._assigned_fgs = {}  # {chan: fg}
        # Sync channels
        self._syncoutputs = []  # Entries: [chan, syncchannel]

        self.chan_range = range(1, 1 + self.num_chans)
        self.channel_validator = vals.Ints(1, self.num_chans)

        for i in self.chan_range:
            stri = str(i)
            self.add_parameter(name='ch{:02}_v'.format(i),
                               label='Channel ' + stri,
                               unit='V',
                               set_cmd=partial(self._set_voltage, i),
                               vals=vals.Numbers(-10, 10),
                               get_cmd=partial(self.read_state, i, 'v')
                               )
            self.add_parameter(name='ch{:02}_vrange'.format(i),
                               set_cmd=partial(self._set_vrange, i),
                               get_cmd=partial(self.read_state, i, 'vrange'),
                               vals=vals.Enum(0, 1)
                               )
            self.add_parameter(name='ch{:02}_irange'.format(i),
                               set_cmd='cur ' + stri + ' {}',
                               get_cmd=partial(self.read_state, i, 'irange')
                               )
            self.add_parameter(name='ch{:02}_i'.format(i),
                               label='Current ' + stri,
                               unit='A',
                               get_cmd='get ' + stri,
                               get_parser=self._current_parser
                               )
            self.add_parameter(name='ch{:02}_slope'.format(i),
                               label='Maximum voltage slope',
                               unit='V/s',
                               set_cmd=partial(self._setslope, i),
                               get_cmd=partial(self._getslope, i),
                               vals=vals.MultiType(vals.Enum('Inf'),
                                                   vals.Numbers(1e-3, 100))
                               )
            self.add_parameter(name='ch{:02}_sync'.format(i),
                               label='Channel {} sync output',
                               set_cmd=partial(self._setsync, i),
                               get_cmd=partial(self._getsync, i),
                               vals=vals.Ints(0, 5)
                               )

            self.add_parameter(name='ch{:02}_sync_delay'.format(i),
                               label='Channel {} sync pulse delay'.format(i),
                               unit='s',
                               parameter_class=ManualParameter,
                               initial_value=0)

            self.add_parameter(name='ch{:02}_sync_duration'.format(i),
                               label='Channel {} sync pulse duration'.format(i),
                               unit='s',
                               parameter_class=ManualParameter,
                               initial_value=0.01)

        for board in range(6):
            for sensor in range(3):
                label = 'Board {}, Temperature {}'.format(board, sensor)
                self.add_parameter(name='temp{}_{}'.format(board, sensor),
                                   label=label,
                                   unit='C',
                                   get_cmd='tem {} {}'.format(board, sensor),
                                   get_parser=self._num_verbose)

        self.add_parameter(name='cal',
                           set_cmd='cal {}',
                           vals=self.channel_validator)
        # TO-DO: maybe it's too dangerous to have this settable.
        # And perhaps ON is a better verbose mode default?
        self.add_parameter(name='verbose',
                           set_cmd='ver {}',
                           val_mapping={True: 1, False: 0})

        # Initialise the instrument, all channels DC (unbind func. generators)
        for chan in self.chan_range:
            # Note: this call does NOT change the voltage on the channel
            self.write('wav {} 0 1 0'.format(chan))

        self.verbose.set(False)
        self.connect_message()
        log.info('[*] Querying all channels for voltages and currents...')
        self._get_status(readcurrents=update_currents)
        log.info('[+] Done')
Пример #2
0
    def __init__(self, parent, name, channum):
        """
        Args:
            parent (Instrument): The instrument to which the channel is
                attached.
            name (str): The name of the channel
            channum (int): The number of the channel in question (1-48)
        """
        super().__init__(parent, name)

        # Validate the channel
        self._CHANNEL_VALIDATION.validate(channum)

        # Add the parameters

        self.add_parameter('v',
                           label=f'Channel {channum} voltage',
                           unit='V',
                           set_cmd=partial(self._parent._set_voltage, channum),
                           get_cmd=partial(self._parent._get_voltage, channum),
                           get_parser=float,
                           vals=vals.Numbers(-10, 10))

        self.add_parameter('vrange',
                           label=f'Channel {channum} atten.',
                           set_cmd=partial(self._parent._set_vrange, channum),
                           get_cmd=partial(self._parent._get_vrange, channum),
                           vals=vals.Enum(0, 1))

        self.add_parameter('i',
                           label=f'Channel {channum} current',
                           get_cmd=f'get {channum}',
                           unit='A',
                           get_parser=self._parent._current_parser)

        self.add_parameter('irange',
                           label=f'Channel {channum} irange',
                           set_cmd=f'cur {channum} {{}}',
                           get_cmd=f'cur {channum}',
                           get_parser=int)

        self.add_parameter('slope',
                           label=f'Channel {channum} slope',
                           unit='V/s',
                           set_cmd=partial(self._parent._setslope, channum),
                           get_cmd=partial(self._parent._getslope, channum),
                           vals=vals.MultiType(vals.Enum('Inf'),
                                               vals.Numbers(1e-3, 100)))

        self.add_parameter('sync',
                           label=f'Channel {channum} sync output',
                           set_cmd=partial(self._parent._setsync, channum),
                           get_cmd=partial(self._parent._getsync, channum),
                           vals=vals.Ints(0, 5))

        self.add_parameter(name='sync_delay',
                           label=f'Channel {channum} sync pulse delay',
                           unit='s',
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=0)

        self.add_parameter(name='sync_duration',
                           label=f'Channel {channum} sync pulse duration',
                           unit='s',
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=0.01)
Пример #3
0
    def __init__(self, name: str, address: str, silent: bool = False,
                 **kwargs: Any):
        """
        Create an instance of the instrument.

        Args:
            name: Name used by QCoDeS. Appears in the DataSet
            address: Visa-resolvable instrument address.
            silent: If True, the connect_message of the instrument
                is supressed. Default: False
        """

        super().__init__(name, address, terminator='\n', **kwargs)

        idn = self.IDN.get()
        self.model = idn['model']

        self.is_34465A_34470A = self.model in ['34465A', '34470A']

        ####################################
        # Instrument specifications

        options = self._options()
        self.has_DIG = self.is_34465A_34470A and (
            'DIG' in options
            or LooseVersion('A.03') <= LooseVersion(idn['firmware'])
        )
        # Note that the firmware version check is still needed because
        # ``_options`` (the ``*OPT?`` command) returns 'DIG' option for
        # firmware 3.0 only if it has been purchased before
        self.has_MEM = self.is_34465A_34470A and 'MEM' in options

        PLCs = {'34410A': [0.006, 0.02, 0.06, 0.2, 1, 2, 10, 100],
                '34460A': [0.02, 0.2, 1, 10, 100],
                '34461A': [0.02, 0.2, 1, 10, 100],
                '34465A': [0.02, 0.06, 0.2, 1, 10, 100],
                '34470A': [0.02, 0.06, 0.2, 1, 10, 100]
                }
        if self.has_DIG:
            PLCs['34465A'] = [0.001, 0.002, 0.006] + PLCs['34465A']
            PLCs['34470A'] = [0.001, 0.002, 0.006] + PLCs['34470A']

        ranges = {'34410A': [10**n for n in range(3, 10)],  # 100 to 1 G
                  '34460A': [10**n for n in range(-3, 9)],  # 1 m to 100 M
                  '34461A': [10**n for n in range(-3, 9)],  # 1 m to 100 M
                  '34465A': [10**n for n in range(-3, 10)],  # 1 m to 1 G
                  '34470A': [10**n for n in range(-3, 10)],  # 1 m to 1 G
                  }

        # The resolution factor order matches the order of PLCs
        res_factors = {'34410A': [30e-6, 15e-5, 6e-6, 3e-6, 1.5e-6, 0.7e-6,
                                  0.3e-6, 0.2e-6, 0.1e-6, 0.03e-6],
                       '34460A': [300e-6, 100e-6, 30e-6, 10e-6, 3e-6],
                       '34461A': [100e-6, 10e-6, 3e-6, 1e-6, 0.3e-6],
                       '34465A': [3e-6, 1.5e-6, 0.7e-6, 0.3e-6, 0.1e-6,
                                  0.03e-6],
                       '34470A': [1e-6, 0.5e-6, 0.3e-6, 0.1e-6, 0.03e-6,
                                  0.01e-6]
                       }
        if self.has_DIG:
            res_factors['34465A'] = [30e-6, 15e-6, 6e-6] + res_factors['34465A']
            res_factors['34470A'] = [30e-6, 10e-6, 3e-6] + res_factors['34470A']

        self._resolution_factors = res_factors[self.model]
        self.ranges = ranges[self.model]
        self.NPLC_list = PLCs[self.model]

        ####################################
        # PARAMETERS

        # this is the "master" parameter that determines whether the DMM is
        # a voltmeter, an ampmeter, etc.
        self.add_parameter('sense_function',
                           label="Instrument sense function",
                           get_cmd="SENSe:FUNCtion?",
                           set_cmd="SENSe:FUNCtion {}",
                           val_mapping={"DC Voltage": '"VOLT"',
                                        "AC Voltage": '"VOLT:AC"',
                                        "DC Current": '"CURR"',
                                        "AC Current": '"CURR:AC"',
                                        "2 Wire Resistance": '"RES"',
                                        "4 Wire Resistance": '"FRES"'})

        self.add_parameter('line_frequency',
                           get_cmd='SYSTem:LFRequency?',
                           get_parser=int,
                           set_cmd=False,
                           label='Line Frequency',
                           unit='Hz',
                           docstring=('The frequency of the power line where '
                                      'the instrument is plugged')
                           )

        self.add_parameter('NPLC',
                           get_cmd='SENSe:VOLTage:DC:NPLC?',
                           get_parser=float,
                           set_cmd=self._set_NPLC,
                           vals=vals.Enum(*self.NPLC_list),
                           label='Integration time',
                           unit='NPLC',
                           docstring=textwrap.dedent("""\
            Sets the integration time in number of power line cycles (PLC)
            for DC voltage and ratio measurements. Integration time is the
            period that the instrument's analog-to-digital (A/D) converter
            samples the input signal for a measurement. A longer integration
            time gives better measurement resolution but slower measurement
            speed.

            Only integration times of 1, 10, or 100 PLC provide normal mode
            (line frequency noise) rejection.

            Setting the integration time also sets the measurement
            resolution."""))

        self.add_parameter('range',
                           get_cmd='SENSe:VOLTage:DC:RANGe?',
                           get_parser=float,
                           set_cmd='SENSe:VOLTage:DC:RANGe {:f}',
                           vals=vals.Enum(*self.ranges))

        self.add_parameter('resolution',
                           get_cmd='SENSe:VOLTage:DC:RESolution?',
                           get_parser=float,
                           set_cmd=self._set_resolution,
                           label='Resolution',
                           unit='V',
                           vals=vals.MultiType(
                               vals.Numbers(0),
                               vals.Enum('MIN', 'MAX', 'DEF')),
                           docstring=textwrap.dedent("""\
            Selects the measurement resolution for DC voltage and ratio
            measurements. The resolution is specified in the same units as the
            selected measurement function, not in number of digits.

            You can also specify MIN (best resolution) or MAX (worst
            resolution).

            To achieve normal mode (line frequency noise) rejection,
            use a resolution that corresponds to an integration time that is
            an integral number of power line cycles.

            Refer to "Resolution Table" or "Range, Resolution and NPLC"
            sections of the instrument's manual for the available ranges for
            the resolution values."""))

        self.add_parameter('autorange',
                           label='Autorange',
                           set_cmd='SENSe:VOLTage:DC:RANGe:AUTO {}',
                           get_cmd='SENSe:VOLTage:DC:RANGe:AUTO?',
                           val_mapping={'ON': 1, 'OFF': 0},
                           vals=vals.Enum('ON', 'OFF'))

        self.add_parameter('autozero',
                           label='Autozero',
                           set_cmd='SENSe:VOLTage:DC:ZERO:AUTO {}',
                           get_cmd='SENSe:VOLTage:DC:ZERO:AUTO?',
                           val_mapping={'ON': 1, 'OFF': 0, 'ONCE': 'ONCE'},
                           vals=vals.Enum('ON', 'OFF', 'ONCE'),
                           docstring=textwrap.dedent("""\
            Disables or enables the autozero mode for DC voltage and ratio
            measurements.

            ON:   the DMM internally measures the offset following each
                  measurement. It then subtracts that measurement from the
                  preceding reading. This prevents offset voltages present on
                  the DMM’s input circuitry from affecting measurement
                  accuracy.
            OFF:  the instrument uses the last measured zero measurement and
                  subtracts it from each measurement. It takes a new zero
                  measurement each time you change the function, range or
                  integration time.
            ONCE: the instrument takes one zero measurement and sets
                  autozero OFF. The zero measurement taken is used for all
                  subsequent measurements until the next change to the
                  function, range or integration time. If the specified
                  integration time is less than 1 PLC, the zero measurement
                  is taken at 1 PLC to optimize noise rejection. Subsequent
                  measurements are taken at the specified fast (< 1 PLC)
                  integration time."""))

        ####################################
        # Aperture parameters

        if self.is_34465A_34470A:
            # Define the extreme aperture time values for the 34465A and 34470A
            utility_freq = self.line_frequency()
            if utility_freq == 50:
                apt_times = {'34465A': [0.3e-3, 2],
                            '34470A': [0.3e-3, 2]}
            elif utility_freq == 60:
                apt_times = {'34465A': [0.3e-3, 1.67],
                            '34470A': [0.3e-3, 1.67]}
            if self.has_DIG:
                apt_times['34465A'][0] = 20e-6
                apt_times['34470A'][0] = 20e-6

            self.add_parameter('aperture_mode',
                               label='Aperture mode',
                               set_cmd='SENSe:VOLTage:DC:APERture:ENABled {}',
                               get_cmd='SENSe:VOLTage:DC:APERture:ENABled?',
                               val_mapping={'ON': 1, 'OFF': 0},
                               vals=vals.Enum('ON', 'OFF'),
                               docstring=textwrap.dedent("""\
                Enables the setting of integration time in seconds (called
                aperture time) for DC voltage measurements. If aperture time
                mode is disabled (default), the integration time is set in PLC
                (power-line cycles)."""))

            self.add_parameter('aperture_time',
                               label='Aperture time',
                               set_cmd=self._set_apt_time,
                               get_cmd='SENSe:VOLTage:DC:APERture?',
                               get_parser=float,
                               vals=vals.Numbers(*apt_times[self.model]),
                               docstring=textwrap.dedent("""\
                Specifies the integration time in seconds (called aperture
                time) with 2 µs resolution for DC voltage measurements.

                Use this command for precise control of the DMM's
                integration time. Use `NPLC` for better power-line noise
                rejection characteristics (NPLC > 1).

                Setting the aperture time automatically enables the aperture
                mode."""))

        ####################################
        # Submodules

        self.add_submodule('display', Display(self, 'display'))
        self.add_submodule('trigger', Trigger(self, 'trigger'))
        self.add_submodule('sample', Sample(self, 'sample'))

        ####################################
        # Measurement Parameters
        # snapshot_get is disabled for each of these to prevent rapid mode
        # changes on initialization or snapshot update, however the cached
        # (last read) value will still be stored in the snapshot.

        self.add_parameter('volt',
                           get_cmd=partial(self._get_parameter, "DC Voltage"),
                           label='Voltage',
                           unit='V',
                           snapshot_get=False)

        self.add_parameter('curr',
                           get_cmd=partial(self._get_parameter, "DC Current"),
                           label='Current',
                           unit='A',
                           snapshot_get=False)

        self.add_parameter('ac_volt',
                           get_cmd=partial(self._get_parameter, "AC Voltage"),
                           label='AC Voltage',
                           unit='V',
                           snapshot_get=False)

        self.add_parameter('ac_curr',
                           get_cmd=partial(self._get_parameter, "AC Current"),
                           label='AC Current',
                           unit='A',
                           snapshot_get=False)

        self.add_parameter('res',
                           get_cmd=partial(self._get_parameter,
                                           "2 Wire Resistance"),
                           label='Resistance',
                           unit='Ohms',
                           snapshot_get=False)

        self.add_parameter('four_wire_res',
                           get_cmd=partial(self._get_parameter,
                                           "4 Wire Resistance"),
                           label='Resistance',
                           unit='Ohms',
                           snapshot_get=False)

        #####################################
        # Time trace parameters

        self.add_parameter('timetrace_npts',
                           label='Time trace number of points',
                           initial_value=500,
                           get_cmd=None,
                           set_cmd=None,
                           vals=vals.Ints(1))

        self.add_parameter('timetrace_dt',
                           label='Time trace time interval',
                           unit='s',
                           initial_value=1e-1,
                           get_cmd=None,
                           set_cmd=None,
                           vals=vals.Numbers(0))

        self.add_parameter('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)

        ####################################
        # Connect message

        if not silent:
            self.connect_message()
Пример #4
0
    def __init__(self,
                 name,
                 address,
                 DIG=False,
                 utility_freq=50,
                 silent=False,
                 **kwargs):
        """
        Create an instance of the instrument.

        Args:
            name (str): Name used by QCoDeS. Appears in the DataSet
            address (str): Visa-resolvable instrument address.
            utility_freq (int): The local utility frequency in Hz. Default: 50
            DIG (bool): Is the DIG option installed on the instrument?
                Default: False.
            silent (bool): If True, the connect_message of the instrument
                is supressed. Default: False
        Returns:
            Keysight_34465A
        """
        if utility_freq not in [50, 60]:
            raise ValueError('Can not set utility frequency to '
                             '{}. '.format(utility_freq) +
                             'Please enter either 50 Hz or 60 Hz.')

        super().__init__(name, address, terminator='\n', **kwargs)

        idn = self.IDN.get()
        self.model = idn['model']

        ####################################
        # Instrument specifications

        PLCs = {
            '34460A': [0.02, 0.2, 1, 10, 100],
            '34461A': [0.02, 0.2, 1, 10, 100],
            '34465A': [0.02, 0.06, 0.2, 1, 10, 100],
            '34470A': [0.02, 0.06, 0.2, 1, 10, 100]
        }
        if DIG:
            PLCs['34465A'] = [0.001, 0.002, 0.006] + PLCs['34465A']
            PLCs['34470A'] = [0.001, 0.002, 0.006] + PLCs['34470A']

        ranges = {
            '34460A': [10**n for n in range(-3, 9)],  # 1 m to 100 M
            '34461A': [10**n for n in range(-3, 9)],  # 1 m to 100 M
            '34465A': [10**n for n in range(-3, 10)],  # 1 m to 1 G
            '34470A': [10**n for n in range(-3, 10)],  # 1 m to 1 G
        }

        # The resolution factor order matches the order of PLCs
        res_factors = {
            '34460A': [300e-6, 100e-6, 30e-6, 10e-6, 3e-6],
            '34461A': [100e-6, 10e-6, 3e-6, 1e-6, 0.3e-6],
            '34465A': [3e-6, 1.5e-6, 0.7e-6, 0.3e-6, 0.1e-6, 0.03e-6],
            '34470A': [1e-6, 0.5e-6, 0.3e-6, 0.1e-6, 0.03e-6, 0.01e-6]
        }
        if DIG:
            res_factors['34465A'] = [30e-6, 15e-6, 6e-6
                                     ] + res_factors['34465A']
            res_factors['34470A'] = [30e-6, 10e-6, 3e-6
                                     ] + res_factors['34470A']

        # Define the extreme aperture time values for the 34465A and 34470A
        if utility_freq == 50:
            apt_times = {'34465A': [0.3e-3, 2], '34470A': [0.3e-3, 2]}
        if utility_freq == 60:
            apt_times = {'34465A': [0.3e-3, 1.67], '34470A': [0.3e-3, 1.67]}
        if DIG:
            apt_times['34465A'][0] = 20e-6
            apt_times['34470A'][0] = 20e-6

        self._resolution_factors = res_factors[self.model]
        self.ranges = ranges[self.model]
        self.NPLC_list = PLCs[self.model]
        self._apt_times = apt_times[self.model]

        def errorparser(rawmssg: str) -> (int, str):
            """
            Parses the error message.

            Args:
                rawmssg: The raw return value of 'SYSTem:ERRor?'

            Returns:
                The error code and the error message.
            """
            code = int(rawmssg.split(',')[0])
            mssg = rawmssg.split(',')[1].strip().replace('"', '')

            return code, mssg

        ####################################
        # PARAMETERS

        self.add_parameter('NPLC',
                           get_cmd='SENSe:VOLTage:DC:NPLC?',
                           get_parser=float,
                           set_cmd=self._set_NPLC,
                           vals=vals.Enum(*self.NPLC_list),
                           label='Integration time',
                           unit='NPLC')

        self.add_parameter('volt',
                           get_cmd=self._get_voltage,
                           label='Voltage',
                           unit='V')

        self.add_parameter('range',
                           get_cmd='SENSe:VOLTage:DC:RANGe?',
                           get_parser=float,
                           set_cmd='SENSe:VOLTage:DC:RANGe {:f}',
                           vals=vals.Enum(*self.ranges))

        self.add_parameter('resolution',
                           get_cmd='SENSe:VOLTage:DC:RESolution?',
                           get_parser=float,
                           set_cmd=self._set_resolution,
                           label='Resolution',
                           unit='V')

        self.add_parameter('autorange',
                           label='Autorange',
                           set_cmd='SENSe:VOLTage:DC:RANGe:AUTO {}',
                           get_cmd='SENSe:VOLTage:DC:RANGe:AUTO?',
                           val_mapping={
                               'ON': 1,
                               'OFF': 0
                           },
                           vals=vals.Enum('ON', 'OFF'))

        self.add_parameter('display_text',
                           label='Display text',
                           set_cmd='DISPLAY:TEXT "{}"',
                           get_cmd='DISPLAY:TEXT?',
                           vals=vals.Strings())

        # TRIGGERING

        self.add_parameter('trigger_count',
                           label='Trigger Count',
                           set_cmd='TRIGger:COUNt {}',
                           get_cmd='TRIGger:COUNt?',
                           get_parser=float,
                           vals=vals.MultiType(
                               vals.Numbers(1, 1e6),
                               vals.Enum('MIN', 'MAX', 'DEF', 'INF')))

        self.add_parameter('trigger_delay',
                           label='Trigger Delay',
                           set_cmd='TRIGger:DELay {}',
                           get_cmd='TRIGger:DELay?',
                           vals=vals.MultiType(vals.Numbers(0, 3600),
                                               vals.Enum('MIN', 'MAX', 'DEF')),
                           get_parser=float)

        self.add_parameter('trigger_slope',
                           label='Trigger Slope',
                           set_cmd='TRIGger:SLOPe {}',
                           get_cmd='TRIGger:SLOPe?',
                           vals=vals.Enum('POS', 'NEG'))

        self.add_parameter('trigger_source',
                           label='Trigger Source',
                           set_cmd='TRIGger:SOURce {}',
                           get_cmd='TRIGger:SOURce?',
                           vals=vals.Enum('IMM', 'EXT', 'BUS', 'INT'))

        # SAMPLING

        self.add_parameter('sample_count',
                           label='Sample Count',
                           set_cmd=partial(self._set_databuffer_setpoints,
                                           'SAMPle:COUNt {}'),
                           get_cmd='SAMPle:COUNt?',
                           vals=vals.MultiType(vals.Numbers(1, 1e6),
                                               vals.Enum('MIN', 'MAX', 'DEF')),
                           get_parser=int)

        if DIG:
            self.add_parameter(
                'sample_count_pretrigger',
                label='Sample Pretrigger Count',
                set_cmd='SAMPle:COUNt:PRETrigger {}',
                get_cmd='SAMPle:COUNt:PRETrigger?',
                vals=vals.MultiType(vals.Numbers(0, 2e6 - 1),
                                    vals.Enum('MIN', 'MAX', 'DEF')),
                get_parser=int,
                docstring=('Allows collection of the data '
                           'being digitized the trigger. Reserves '
                           'memory for pretrigger samples up to the'
                           ' specified num. of pretrigger samples.'))

        self.add_parameter('sample_source',
                           label='Sample Timing Source',
                           set_cmd='SAMPle:SOURce {}',
                           get_cmd='SAMPle:SOURce?',
                           vals=vals.Enum('IMM', 'TIM'),
                           docstring=('Determines sampling time, immediate'
                                      ' or using sample_timer'))

        self.add_parameter('sample_timer',
                           label='Sample Timer',
                           set_cmd='SAMPle:TIMer {}',
                           get_cmd='SAMPle:TIMer?',
                           unit='s',
                           vals=vals.MultiType(vals.Numbers(0, 3600),
                                               vals.Enum('MIN', 'MAX', 'DEF')),
                           get_parser=float)

        self.add_parameter('sample_timer_minimum',
                           label='Minimal sample time',
                           get_cmd='SAMPle:TIMer? MIN',
                           get_parser=float,
                           unit='s')

        # SYSTEM
        self.add_parameter('error',
                           label='Error message',
                           get_cmd='SYSTem:ERRor?',
                           get_parser=errorparser)

        # The array parameter
        self.add_parameter('data_buffer', parameter_class=ArrayMeasurement)

        ####################################
        # Model-specific parameters

        if self.model in ['34465A', '34470A']:

            self.add_parameter('aperture_mode',
                               label='Aperture mode',
                               set_cmd='SENSe:VOLTage:DC:APERture:ENABled {}',
                               get_cmd='SENSe:VOLTage:DC:APERture:ENABled?',
                               val_mapping={
                                   'ON': 1,
                                   'OFF': 0
                               },
                               vals=vals.Enum('ON', 'OFF'))

            self.add_parameter('aperture_time',
                               label='Aperture time',
                               set_cmd=self._set_apt_time,
                               get_cmd='SENSe:VOLTage:DC:APERture?',
                               get_parser=float,
                               vals=vals.Numbers(*self._apt_times),
                               docstring=('Setting the aperture time '
                                          'automatically enables the aperture'
                                          ' mode.'))

        self.add_function('init_measurement', call_cmd='INIT')
        self.add_function('reset', call_cmd='*RST')
        self.add_function('display_clear', call_cmd=('DISPLay:TEXT:CLEar'))
        self.add_function('abort_measurement', call_cmd='ABORt')

        if not silent:
            self.connect_message()
Пример #5
0
    def _add_waveform_parameters(self):
        """
        Adds the parameters required to generate the standard waveforms

        The following prefixes are used for waveform parameters
            sq
            cz
            czd
            mcz
            custom

        """
        self.add_parameter('sq_amp', initial_value=.5,
                           # units is part of the total range of AWG8
                           label='Square pulse amplitude',
                           unit='dac value', vals=vals.Numbers(),
                           parameter_class=ManualParameter)
        self.add_parameter('sq_length', unit='s',
                           label='Square pulse length',
                           initial_value=40e-9,
                           vals=vals.Numbers(0, 100e-6),
                           parameter_class=ManualParameter)

        self.add_parameter('cz_length', vals=vals.Numbers(),
                           unit='s', initial_value=35e-9,
                           parameter_class=ManualParameter)
        self.add_parameter('cz_lambda_2', vals=vals.Numbers(),
                           initial_value=0,
                           parameter_class=ManualParameter)
        self.add_parameter('cz_lambda_3', vals=vals.Numbers(),
                           initial_value=0,
                           parameter_class=ManualParameter)
        self.add_parameter('cz_theta_f', vals=vals.Numbers(),
                           unit='deg',
                           initial_value=80,
                           parameter_class=ManualParameter)

        self.add_parameter('czd_length_ratio', vals=vals.Numbers(0, 1),
                           initial_value=0.5,
                           parameter_class=ManualParameter)
        self.add_parameter(
            'czd_lambda_2',
            docstring='lambda_2 parameter of the negative part of the cz pulse'
            ' if set to np.nan will default to the value of the main parameter',
            vals=vals.MultiType(vals.Numbers(), NP_NANs()),
            initial_value=np.nan,
            parameter_class=ManualParameter)

        self.add_parameter(
            'czd_lambda_3',
            docstring='lambda_3 parameter of the negative part of the cz pulse'
            ' if set to np.nan will default to the value of the main parameter',
            vals=vals.MultiType(vals.Numbers(), NP_NANs()),
            initial_value=np.nan,
            parameter_class=ManualParameter)
        self.add_parameter(
            'czd_theta_f',
            docstring='theta_f parameter of the negative part of the cz pulse'
            ' if set to np.nan will default to the value of the main parameter',
            vals=vals.MultiType(vals.Numbers(), NP_NANs()),
            unit='deg',
            initial_value=np.nan,
            parameter_class=ManualParameter)

        self.add_parameter('cz_freq_01_max', vals=vals.Numbers(),
                           # initial value is chosen to not raise errors
                           initial_value=6e9,
                           unit='Hz', parameter_class=ManualParameter)
        self.add_parameter('cz_J2', vals=vals.Numbers(), unit='Hz',
                            # initial value is chosen to not raise errors
                           initial_value=15e6,
                           parameter_class=ManualParameter)
        self.add_parameter('cz_freq_interaction', vals=vals.Numbers(),
                           # initial value is chosen to not raise errors
                           initial_value=5e9,
                           unit='Hz',
                           parameter_class=ManualParameter)

        self.add_parameter('cz_phase_corr_length', unit='s',
                           initial_value=5e-9, vals=vals.Numbers(),
                           parameter_class=ManualParameter)
        self.add_parameter('cz_phase_corr_amp',
                           unit='dac value',
                           initial_value=0, vals=vals.Numbers(),
                           parameter_class=ManualParameter)

        self.add_parameter('czd_amp_ratio',
                           docstring='Amplitude ratio for double sided CZ gate',
                           initial_value=1,
                           vals=vals.Numbers(),
                           parameter_class=ManualParameter)

        self.add_parameter('czd_amp_offset',
                           docstring='used to add an offset to the negative '
                           ' pulse that is used in the net-zero cz gate',
                           initial_value=0,
                           unit='dac value',
                           vals=vals.Numbers(),
                           parameter_class=ManualParameter)

        self.add_parameter('czd_double_sided',
                           initial_value=False,
                           vals=vals.Bool(),
                           parameter_class=ManualParameter)

        self.add_parameter('mcz_nr_of_repeated_gates',
                           initial_value=1, vals=vals.PermissiveInts(1, 40),
                           parameter_class=ManualParameter)
        self.add_parameter('mcz_gate_separation', unit='s',
                           label='Gate separation',  initial_value=0,
                           docstring=('Separtion between the start of CZ gates'
                                      'in the "multi_cz" gate'),
                           parameter_class=ManualParameter,
                           vals=vals.Numbers(min_value=0))

        self.add_parameter(
            'custom_wf',
            initial_value=np.array([]),
            label='Custom waveform',
            docstring=('Specifies a custom waveform, note that '
                       '`custom_wf_length` is used to cut of the waveform if'
                       'it is set.'),
            parameter_class=ManualParameter,
            vals=vals.Arrays())
        self.add_parameter(
            'custom_wf_length',
            unit='s',
            label='Custom waveform length',
            initial_value=np.inf,
            docstring=('Used to determine at what sample the custom waveform '
                       'is forced to zero. This is used to facilitate easy '
                       'cryoscope measurements of custom waveforms.'),
            parameter_class=ManualParameter,
            vals=vals.Numbers(min_value=0))
Пример #6
0
    def __init__(self, parent: '_Keysight_344xxA', name: str, **kwargs):
        super(Sample, self).__init__(parent, name, **kwargs)

        if self.parent.is_34465A_34470A:
            _max_sample_count = 1e9
        else:
            _max_sample_count = 1e6

        self.add_parameter('count',
                           label='Sample Count',
                           set_cmd='SAMPle:COUNt {}',
                           get_cmd='SAMPle:COUNt?',
                           vals=vals.MultiType(
                               vals.Numbers(1, _max_sample_count),
                               vals.Enum('MIN', 'MAX', 'DEF')),
                           get_parser=int,
                           docstring=textwrap.dedent("""\
            Specifies the number of measurements (samples) the instrument 
            takes per trigger.

            MAX selects 1 billion readings. However, when pretrigger is 
            selected, the maximum is 50,000 readings (without the MEM 
            option) or 2,000,000 readings (with the MEM option)"""))

        if self.parent.has_DIG:
            self.add_parameter('pretrigger_count',
                               label='Sample Pretrigger Count',
                               set_cmd='SAMPle:COUNt:PRETrigger {}',
                               get_cmd='SAMPle:COUNt:PRETrigger?',
                               vals=vals.MultiType(
                                   vals.Numbers(0, 2e6 - 1),
                                   vals.Enum('MIN', 'MAX', 'DEF')),
                               get_parser=int,
                               docstring=textwrap.dedent("""\
                Allows collection of the data being digitized the trigger. 
                Reserves memory for pretrigger samples up to the specified 
                num. of pretrigger samples."""))

        if self.parent.is_34465A_34470A:
            self.add_parameter('source',
                               label='Sample Timing Source',
                               set_cmd='SAMPle:SOURce {}',
                               get_cmd='SAMPle:SOURce?',
                               vals=vals.Enum('IMM', 'TIM'),
                               docstring=('Determines sampling time, '
                                          'immediate or using `sample.timer`'))

        self.add_parameter('timer',
                           label='Sample Timer',
                           set_cmd='SAMPle:TIMer {}',
                           get_cmd='SAMPle:TIMer?',
                           unit='s',
                           vals=vals.MultiType(vals.Numbers(0, 3600),
                                               vals.Enum('MIN', 'MAX', 'DEF')),
                           get_parser=float,
                           docstring=textwrap.dedent("""\
            The value is rounded by the instrument to the nearest step. For DC 
            measurements, the step size is 1 µs. For AC measurements, 
            it is AC bandwidth dependent.

            Special values are: MIN - recommended minimum, MAX - maximum, 
            DEF - default. In order to obtain the actual value of the 
            parameter that gets set when setting it to one of these special 
            values, just call the get method of the parameter, or use 
            corresponding parameters in this driver, 
            like `sample.timer_minimum`.

            Specifying a value that is between the absolute minimum (assumes 
            no range changes) and the recommended minimum value, 
            may generate a timing violation error when making measurements.

            Applying a value less than the absolute minimum will generate an 
            error."""))

        self.add_parameter('timer_minimum',
                           label='Minimal recommended sample time',
                           get_cmd='SAMPle:TIMer? MIN',
                           get_parser=float,
                           unit='s',
                           docstring=textwrap.dedent("""\
            This value is measurement dependent. It depends on such things 
            as the integration time, autozero on or off, autorange on or 
            off, and the measurement range. Basically, the minimum is 
            automatically determined by the instrument so that the sample 
            interval is always greater than the sampling time.

            Since the minimum value changes depending on configuration, a 
            command order dependency exists. You must completely configure 
            the measurement before setting the sample timer to minimum, 
            or you may generate an error. A complete configuration includes 
            such things as math statistics or scaling.

            When using autorange, the minimum value is the recommended value, 
            not the absolute minimum value. With autorange enabled, minimum 
            value is calculated assuming a single range change will occur 
            for every measurement (not multiple ranges, just one range up or 
            down per measurement)."""))
Пример #7
0
    def __init__(self, name: str, address: str, timeout=8, **kwargs):
        """
        Args:
            name: Name to use internally in QCoDeS
            address: VISA ressource address COM4 is the currently connected usb port)
            timeout: for the serial communication
        """
        super().__init__(name, **kwargs)

        self.address = address
        self.terminator = '\n'
        self._open_serial_connection(timeout)

        self._ac_init = False
        self._ac_ampl = False
        self._ac_freq = False

        self.add_parameter('current',
                           label='Current',
                           get_cmd='SOUR:CURR?',
                           set_cmd='SOUR:CURR {}',
                           get_parser=float,
                           unit='A',
                           vals=vals.Numbers(-105e-3, 105e-3))
        self.add_parameter('output',
                           get_cmd='OUTP:STAT?',
                           set_cmd='OUTP:STAT {}',
                           get_parser=int,
                           set_parser=parse_output_bool,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('range',
                           get_cmd='CURR:RANG?',
                           set_cmd='CURR:RANG {}',
                           get_parser=float,
                           unit='A',
                           vals=vals.Numbers(-105e-3, 105e-3))
        self.add_parameter('auto_range',
                           get_cmd='CURR:RANG:AUTO?',
                           set_cmd='CURR:RANG:AUTO {}',
                           get_parser=int,
                           set_parser=parse_output_bool,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('compliance',
                           get_cmd='CURR:COMP?',
                           set_cmd='CURR:COMP {}',
                           unit='V',
                           get_parser=float,
                           vals=vals.Numbers(-.1, 105))
        self.add_parameter('delay',
                           unit='s',
                           get_cmd='SOUR:DEL?',
                           set_cmd='SOUR:DEL {}',
                           get_parser=float,
                           vals=vals.Numbers(0.001, 999999.999))
        self.add_parameter('filter',
                           get_cmd='CURR:FILT?',
                           set_cmd='CURR:FILT {}',
                           get_parser=int,
                           set_parser=parse_output_bool,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('speed',
                           get_cmd='OUTP:RESP?',
                           set_cmd='OUTP:RESP {}',
                           get_parser=str,
                           vals=vals.Enum('slow', 'fast', 'SLOW', 'FAST'))
        self.add_parameter('display',
                           snapshot_get=False,
                           get_cmd='DISP:ENAB?',
                           set_cmd='DISP:ENAB {}',
                           get_parser=int,
                           set_parser=parse_output_bool,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('beeper',
                           snapshot_get=False,
                           get_cmd='SYST:BEEP?',
                           set_cmd='SYST:BEEP {}',
                           get_parser=int,
                           set_parser=parse_output_bool,
                           vals=vals.Enum(*boolcheck))

        self.add_parameter('AC_amplitude',
                           get_cmd='SOUR:WAVE:AMPL?',
                           set_cmd=self._setac_amplitude,
                           get_parser=float,
                           unit='A',
                           vals=vals.Numbers(2e-12, 0.105))
        self.add_parameter('AC_frequency',
                           get_cmd='SOUR:WAVE:FREQ?',
                           set_cmd=self._setac_frequency,
                           get_parser=float,
                           unit='Hz',
                           vals=vals.Numbers(0, 1e5))
        self.add_parameter('AC_offset',
                           get_cmd='SOUR:WAVE:OFFS?',
                           set_cmd='SOUR:WAVE:OFFS {}',
                           get_parser=float,
                           unit='A',
                           vals=vals.Numbers(-0.105, 0.105))
        self.add_parameter('AC_duration_time',
                           get_cmd='SOUR:WAVE:DUR:TIME?',
                           set_cmd='SOUR:WAVE:DUR:TIME {}',
                           get_parser=float,
                           unit='s',
                           vals=vals.MultiType(
                               vals.Enum('INF'),
                               vals.Numbers(100e-9, 999999.999)))
        self.add_parameter('AC_duration_cycles',
                           get_cmd='SOUR:WAVE:DUR:CYCL?',
                           set_cmd='SOUR:WAVE:DUR:CYCL {}',
                           get_parser=float,
                           unit='cycles',
                           vals=vals.MultiType(
                               vals.Enum('INF'),
                               vals.Numbers(0.001, 99999999900)))
        self.add_parameter('AC_phasemark',
                           get_cmd='SOUR:WAVE:PMAR:STAT?',
                           set_cmd='SOUR:WAVE:PMAR:STAT {}',
                           get_parser=int,
                           set_parser=parse_output_bool,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('AC_phasemark_offset',
                           get_cmd='SOUR:WAVE:PMAR?',
                           set_cmd='SOUR:WAVE:PMAR {}',
                           get_parser=float,
                           unit='degrees',
                           vals=vals.Numbers(0, 360))
        self.add_parameter('AC_ranging',
                           get_cmd='SOUR:WAVE:RANG?',
                           set_cmd='SOUR:WAVE:RANG {}',
                           get_parser=str,
                           vals=vals.Enum('BEST', 'best', 'FIX', 'fix',
                                          'FIXED', 'fixed'))

        self.connect_message()
Пример #8
0
    def __init__(self, name, address, **kwargs):
        super().__init__(name, address, terminator='\n', timeout=20, **kwargs)

        self.add_parameter('trigger_mode',
                           label='Trigger mode',
                           unit='',
                           get_cmd='OUTPut:TRIGger:MODE?',
                           get_parser=str,
                           set_cmd='OUTPut:TRIGger:MODE {}',
                           vals=vals.Enum('TRIGger', 'TRIG', 'SYNC'))

        #: Source/output parameters, 2 channels
        for src in [1, 2]:

            #: Outputs
            self.add_parameter('impedance_output{}'.format(src),
                               label='Output {} impedance'.format(src),
                               unit='Ohm',
                               get_cmd='OUTPut{}:IMPedance?'.format(src),
                               get_parser=float,
                               set_cmd='OUTPut{}:IMPedance {{}}'.format(src),
                               vals=vals.Strings())
            self.add_parameter('polarity_output{}'.format(src),
                               label='Output {} polarity'.format(src),
                               unit='',
                               get_cmd='OUTPut{}:POLarity?'.format(src),
                               get_parser=str,
                               set_cmd='OUTPut{}:POLarity {{}}'.format(src),
                               vals=vals.Enum('NORMal', 'NORM', 'INVerted',
                                              'INV'))
            self.add_parameter('state_output{}'.format(src),
                               label='Output {} state'.format(src),
                               unit='',
                               get_cmd='OUTPut{}:STATe?'.format(src),
                               get_parser=lambda x: bool(int(x)),
                               set_cmd='OUTPut{}:STATe {{}}'.format(src),
                               vals=vals.Enum('OFF', 0, 'ON', 1))

            #: Amplitude modulation
            self.add_parameter('am_depth{}'.format(src),
                               label='Source {} AM depth'.format(src),
                               unit='%',
                               get_cmd='SOURce{}:AM:DEPTh?'.format(src),
                               get_parser=float,
                               set_cmd='SOURce{}:AM:DEPTh {{}}'.format(src),
                               vals=vals.Strings())

            #: Frequency modulation
            self.add_parameter(
                'fm_deviation{}'.format(src),
                label='Source {} FM deviation'.format(src),
                unit='Hz',
                get_cmd='SOURce{}:FM:DEViation?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:FM:DEViation {{}}'.format(src),
                vals=vals.Strings())

            #: Phase modulation
            self.add_parameter(
                'pm_deviation{}'.format(src),
                label='Source {} PM deviation'.format(src),
                unit='Radians',
                get_cmd='SOURce{}:PM:DEViation?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:PM:DEViation {{}}'.format(src),
                vals=vals.Strings())

            #: Pulse-width modulation
            self.add_parameter(
                'pwm_duty_deviation{}'.format(src),
                label='Source {} PWM duty cycle deviation'.format(src),
                unit='%',
                get_cmd='SOURce{}:PWM:DEViation:DCYCle?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:PWM:DEViation:DCYCle {{}}'.format(src),
                vals=vals.Numbers(min_value=0, max_value=100))

            #: Amplitude, frequency, phase, and pulse-width modulation
            for mod_type in ['AM', 'FM', 'PM', 'PWM']:
                self.add_parameter(
                    '{}_internal_freq{}'.format(mod_type.lower(), src),
                    label='Source {} {} interal frequency'.format(
                        src, mod_type),
                    unit='Hz',
                    get_cmd='SOURce{}:{}:INTernal:FREQuency?'.format(
                        src, mod_type),
                    get_parser=float,
                    set_cmd='SOURce{}:{}:INTernal:FREQuency {{}}'.format(
                        src, mod_type),
                    vals=vals.Strings())
                self.add_parameter(
                    '{}_internal_function{}'.format(mod_type.lower(), src),
                    label='Source {} {} interal function'.format(
                        src, mod_type),
                    unit='',
                    get_cmd='SOURce{}:{}:INTernal:FUNCtion?'.format(
                        src, mod_type),
                    get_parser=str,
                    set_cmd='SOURce{}:{}:INTernal:FUNCtion {{}}'.format(
                        src, mod_type),
                    vals=vals.Enum('SINusoid', 'SIN', 'SQUare', 'SQU',
                                   'TRIangle', 'TRI', 'RAMP', 'NRAMp', 'NRAM',
                                   'PRNoise', 'PRN', 'USER', 'USER1', 'USER2',
                                   'USER3', 'USER4', 'EMEMory', 'EMEM',
                                   'EFILe', 'EFIL'))
                self.add_parameter(
                    '{}_internal_efile{}'.format(mod_type.lower(), src),
                    label='Source {} {} interal EFile'.format(src, mod_type),
                    unit='',
                    get_cmd='SOURce{}:{}:INTernal:FUNCtion:EFILe?'.format(
                        src, mod_type),
                    get_parser=str,
                    set_cmd='SOURce{}:{}:INTernal:FUNCtion:EFILe {{}}'.format(
                        src, mod_type),
                    vals=vals.Strings())
                self.add_parameter(
                    '{}_internal_source{}'.format(mod_type.lower(), src),
                    label='Source {} {} source'.format(src, mod_type),
                    unit='',
                    get_cmd='SOURce{}:{}:SOURce?'.format(src, mod_type),
                    get_parser=str,
                    set_cmd='SOURce{}:{}:SOURce? {{}}'.format(src, mod_type),
                    vals=vals.Enum('INTernal', 'INT', 'EXTernal', 'EXT'))
                self.add_parameter(
                    '{}_state{}'.format(mod_type.lower(), src),
                    label='Source {} {} interal state'.format(src, mod_type),
                    unit='',
                    get_cmd='SOURce{}:{}:STATe?'.format(src, mod_type),
                    get_parser=lambda x: bool(int(x)),
                    set_cmd='SOURce{}:{}:STATe {{}}'.format(src, mod_type),
                    vals=vals.Enum('OFF', 0, 'ON', 1))

            #: Burst mode
            self.add_parameter('burst_mode{}'.format(src),
                               label='Source {} burst mode'.format(src),
                               unit='',
                               get_cmd='SOURce{}:BURSt:MODE?'.format(src),
                               get_parser=str,
                               set_cmd='SOURce{}:BURSt:MODE {{}}'.format(src),
                               vals=vals.Enum('TRIGgered', 'TRIG', 'GATed',
                                              'GAT'))
            self.add_parameter(
                'burst_ncycles{}'.format(src),
                label='Source {} burst N cycles'.format(src),
                unit='',
                get_cmd='SOURce{}:BURSt:NCYCles?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:BURSt:NCYCles {{}}'.format(src),
                vals=vals.MultiType(
                    vals.Ints(min_value=1, max_value=1000000),
                    vals.Enum('INFinity', 'INF', 'MAXimum', 'MAX', 'MINimum',
                              'MIN')))
            self.add_parameter('burst_state{}'.format(src),
                               label='Source {} burst state'.format(src),
                               unit='',
                               get_cmd='SOURce{}:BURSt:STATe?'.format(src),
                               get_parser=lambda x: bool(int(x)),
                               set_cmd='SOURce{}:BURSt:STATe {{}}'.format(src),
                               vals=vals.Enum('OFF', 0, 'ON', 1))
            self.add_parameter(
                'burst_tdelay{}'.format(src),
                label='Source {} burst time delay'.format(src),
                unit='s',
                get_cmd='SOURce{}:BURSt:TDELay?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:BURSt:TDELay {{}}'.format(src),
                vals=vals.Strings())

            if src == 1:
                combine_enum = ('NOISe', 'NOIS', 'EXTernal', 'EXT', 'BOTH', '')
            else:
                combine_enum = ('NOISe', 'NOIS', '')
            self.add_parameter(
                'combine{}'.format(src),
                label='Source {} combine signals'.format(src),
                unit='',
                get_cmd='SOURce{}:COMBine:FEED?'.format(src),
                get_parser=str,
                set_cmd='SOURce{}:COMBine:FEED {{}}'.format(src),
                vals=vals.Enum(combine_enum))

            #: Frequency controls
            self.add_parameter(
                'center_freq{}'.format(src),
                label='Source {} center frequency'.format(src),
                unit='Hz',
                get_cmd='SOURce{}:FREQuency:CENTer?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:FREQuency:CENTer {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter(
                'freq_concurrent{}'.format(src),
                label='Source {} concurrent frequency'.format(src),
                unit='',
                get_cmd='SOURce{}:FREQuency:CONCurrent?'.format(src),
                get_parser=lambda x: bool(int(x)),
                set_cmd='SOURce{}:FREQuency:CONCurrent {{}}'.format(src),
                vals=vals.Enum('OFF', 0, 'ON', 1))
            self.add_parameter(
                'freq_cw{}'.format(src),
                label='Source {} continuous frequency'.format(src),
                unit='Hz',
                get_cmd='SOURce{}:FREQuency:CW?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:FREQuency:CW {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter(
                'freq_fixed{}'.format(src),
                label='Source {} fixed frequency'.format(src),
                unit='Hz',
                get_cmd='SOURce{}:FREQuency:FIXed?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:FREQuency:FIXed {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter(
                'freq_mode{}'.format(src),
                label='Source {} frequency mode'.format(src),
                unit='',
                get_cmd='SOURce{}:FREQuency:MODE?'.format(src),
                get_parser=str,
                set_cmd='SOURce{}:FREQuency:MODE {{}}'.format(src),
                vals=vals.Enum('CW', 'FIXed', 'FIX', 'SWEep', 'SWE'))
            self.add_parameter(
                'freq_span{}'.format(src),
                label='Source {} frequency span'.format(src),
                unit='Hz',
                get_cmd='SOURce{}:FREQuency:SPAN?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:FREQuency:SPAN {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter(
                'freq_start{}'.format(src),
                label='Source {} frequency start'.format(src),
                unit='Hz',
                get_cmd='SOURce{}:FREQuency:STARt?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:FREQuency:STARt {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter(
                'freq_stop{}'.format(src),
                label='Source {} frequency stop'.format(src),
                unit='Hz',
                get_cmd='SOURce{}:FREQuency:STOP?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:FREQuency:STOP {{}}'.format(src),
                vals=vals.Strings())

            #: FSK modulation
            self.add_parameter(
                'fsk_freq{}'.format(src),
                label='Source {} FSK frequency'.format(src),
                unit='Hz',
                get_cmd='SOURce{}:FSKey:FREQuency?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:FSKey:FREQuency {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter(
                'fsk_internal_rate{}'.format(src),
                label='Source {} FSK internal rate'.format(src),
                unit='Hz',
                get_cmd='SOURce{}:FSKey:INTernal:RATE?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:FSKey:INTernal:RATE {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter(
                'fsk_source{}'.format(src),
                label='Source {} FSK source'.format(src),
                unit='',
                get_cmd='SOURce{}:FSKey:SOURce?'.format(src),
                get_parser=str,
                set_cmd='SOURce{}:FSKey:SOURce {{}}'.format(src),
                vals=vals.Enum('INTernal', 'INT', 'EXTernal', 'EXT'))
            self.add_parameter('fsk_state{}'.format(src),
                               label='Source {} FSK state'.format(src),
                               unit='',
                               get_cmd='SOURce{}:FSKey:STATe?'.format(src),
                               get_parser=lambda x: bool(int(x)),
                               set_cmd='SOURce{}:FSKey:STATe {{}}'.format(src),
                               vals=vals.Enum('OFF', 0, 'ON', 1))

            #: Function parameters
            self.add_parameter(
                'function_efile{}'.format(src),
                label='Source {} function efile'.format(src),
                unit='',
                get_cmd='SOURce{}:FUNCtion:EFILe?'.format(src),
                get_parser=str,
                set_cmd='SOURce{}:FUNCtion:EFILe {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter(
                'function_ramp_symmetry{}'.format(src),
                label='Source {} function ramp symmetry'.format(src),
                unit='%',
                get_cmd='SOURce{}:FUNCtion:RAMP:SYMMetry?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:FUNCtion:RAMP:SYMMetry {{}}'.format(src),
                vals=vals.Numbers(min_value=0, max_value=100))
            self.add_parameter(
                'function_shape{}'.format(src),
                label='Source {} function shape'.format(src),
                unit='',
                get_cmd='SOURce{}:FUNCtion:SHAPe?'.format(src),
                get_parser=str,
                set_cmd='SOURce{}:FUNCtion:SHAPe {{}}'.format(src),
                vals=vals.Enum('SINusoid', 'SIN', 'SQUare', 'SQU', 'TRIangle',
                               'TRI', 'RAMP', 'NRAMp', 'NRAM', 'PRNoise',
                               'PRN', 'USER', 'USER1', 'USER2', 'USER3',
                               'USER4', 'EMEMory', 'EMEM', 'EFILe', 'EFIL',
                               'USER', 'USER1', 'USER2', 'USER3', 'USER4',
                               'EMEMory', 'EMEM', 'EFILe', 'EFIL'))

            #: Phase parameters
            self.add_parameter(
                'phase{}'.format(src),
                label='Source {} phase'.format(src),
                unit='Radians',
                get_cmd='SOURce{}:PHASe:ADJust?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:PHASe:ADJust {{}}'.format(src),
                vals=vals.Strings())

            #: Pulse parameters
            self.add_parameter(
                'pulse_duty_cycle{}'.format(src),
                label='Source {} pulse duty cycle'.format(src),
                unit='%',
                get_cmd='SOURce{}:PULSe:DCYCle?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:PULSe:DCYCle {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter('pulse_delay{}'.format(src),
                               label='Source {} pulse delay'.format(src),
                               unit='s',
                               get_cmd='SOURce{}:PULSe:DELay?'.format(src),
                               get_parser=float,
                               set_cmd='SOURce{}:PULSe:DELay {{}}'.format(src),
                               vals=vals.Strings())
            self.add_parameter('pulse_hold{}'.format(src),
                               label='Source {} pulse hold'.format(src),
                               unit='',
                               get_cmd='SOURce{}:PULSe:HOLD?'.format(src),
                               get_parser=str,
                               set_cmd='SOURce{}:PULSe:HOLD {{}}'.format(src),
                               vals=vals.Enum('WIDTh', 'WIDT', 'DUTY'))
            self.add_parameter(
                'pulse_period{}'.format(src),
                label='Source {} pulse period'.format(src),
                unit='s',
                get_cmd='SOURce{}:PULSe:PERiod?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:PULSe:PERiod {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter(
                'pulse_trans_lead{}'.format(src),
                label='Source {} pulse leading edge time'.format(src),
                unit='s',
                get_cmd='SOURce{}:PULSe:TRANsition:LEADing?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:PULSe:TRANsition:LEADing {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter(
                'pulse_trans_trail{}'.format(src),
                label='Source {} pulse trailing edge time'.format(src),
                unit='s',
                get_cmd='SOURce{}:PULSe:TRANsition:TRAiling?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:PULSe:TRANsition:TRAiling {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter('pulse_width{}'.format(src),
                               label='Source {} pulse width'.format(src),
                               unit='s',
                               get_cmd='SOURce{}:PULSe:WIDTh?'.format(src),
                               get_parser=float,
                               set_cmd='SOURce{}:PULSe:WIDTh {{}}'.format(src),
                               vals=vals.Strings())

            #: Sweep parameters
            self.add_parameter('sweep_hold_time{}'.format(src),
                               label='Source {} sweep hold time'.format(src),
                               unit='s',
                               get_cmd='SOURce{}:SWEep:HTIMe?'.format(src),
                               get_parser=float,
                               set_cmd='SOURce{}:SWEep:HTIMe {{}}'.format(src),
                               vals=vals.Strings())
            self.add_parameter('sweep_mode{}'.format(src),
                               label='Source {} sweep mode'.format(src),
                               unit='',
                               get_cmd='SOURce{}:SWEep:MODE?'.format(src),
                               get_parser=str,
                               set_cmd='SOURce{}:SWEep:MODE {{}}'.format(src),
                               vals=vals.Enum('AUTO', 'MANual', 'MAN'))
            self.add_parameter('sweep_return_time{}'.format(src),
                               label='Source {} sweep return time'.format(src),
                               unit='s',
                               get_cmd='SOURce{}:SWEep:RTIMe?'.format(src),
                               get_parser=float,
                               set_cmd='SOURce{}:SWEep:RTIMe {{}}'.format(src),
                               vals=vals.Strings())
            self.add_parameter(
                'sweep_spacing{}'.format(src),
                label='Source {} sweep spacing'.format(src),
                unit='',
                get_cmd='SOURce{}:SWEep:SPACing?'.format(src),
                get_parser=str,
                set_cmd='SOURce{}:SWEep:SPACing {{}}'.format(src),
                vals=vals.Enum('LINear', 'LIN', 'LOGarithmic', 'LOG'))
            self.add_parameter('sweep_time{}'.format(src),
                               label='Source {} sweep time'.format(src),
                               unit='s',
                               get_cmd='SOURce{}:SWEep:TIME?'.format(src),
                               get_parser=float,
                               set_cmd='SOURce{}:SWEep:TIME {{}}'.format(src),
                               vals=vals.Strings())

            #: Voltage parameters
            self.add_parameter(
                'voltage_concurrent{}'.format(src),
                label='Source {} concurrent voltage'.format(src),
                unit='',
                get_cmd='SOURce{}:VOLTage:CONCurrent:STATe?'.format(src),
                get_parser=lambda x: bool(int(x)),
                set_cmd='SOURce{}:VOLTage:CONCurrent:STATe {{}}'.format(src),
                vals=vals.Enum('OFF', 0, 'ON', 1))
            self.add_parameter(
                'voltage_high{}'.format(src),
                label='Source {} high voltage level'.format(src),
                unit='V',
                get_cmd='SOURce{}:VOLTage:LEVel:IMMediate:HIGH?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:VOLTage:LEVel:IMMediate:HIGH {{}}'.format(
                    src),
                vals=vals.Strings())
            self.add_parameter(
                'voltage_low{}'.format(src),
                label='Source {} low voltage level'.format(src),
                unit='V',
                get_cmd='SOURce{}:VOLTage:LEVel:IMMediate:LOW?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:VOLTage:LEVel:IMMediate:LOW {{}}'.format(
                    src),
                vals=vals.Strings())
            self.add_parameter(
                'voltage_offset{}'.format(src),
                label='Source {} voltage offset'.format(src),
                unit='V',
                get_cmd='SOURce{}:VOLTage:LEVel:IMMediate:OFFSet?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:VOLTage:LEVel:IMMediate:OFFSet {{}}'.format(
                    src),
                vals=vals.Strings())
            self.add_parameter(
                'voltage_unit{}'.format(src),
                label='Source {} voltage unit'.format(src),
                unit='',
                get_cmd='SOURce{}:VOLTage:UNIT?'.format(src),
                get_parser=str,
                set_cmd='SOURce{}:VOLTage:UNIT {{}}'.format(src),
                vals=vals.Enum('VPP', 'VRMS', 'DBM'))
            self.add_parameter(
                'voltage_amplitude{}'.format(src),
                label='Source {} voltage amplitude'.format(src),
                unit=getattr(self, 'voltage_unit{}'.format(src))(),
                get_cmd='SOURce{}:VOLTage:LEVel:IMMediate:AMPLitude?'.format(
                    src),
                get_parser=float,
                set_cmd='SOURce{}:VOLTage:LEVel:IMMediate:AMPLitude {{}}'.
                format(src),
                vals=vals.Strings())
            self.add_parameter(
                'voltage_limit_high{}'.format(src),
                label='Source {} voltage limit high'.format(src),
                unit='V',
                get_cmd='SOURce{}:VOLTage:LIMit:HIGH?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:VOLTage:LIMit:HIGH {{}}'.format(src),
                vals=vals.Strings())
            self.add_parameter(
                'voltage_limit_low{}'.format(src),
                label='Source {} voltage limit low'.format(src),
                unit='V',
                get_cmd='SOURce{}:VOLTage:LIMit:LOW?'.format(src),
                get_parser=float,
                set_cmd='SOURce{}:VOLTage:LIMit:LOW {{}}'.format(src),
                vals=vals.Strings())

        #: Noise parameters
        for src in [3, 4]:
            self.add_parameter(
                'noise_level{}'.format(src),
                label='Source {} noise level'.format(src),
                unit='%',
                get_cmd='SOURce{}:POWer:LEVel:IMMediate:AMPLitude?'.format(
                    src),
                get_parser=float,
                set_cmd='SOURce{}:POWer:LEVel:IMMediate:AMPLitude {{}}'.format(
                    src),
                vals=vals.Strings())

        self.add_parameter('ref_osc_source',
                           label='Reference clock source'.format(src),
                           unit='',
                           get_cmd='SOURce:ROSCillator:SOURce?',
                           get_parser=str,
                           set_cmd='SOURce:ROSCillator:SOURce {}',
                           vals=vals.Enum('INTernal', 'INT', 'EXTernal',
                                          'EXT'))

        #: Trigger parameters
        self.add_parameter('trigger_slope',
                           label='Trigger slope',
                           unit='',
                           get_cmd='TRIGger:SEQuence:SLOPe?',
                           get_parser=str,
                           set_cmd='TRIGger:SEQuence:SLOPe {}',
                           vals=vals.Enum('POSitive', 'POS', 'NEGative',
                                          'NEG'))
        self.add_parameter('trigger_source',
                           label='Trigger source',
                           unit='',
                           get_cmd='TRIGger:SEQuence:SOURce?',
                           get_parser=str,
                           set_cmd='TRIGger:SEQuence:SOURce {}',
                           vals=vals.Enum('TIMer', 'TIM', 'EXTernal', 'EXT'))
        self.add_parameter('trigger_timer',
                           label='Trigger timer period',
                           unit='s',
                           get_cmd='TRIGger:SEQuence:TIMer?',
                           get_parser=float,
                           set_cmd='TRIGger:SEQuence:TIMer {}',
                           vals=vals.Strings())

        self.snapshot(update=True)
        self.connect_message()
Пример #9
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)

        # Initialize channels
        self._input_channels = {
            'ext1': Channel(instrument_name=self.instrument_name(),
                            name='ext1', input=True),
            'ext2': Channel(instrument_name=self.instrument_name(),
                            name='ext2', input=True),
            'int1': Channel(instrument_name=self.instrument_name(),
                            name='int1', input=True),
            'int2': Channel(instrument_name=self.instrument_name(),
                            name='int2', input=True),
            'I': Channel(instrument_name=self.instrument_name(),
                         name='I', input=True),
            'Q': Channel(instrument_name=self.instrument_name(),
                         name='Q', input=True)
        }
        self._output_channels = {
            'RF_out': Channel(instrument_name=self.instrument_name(),
                              name='RF_out', output=True),
        }

        self._channels = {
            **self._input_channels,
            **self._output_channels,
            'trig_in': Channel(instrument_name=self.instrument_name(),
                               name='trig_in', input=True),
            'pattern_trig_in': Channel(instrument_name=self.instrument_name(),
                                       name='pattern_trig_in', input=True)
        }

        self.pulse_implementations = [
            SinePulseImplementation(
                pulse_requirements=[('frequency', {'min': 250e3, 'max': 44e9})]
            ),
            MultiSinePulseImplementation(),
            SingleWaveformPulseImplementation(),
            FrequencyRampPulseImplementation(
                pulse_requirements=[
                    ('frequency_start', {'min': 250e3, 'max': 44e9}),
                    ('frequency_stop', {'min': 250e3, 'max': 44e9})]
            )
        ]

        self.add_parameter('envelope_padding',
                           unit='s',
                           set_cmd=None,
                           initial_value=0,
                           vals=vals.Numbers(min_value=0, max_value=10e-3),
                           docstring="Padding for any pulses that use either "
                                     "IQ and/or FM modulation. This is to "
                                     "ensure that any such pulses start before "
                                     "the gate marker pulse, and end afterwards. "
                                     "This is ignored for chirp pulses where "
                                     "FM_mode = 'IQ'.")
        self.envelope_IQ = Parameter(
            set_cmd=None,
            vals=vals.Bool(),
            initial_value=True,
            docstring="Apply the envelope padding to the IQ pulse instead of marker pulse."
                      "If True, the marker pulse length equals the pulse length, and the "
                      "I and Q pulses are extended by the envelope padding "
                      "before (after) the pulse start (stop) time. "
                      "If False, the marker pulse starts before (after) the pulse start (stop) "
                      "time, and the IQ pulses starts (stops) at the pulse start (stop) time."
                      "This means that there might be some leakage at the carrier frequency "
                      "when the IQ is zero, but the marker pulse is still high."
        )
        self.add_parameter('I_phase_correction',
                           unit='deg',
                           set_cmd=None,
                           initial_value=0,
                           docstring="Additional phase added to I pulse, which compensates "
                                     "any phase mismatch between I and Q components. Only for "
                                     "FM_mode = 'IQ'.")
        self.add_parameter('Q_phase_correction',
                           unit='deg',
                           set_cmd=None,
                           initial_value=0,
                           docstring="Additional phase added to Q pulse, which compensates "
                                     "any phase mismatch between Q and I components. Only for "
                                     "FM_mode = 'IQ'.")
        self.add_parameter('I_amplitude_correction',
                           unit='V',
                           set_cmd=None,
                           initial_value=0,
                           vals=vals.Numbers(min_value=-1, max_value=0),
                           docstring="Amplitude correction added to the amplitude of I pulse"
                                     "to compensate for any mismatch in amplitude/power "
                                     "between I and Q components. The correction is restricted "
                                     "in value between -1V to 0V to ensure the I/Q inputs do not "
                                     "receive signals above 1V. Only for FM_mode = 'IQ'.")
        self.add_parameter('Q_amplitude_correction',
                           unit='V',
                           set_cmd=None,
                           initial_value=0,
                           vals=vals.Numbers(min_value=-1, max_value=0),
                           docstring="Amplitude correction added to the amplitude of Q pulse"
                                     "to compensate for any mismatch in amplitude/power "
                                     "between Q and I components. The correction is restricted "
                                     "in value between -1V to 0V to ensure the I/Q inputs do not "
                                     "receive signals above 1V. Only for FM_mode = 'IQ'.")
        self.add_parameter('marker_amplitude',
                           unit='V',
                           set_cmd=None,
                           initial_value=1.5,
                           docstring="Amplitude of marker pulse used for gating")
        self.add_parameter('modulation_channel',
                           set_cmd=None,
                           initial_value='ext1',
                           vals=vals.Enum(*self._input_channels),
                           docstring="Channel to use for FM.")
        self.add_parameter('fix_frequency',
                           set_cmd=None,
                           initial_value=False,
                           vals=vals.Bool(),
                           docstring="Whether to fix frequency to current "
                                     "value, or to dynamically choose frequency"
                                     " during setup")
        self.add_parameter('fix_frequency_deviation',
                           set_cmd=None,
                           initial_value=False,
                           vals=vals.Bool(),
                           docstring="Whether to fix frequency_deviation to "
                                     "current value, or to dynamically choose "
                                     "deviation during setup")
        self.add_parameter('frequency_carrier_choice',
                           set_cmd=None,
                           initial_value='center',
                           vals=vals.MultiType(vals.Enum('min', 'center', 'max'),
                                               vals.Numbers()),
                           docstring='The choice for the microwave frequency, '
                                     'This is used if pulses with multiple '
                                     'frequencies are used, or if frequency '
                                     'modulation is needed. Ignored if '
                                     'fix_frequency = True. Can be either "max",'
                                     '"min", or "center", or a number which is '
                                     'the offset from the center')
        self.add_parameter('frequency',
                           unit='Hz',
                           set_cmd=None,
                           initial_value=None)
        self.add_parameter('frequency_deviation',
                           unit='Hz',
                           set_cmd=None,
                           initial_value=None)
        self.add_parameter('power',
                           unit='dBm',
                           set_cmd=None,
                           initial_value=None)
        self.add_parameter('IQ_modulation',
                           initial_value=None,
                           vals=vals.Enum('on', 'off'),
                           docstring='Whether to use IQ modulation. This '
                                     'cannot be directly set, but is determined '
                                     'by FM_mode and whether pulses have '
                                     'frequency_sideband not None.')
        self.add_parameter('IQ_channels',
                           initial_value='IQ',
                           vals=vals.Enum('IQ', 'I', 'Q'),
                           set_cmd=None,
                           docstring="Which channels to use for IQ modulation."
                                     "Double-sideband modulation is used if only 'I' or 'Q' "
                                     "is chosen, while single-sideband modulation is used when "
                                     "'IQ' is chosen.")
        self.add_parameter('force_IQ',
                           set_cmd=None,
                           initial_value=False,
                           vals=vals.Bool(),
                           docstring='Force IQ modulation to be enabled, even when'
                                     'outputting only a single frequency.')
        self.add_parameter('FM_mode',
                           set_cmd=None,
                           initial_value='ramp',
                           vals=vals.Enum('ramp', 'IQ'),
                           docstring="Type of frequency modulation used. "
                                     "Can be either 'ramp' in which case the "
                                     "internal FM is used by converting a DC "
                                     "amplitude from an ext port, or 'IQ', in "
                                     "which case the internal FM is turned off.")
Пример #10
0
    def __init__(self, name: str, address: str, **kwargs):
        super().__init__(name, address, terminator='\n', **kwargs)

        self.range_vals = {
            2e-3: 0,
            20e-3: 1,
            200e-3: 2,
            2: 3,
            20: 4,
            200: 5,
            2e3: 6,
            20e3: 7,
            200e3: 8,
            2e6: 9,
            np.nan: np.nan
        }
        self.excitation_vals = {
            20e-6: 0,
            60e-6: 1,
            200e-6: 2,
            600e-6: 3,
            2e-3: 4,
            6e-3: 5,
            20e-3: 6,
            np.nan: np.nan
        }
        self.dfilter_vals = {
            0.2: '00',
            0.4: '01',
            0.6: '02',
            0.8: '03',
            1.0: '04',
            1.6: '05',
            2.0: '06',
            3.0: '07',
            5.0: '08',
            7.0: '09',
            10.0: '10',
            15.0: '11',
            20.0: '12',
            30.0: '13',
            45.0: '14',
            60.0: '15',
            90.0: '16',
            120.0: '17',
            180.0: '18',
            300.0: '19',
            420.0: '20',
            600.0: '21',
            900.0: '22',
            1200.0: '23',
            1800.0: '24',
            np.nan: np.nan
        }
        self.afilter_vals = {
            0.01: 0,
            0.1: 1,
            0.3: 2,
            1.0: 3,
            3.0: 4,
            10.0: 5,
            30.0: 6
        }

        self.add_parameter('range',
                           set_cmd='Range {}',
                           val_mapping=self.range_vals,
                           get_cmd=partial(self.get_string_repeat, 'Get 6'),
                           get_parser=partial(self.get6parser, 'range'),
                           unit='Ohms')
        self.add_parameter('autorange',
                           set_cmd='Autorange {}',
                           vals=vals.Ints(0, 1))
        self.add_parameter('excitation',
                           set_cmd='Excitation {}',
                           get_cmd=partial(self.get_string_repeat, 'Get 6'),
                           get_parser=partial(self.get6parser, 'excitation'),
                           val_mapping=self.excitation_vals,
                           unit='V')
        self.add_parameter('exc_pct',
                           set_cmd='Varexc ={}',
                           set_parser=partial(zfill_parser, 2),
                           get_cmd=partial(self.get_string_repeat, 'Get 6'),
                           get_parser=partial(self.get6parser, 'exc_pct'),
                           vals=vals.Ints(5, 99))
        self.add_parameter('exc_pct_on',
                           set_cmd='Varexc {}',
                           vals=vals.Ints(0, 1))
        self.add_parameter('R_measure',
                           get_cmd=partial(self.get_string_repeat, 'Get 0'),
                           unit='Ohms',
                           get_parser=R_parser)
        self.add_parameter('DelR_measure',
                           get_cmd=partial(self.get_string_repeat, 'Get 2'),
                           get_parser=R_parser,
                           unit='Ohms')
        self.add_parameter('X_measure',
                           get_cmd=partial(self.get_string_repeat, 'Get 1'),
                           get_parser=R_parser)
        self.add_parameter('DelX_measure',
                           get_cmd=partial(self.get_string_repeat, 'Get 3'),
                           get_parser=R_parser)
        self.add_parameter('x10mode',
                           set_cmd='Mode {}',
                           get_cmd=partial(self.get_string_repeat, 'Get 6'),
                           get_parser=partial(self.get6parser, 'x10mode'),
                           vals=vals.Ints(0, 1))
        self.add_parameter('dfilter',
                           set_cmd=self.dfilter_set,
                           get_cmd=partial(self.get_string_repeat, 'Get 6'),
                           get_parser=partial(self.get6parser, 'dfilter'),
                           val_mapping=self.dfilter_vals,
                           unit='s')
        self.add_parameter('afilter',
                           set_cmd='Noise F={}',
                           val_mapping=self.afilter_vals,
                           unit='s')
        self.add_parameter('afilter_input',
                           set_cmd='Noise I={}',
                           val_mapping={
                               'delR': 0,
                               'delX': 1
                           })
        self.add_parameter('R_offset',
                           label='LR Resistance',
                           set_cmd='Offset {}',
                           set_parser=partial(offset_parser, 'R'),
                           get_cmd=partial(self.get_string_repeat, 'Get 4'),
                           get_parser=R_parser,
                           unit='Ohms',
                           vals=vals.MultiType(vals.Numbers(-99.9995, 99.9995),
                                               vals.Enum('R', 'X')))
        self.add_parameter('X_offset',
                           set_cmd='Offset {}',
                           set_parser=partial(offset_parser, 'X'),
                           get_cmd=partial(self.get_string_repeat, 'Get 5'),
                           get_parser=R_parser,
                           vals=vals.MultiType(vals.Numbers(-99.9995, 99.9995),
                                               vals.Enum('R', 'X')))
Пример #11
0
    def __init__(self, name: str, address: str, reset: bool=False, **kwargs):
        """
        Args:
            name: Name to use internally in QCoDeS
            address: VISA ressource address
            reset: Set Keithley to defaults? True or False
        """
        super().__init__(name, address, terminator='\n', **kwargs)

        self._ac_init = False
        self._ac_ampl = False
        self._ac_freq = False

        self.add_parameter('current',
                           label='Current',
                           get_cmd='SOUR:CURR?',
                           set_cmd='SOUR:CURR {}',
                           get_parser=float,
                           unit='A',
                           vals=vals.Numbers())
        self.add_parameter('output',
                           get_cmd='OUTP:STAT?',
                           set_cmd='OUTP:STAT {}',
                           get_parser=int,
                           set_parser=parse_output_bool,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('range',
                           get_cmd='CURR:RANG?',
                           set_cmd='CURR:RANG {}',
                           get_parser=float,
                           unit='A',
                           vals=vals.Numbers(-105e-3, 105e-3))
        self.add_parameter('auto_range',
                           get_cmd='CURR:RANG:AUTO?',
                           set_cmd='CURR:RANG:AUTO {}',
                           get_parser=int,
                           set_parser=parse_output_bool,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('compliance',
                           get_cmd='CURR:COMP?',
                           set_cmd='CURR:COMP {}',
                           unit='V',
                           get_parser=float,
                           vals=vals.Numbers(-.1, 105))
        self.add_parameter('delay',
                           unit='s',
                           get_cmd='SOUR:DEL?',
                           set_cmd='SOUR:DEL {}',
                           get_parser=float,
                           vals=vals.Numbers(0.001, 999999.999))
        self.add_parameter('filter',
                           get_cmd='CURR:FILT?',
                           set_cmd='CURR:FILT {}',
                           get_parser=int,
                           set_parser=parse_output_bool,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('speed',
                           get_cmd='OUTP:RESP?',
                           set_cmd='OUTP:RESP {}',
                           get_parser=str,
                           vals=vals.Enum('slow', 'fast', 'SLOW', 'FAST'))
        self.add_parameter('display',
                           snapshot_get=False,
                           get_cmd='DISP:ENAB?',
                           set_cmd='DISP:ENAB {}',
                           get_parser=int,
                           set_parser=parse_output_bool,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('beeper',
                           snapshot_get=False,
                           get_cmd='SYST:BEEP?',
                           set_cmd='SYST:BEEP {}',
                           get_parser=int,
                           set_parser=parse_output_bool,
                           vals=vals.Enum(*boolcheck))

        self.add_parameter('AC_amplitude',
                           get_cmd='SOUR:WAVE:AMPL?',
                           set_cmd=self._setac_amplitude,
                           get_parser=float,
                           unit='A',
                           vals=vals.Numbers(2e-12, 0.105))
        self.add_parameter('AC_frequency',
                           get_cmd='SOUR:WAVE:FREQ?',
                           set_cmd=self._setac_frequency,
                           get_parser=float,
                           unit='Hz',
                           vals=vals.Numbers(0, 1e5))
        self.add_parameter('AC_offset',
                           get_cmd='SOUR:WAVE:OFFS?',
                           set_cmd='SOUR:WAVE:OFFS {}',
                           get_parser=float,
                           unit='A',
                           vals=vals.Numbers(-0.105, 0.105))
        self.add_parameter('AC_duration_time',
                           get_cmd='SOUR:WAVE:DUR:TIME?',
                           set_cmd='SOUR:WAVE:DUR:TIME {}',
                           get_parser=float,
                           unit='s',
                           vals=vals.MultiType(vals.Enum('INF'),
                                               vals.Numbers(100e-9,
                                                            999999.999)))
        self.add_parameter('AC_duration_cycles',
                           get_cmd='SOUR:WAVE:DUR:CYCL?',
                           set_cmd='SOUR:WAVE:DUR:CYCL {}',
                           get_parser=float,
                           unit='cycles',
                           vals=vals.MultiType(vals.Enum('INF'),
                                               vals.Numbers(0.001,
                                                            99999999900)))
        self.add_parameter('AC_phasemark',
                           get_cmd='SOUR:WAVE:PMAR:STAT?',
                           set_cmd='SOUR:WAVE:PMAR:STAT {}',
                           get_parser=int,
                           set_parser=parse_output_bool,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('AC_phasemark_offset',
                           get_cmd='SOUR:WAVE:PMAR?',
                           set_cmd='SOUR:WAVE:PMAR {}',
                           get_parser=float,
                           unit='degrees',
                           vals=vals.Numbers(0, 360))
        self.add_parameter('AC_ranging',
                           get_cmd='SOUR:WAVE:RANG?',
                           set_cmd='SOUR:WAVE:RANG {}',
                           get_parser=str,
                           vals=vals.Enum('BEST', 'best', 'FIX', 'fix',
                                          'FIXED', 'fixed'))

        # Related to attached 2182(a) nanovoltmeter
        self.add_parameter('unit',
                           label='diff conductance unit',
                           get_cmd='UNIT?',
                           set_cmd='UNIT {}',
                           initial_value='OHMS',
                           get_parser=str,
                           vals=vals.Enum('V', 'ohms', 'OHMS', 'S', 'SIEM',
                                          'siem', 'siemens', 'SIEMENS'))
        self.add_parameter('k2182_present',
                           get_cmd='SOUR:DELT:NVPR?',
                           get_parser=int)
        self.add_parameter('delta_arm',
                           get_cmd='SOUR:DELT:ARM?',
                           get_parser=int)
        self.add_parameter('diff_arm',
                           get_cmd='SOUR:DCON:ARM?',
                           get_parser=int)
        self.add_parameter('delta_IV_sweep',  # STILL A WORK IN PROGRESS
                           snapshot_get=False,
                           get_cmd=self.delta_IV_sweep_get,
                           set_cmd=self.delta_IV_sweep_set,
                           get_parser=float,
                           set_parser=float)

        # These are only useable if you have connected to the Keithley 2182
        # Through an RS-232 port. Make sure to check the settings on the 2182
        # at set to GPIB: off, RS-232 on
        self.add_parameter('k2_measure',
                           snapshot_get=False,
                           get_cmd=partial(self.k2_read_cmd,
                                           'SENS:DATA:FRES?'),
                           get_parser=float,
                           unit='V')

        self.add_parameter('k2_range',
                           snapshot_get=False,
                           set_cmd='SYST:COMM:SER:SEND "VOLT:RANG {}"',
                           get_cmd=partial(self.k2_read_cmd, 'VOLT:RANG?'),
                           set_parser=float,
                           get_parser=float,
                           vals=vals.Numbers(0, 120))
        self.add_parameter('k2_nplc',
                           snapshot_get=False,
                           set_cmd='SYST:COMM:SER:SEND "VOLT:NPLC {}"',
                           get_cmd=partial(self.k2_read_cmd, 'VOLT:NPLC?'),
                           set_parser=float,
                           get_parser=float,
                           vals=vals.Numbers(0.01, 60))
        self.add_parameter('k2_line_sync',
                           snapshot_get=False,
                           set_cmd='SYST:COMM:SER:SEND "SYST:LSYN {}"',
                           get_cmd=partial(self.k2_read_cmd, 'SYST:LSYN?'),
                           set_parser=parse_output_bool,
                           get_parser=int,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('k2_front_autozero',
                           snapshot_get=False,
                           set_cmd='SYST:COMM:SER:SEND "SYST:FAZ {}"',
                           get_cmd=partial(self.k2_read_cmd, 'SYST:FAZ?'),
                           set_parser=parse_output_bool,
                           get_parser=int,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('k2_autozero',
                           snapshot_get=False,
                           set_cmd='SYST:COMM:SER:SEND "SYST:AZER {}"',
                           get_cmd=partial(self.k2_read_cmd, 'SYST:AZER?'),
                           set_parser=parse_output_bool,
                           get_parser=int,
                           vals=vals.Enum(*boolcheck))
        self.add_parameter('k2_dfilter_count',
                           snapshot_get=False,
                           get_cmd=partial(self.k2_read_cmd,
                                           'SENS:VOLT:DFIL:COUN?'),
                           set_cmd='SYST:COMM:SER:SEND "SENS:VOLT:DFIL:COUN {}"',
                           get_parser=int,
                           set_parser=int,
                           vals=vals.Ints(1, 100))
        self.add_parameter('k2_dfilter_window',
                           snapshot_get=False,
                           get_cmd=partial(self.k2_read_cmd,
                                           'SENS:VOLT:DFIL:WIND?'),
                           set_cmd='SYST:COMM:SER:SEND "SENS:VOLT:DFIL:WIND {}"',
                           get_parser=float,
                           set_parser=float,
                           vals=vals.Numbers(0.01, 10))
        self.add_parameter('k2_dfilter_type',
                           snapshot_get=False,
                           get_cmd=partial(self.k2_read_cmd,
                                           'SENS:VOLT:DFIL:TCON?'),
                           set_cmd='SYST:COMM:SER:SEND "SENS:VOLT:DFIL:TCON {}"',
                           vals=vals.Enum('MOV', 'REP'))

        self.add_function('abort_arm', call_cmd='SOUR:SWE:ABOR')
        self.add_function('reset', call_cmd='*RST')
        # TODO: Getting error messages doesn't work
        self.add_function('get_error', call_cmd='SYST:ERR?')

        if reset:
            self.reset()

        self.connect_message()
Пример #12
0
    def __init__(self, name, timeout=5, address=''):
        Instrument.__init__(self, name)
        self._address = address
        self._terminator = ''
        self.add_parameter('timeout',
                           unit='s',
                           initial_value=5,
                           parameter_class=ManualParameter,
                           vals=vals.MultiType(vals.Numbers(min_value=0),
                                               vals.Enum(None)))
        self.add_parameter('address',
                           unit='',
                           initial_value='',
                           parameter_class=ManualParameter,
                           vals=vals.Strings())
        self.add_parameter('DC_output',
                           label='DC Output (ON/OFF)',
                           parameter_class=ManualParameter,
                           vals=vals.Ints(0, 1))

        for i in range(1, 5):
            self.add_parameter('ch{}_state'.format(i),
                               initial_value=1,
                               label='Status channel {}'.format(i),
                               parameter_class=ManualParameter,
                               vals=vals.Ints(0, 1))
            self.add_parameter('ch{}_amp'.format(i),
                               initial_value=1.,
                               label='Amplitude channel {}'.format(i),
                               unit='Vpp',
                               parameter_class=ManualParameter,
                               vals=vals.Numbers(0.02, 4.5))
            self.add_parameter('ch{}_offset'.format(i),
                               initial_value=0,
                               label='Offset channel {}'.format(i),
                               unit='V',
                               parameter_class=ManualParameter,
                               vals=vals.Numbers(-.1, .1))
            self.add_parameter('ch{}_waveform'.format(i),
                               initial_value="",
                               label='Waveform channel {}'.format(i),
                               parameter_class=ManualParameter,
                               vals=vals.Strings())
            self.add_parameter('ch{}_direct_output'.format(i),
                               initial_value=1,
                               label='Direct output channel {}'.format(i),
                               parameter_class=ManualParameter,
                               vals=vals.Ints(0, 1))
            self.add_parameter('ch{}_filter'.format(i),
                               initial_value='INF',
                               label='Low pass filter channel {}'.format(i),
                               unit='Hz',
                               parameter_class=ManualParameter,
                               vals=vals.Enum(20e6, 100e6, 9.9e37, 'INF',
                                              'INFinity'))
            self.add_parameter('ch{}_DC_out'.format(i),
                               initial_value=0,
                               label='DC output level channel {}'.format(i),
                               unit='V',
                               parameter_class=ManualParameter,
                               vals=vals.Numbers(-3, 5))

            for j in range(1, 3):
                self.add_parameter('ch{}_m{}_del'.format(i, j),
                                   initial_value=0,
                                   label='Channel {} Marker {} delay'.format(
                                       i, j),
                                   unit='ns',
                                   parameter_class=ManualParameter,
                                   vals=vals.Numbers(0, 1))
                self.add_parameter(
                    'ch{}_m{}_high'.format(i, j),
                    initial_value=2,
                    label='Channel {} Marker {} high level'.format(i, j),
                    unit='V',
                    parameter_class=ManualParameter,
                    vals=vals.Numbers(-2.7, 2.7))
                self.add_parameter(
                    'ch{}_m{}_low'.format(i, j),
                    initial_value=0,
                    label='Channel {} Marker {} low level'.format(i, j),
                    unit='V',
                    parameter_class=ManualParameter,
                    vals=vals.Numbers(-2.7, 2.7))

        self.add_parameter('clock_freq',
                           label='Clock frequency',
                           unit='Hz',
                           vals=vals.Numbers(1e6, 1.2e9),
                           parameter_class=ManualParameter,
                           initial_value=1.2e9)

        self.awg_files = {}
        self.file = None
        self.stop()  # to init self._state
Пример #13
0
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)

        # Initialize channels
        self._input_channels = {
            'ext1': Channel(instrument_name=self.instrument_name(),
                            name='ext1', input=True),
            'ext2': Channel(instrument_name=self.instrument_name(),
                            name='ext2', input=True),
            'I': Channel(instrument_name=self.instrument_name(),
                            name='I', input=True),
            'Q': Channel(instrument_name=self.instrument_name(),
                            name='Q', input=True)
        }
        self._output_channels = {
            'RF_out': Channel(instrument_name=self.instrument_name(),
                              name='RF_out', output=True),
        }

        self._channels = {
            **self._input_channels,
            **self._output_channels,
            'trig_in': Channel(instrument_name=self.instrument_name(),
                               name='trig_in', input=True),
            'pattern_trig_in': Channel(instrument_name=self.instrument_name(),
                                       name='pattern_trig_in', input=True)
        }

        self.pulse_implementations = [
            SinePulseImplementation(
                pulse_requirements=[('frequency', {'min': 250e3, 'max': 44e9})]
            ),
            FrequencyRampPulseImplementation(
                pulse_requirements=[
                    ('frequency_start', {'min': 250e3, 'max': 44e9}),
                    ('frequency_stop', {'min': 250e3, 'max': 44e9})]
            )
        ]

        self.add_parameter('envelope_padding',
                           unit='s',
                           set_cmd=None,
                           initial_value=0,
                           vals=vals.Numbers(min_value=0, max_value=10e-3),
                           docstring="Padding for any pulses that use either "
                                     "IQ and/or FM modulation. This is to "
                                     "ensure that any such pulses start before "
                                     "the gate marker pulse, and end afterwards. "
                                     "This is ignored for chirp pulses where "
                                     "FM_mode = 'IQ'.")
        self.add_parameter('marker_amplitude',
                           unit='V',
                           set_cmd=None,
                           initial_value=1.5,
                           docstring="Amplitude of marker pulse used for gating")
        self.add_parameter('modulation_channel',
                           set_cmd=None,
                           initial_value='ext1',
                           vals=vals.Enum(*self._input_channels),
                           docstring="Channel to use for FM.")
        self.add_parameter('fix_frequency',
                           set_cmd=None,
                           initial_value=False,
                           vals=vals.Bool(),
                           docstring="Whether to fix frequency to current "
                                     "value, or to dynamically choose frequency"
                                     " during setup")
        self.add_parameter('fix_frequency_deviation',
                           set_cmd=None,
                           initial_value=False,
                           vals=vals.Bool(),
                           docstring="Whether to fix frequency_deviation to "
                                     "current value, or to dynamically choose "
                                     "deviation during setup")
        self.add_parameter('frequency_carrier_choice',
                           set_cmd=None,
                           initial_value='center',
                           vals=vals.MultiType(vals.Enum('min', 'center', 'max'),
                                           vals.Numbers()),
                           docstring='The choice for the microwave frequency, '
                                     'This is used if pulses with multiple '
                                     'frequencies are used, or if frequency '
                                     'modulation is needed. Ignored if '
                                     'fix_frequency = True. Can be either "max",'
                                     '"min", or "center", or a number which is '
                                     'the offset from the center')
        self.add_parameter('frequency',
                           unit='Hz',
                           set_cmd=None,
                           initial_value=None)
        self.add_parameter('frequency_deviation',
                           unit='Hz',
                           set_cmd=None,
                           initial_value=None)
        self.add_parameter('IQ_modulation',
                           initial_value=None,
                           vals=vals.Enum('on', 'off'),
                           docstring='Whether to use IQ modulation. This '
                                     'cannot be directly set, but is determined '
                                     'by FM_mode and whether pulses have '
                                     'frequency_sideband not None')
        self.add_parameter('FM_mode',
                           set_cmd=None,
                           initial_value='ramp',
                           vals=vals.Enum('ramp', 'IQ'),
                           docstring="Type of frequency modulation used. "
                                     "Can be either 'ramp' in which case the "
                                     "internal FM is used by converting a DC "
                                     "amplitude from an ext port, or 'IQ', in "
                                     "which case the internal FM is turned off.")
Пример #14
0
    def __init__(self, name: str = 'Pulsar', master_awg: str = None):
        """Pulsar constructor.

        Args:
            name: Instrument name.
            master_awg: Name of the AWG that triggers all the other AWG-s and
                should be started last (after other AWG-s are already
                waiting for a trigger.
        """

        super().__init__(name)

        self._sequence_cache = dict()
        self.reset_sequence_cache()

        self.add_parameter('master_awg',
                           parameter_class=InstrumentRefParameter,
                           initial_value=master_awg)
        self.add_parameter('inter_element_spacing',
                           vals=vals.MultiType(vals.Numbers(0),
                                               vals.Enum('auto')),
                           set_cmd=self._set_inter_element_spacing,
                           get_cmd=self._get_inter_element_spacing)
        self.add_parameter('reuse_waveforms',
                           initial_value=False,
                           parameter_class=ManualParameter,
                           vals=vals.Bool())
        self.add_parameter('use_sequence_cache',
                           initial_value=False,
                           parameter_class=ManualParameter,
                           vals=vals.Bool(),
                           set_parser=self._use_sequence_cache_parser)
        self.add_parameter('prepend_zeros',
                           initial_value=0,
                           vals=vals.Ints(),
                           parameter_class=ManualParameter)
        self.add_parameter('flux_crosstalk_cancellation',
                           initial_value=False,
                           parameter_class=ManualParameter)
        self.add_parameter('flux_channels',
                           initial_value=[],
                           parameter_class=ManualParameter)
        self.add_parameter('flux_crosstalk_cancellation_mtx',
                           initial_value=None,
                           parameter_class=ManualParameter)
        self.add_parameter('flux_crosstalk_cancellation_shift_mtx',
                           initial_value=None,
                           parameter_class=ManualParameter)
        self.add_parameter('resolve_overlapping_elements',
                           vals=vals.Bool(),
                           initial_value=False,
                           parameter_class=ManualParameter,
                           docstring='Flag determining whether overlapping '
                           'elements should be resolved by '
                           'combining them into one element. NB: '
                           'overlap resolution only applies to'
                           'non-trigger elements!')
        # This parameter can be used to record only a specified consecutive
        # subset of segments of a programmed hard sweep. This is used by the
        # sweep function FilteredSweep. The parameter expects a tuple of indices
        # indicating the first and the last segment to be measured. (Segments
        # with the property allow_filter set to False are always measured.)
        self.add_parameter('filter_segments',
                           set_cmd=self._set_filter_segments,
                           get_cmd=self._get_filter_segments,
                           initial_value=None)
        self.add_parameter('sigouts_on_after_programming',
                           initial_value=True,
                           parameter_class=ManualParameter,
                           vals=vals.Bool(),
                           docstring='Whether signal outputs should be '
                           'switched off automatically after '
                           'programming a AWGs. Can be set to '
                           'False to save time if it is ensured '
                           'that the channels are switched on '
                           'somewhere else.')
        self.add_parameter('trigger_pulse_parameters',
                           initial_value={},
                           label='trigger pulse parameters',
                           parameter_class=ManualParameter,
                           docstring='A dict whose keys are channel names and '
                           'whose values are dicts of pulse '
                           'parameters to overwrite the default '
                           'trigger pulse parameters whenever a '
                           'trigger pulse is played on the '
                           'respective channel. In addition, the '
                           'dict can contain keys of the form '
                           '{channel}_first to provide different '
                           'parameters for the first trigger pulse '
                           'on that channel in a sequence.')

        self._inter_element_spacing = 'auto'
        self.channels = set()  # channel names
        self.awgs: Set[str] = set()  # AWG names
        self.awg_interfaces: Dict[str, PulsarAWGInterface] = {}
        self.last_sequence = None
        self.last_elements = None
        self._awgs_with_waveforms = set()
        self.channel_groups = {}
        self.num_channel_groups = {}

        self._awgs_prequeried_state = False

        self._hash_to_wavename_table = {}
        self._filter_segments = None

        Pulsar._instance = self
Пример #15
0
    def __init__(self, name, address, silent=False, **kwargs):
        """
        Create an instance of the instrument.

        Args:
            name (str): Name used by QCoDeS. Appears in the DataSet
            address (str): Visa-resolvable instrument address.
            silent (bool): If True, the connect_message of the instrument
                is supressed. Default: False
        """

        warnings.warn(
            "This driver is old and will be removed from QCoDeS "
            "soon. Please use the Keysight_344xxA classes from the "
            "files "
            "instrument_drivers/Keysight"
            "/Keysight_344xxA_submodules "
            "instead.", UserWarning)

        super().__init__(name, address, terminator='\n', **kwargs)

        idn = self.IDN.get()
        self.model = idn['model']

        ####################################
        # Instrument specifications

        self.has_DIG = 'DIG' in self._licenses()

        PLCs = {
            '34460A': [0.02, 0.2, 1, 10, 100],
            '34461A': [0.02, 0.2, 1, 10, 100],
            '34465A': [0.02, 0.06, 0.2, 1, 10, 100],
            '34470A': [0.02, 0.06, 0.2, 1, 10, 100]
        }
        if self.has_DIG:
            PLCs['34465A'] = [0.001, 0.002, 0.006] + PLCs['34465A']
            PLCs['34470A'] = [0.001, 0.002, 0.006] + PLCs['34470A']

        ranges = {
            '34460A': [10**n for n in range(-3, 9)],  # 1 m to 100 M
            '34461A': [10**n for n in range(-3, 9)],  # 1 m to 100 M
            '34465A': [10**n for n in range(-3, 10)],  # 1 m to 1 G
            '34470A': [10**n for n in range(-3, 10)],  # 1 m to 1 G
        }

        # The resolution factor order matches the order of PLCs
        res_factors = {
            '34460A': [300e-6, 100e-6, 30e-6, 10e-6, 3e-6],
            '34461A': [100e-6, 10e-6, 3e-6, 1e-6, 0.3e-6],
            '34465A': [3e-6, 1.5e-6, 0.7e-6, 0.3e-6, 0.1e-6, 0.03e-6],
            '34470A': [1e-6, 0.5e-6, 0.3e-6, 0.1e-6, 0.03e-6, 0.01e-6]
        }
        if self.has_DIG:
            res_factors['34465A'] = [30e-6, 15e-6, 6e-6
                                     ] + res_factors['34465A']
            res_factors['34470A'] = [30e-6, 10e-6, 3e-6
                                     ] + res_factors['34470A']

        self._resolution_factors = res_factors[self.model]
        self.ranges = ranges[self.model]
        self.NPLC_list = PLCs[self.model]

        ####################################
        # PARAMETERS

        self.add_parameter('line_frequency',
                           get_cmd='SYSTem:LFRequency?',
                           get_parser=int,
                           set_cmd=False,
                           label='Line Frequency',
                           unit='Hz',
                           docstring=('The frequency of the power line where '
                                      'the instrument is plugged'))

        self.add_parameter('NPLC',
                           get_cmd='SENSe:VOLTage:DC:NPLC?',
                           get_parser=float,
                           set_cmd=self._set_NPLC,
                           vals=vals.Enum(*self.NPLC_list),
                           label='Integration time',
                           unit='NPLC',
                           docstring=textwrap.dedent("""\
            Sets the integration time in number of power line cycles (PLC)
            for DC voltage and ratio measurements. Integration time is the
            period that the instrument's analog-to-digital (A/D) converter
            samples the input signal for a measurement. A longer integration
            time gives better measurement resolution but slower measurement
            speed.

            Only integration times of 1, 10, or 100 PLC provide normal mode
            (line frequency noise) rejection.

            Setting the integration time also sets the measurement
            resolution."""))

        self.add_parameter('volt',
                           get_cmd=self._get_voltage,
                           label='Voltage',
                           unit='V')

        self.add_parameter('range',
                           get_cmd='SENSe:VOLTage:DC:RANGe?',
                           get_parser=float,
                           set_cmd='SENSe:VOLTage:DC:RANGe {:f}',
                           vals=vals.Enum(*self.ranges))

        self.add_parameter('resolution',
                           get_cmd='SENSe:VOLTage:DC:RESolution?',
                           get_parser=float,
                           set_cmd=self._set_resolution,
                           label='Resolution',
                           unit='V',
                           vals=vals.MultiType(vals.Numbers(0),
                                               vals.Enum('MIN', 'MAX', 'DEF')),
                           docstring=textwrap.dedent("""\
            Selects the measurement resolution for DC voltage and ratio
            measurements. The resolution is specified in the same units as the
            selected measurement function, not in number of digits.

            You can also specify MIN (best resolution) or MAX (worst
            resolution).

            To achieve normal mode (line frequency noise) rejection,
            use a resolution that corresponds to an integration time that is
            an integral number of power line cycles.

            Refer to "Resolution Table" or "Range, Resolution and NPLC"
            sections of the instrument's manual for the available ranges for
            the resolution values."""))

        self.add_parameter('autorange',
                           label='Autorange',
                           set_cmd='SENSe:VOLTage:DC:RANGe:AUTO {}',
                           get_cmd='SENSe:VOLTage:DC:RANGe:AUTO?',
                           val_mapping={
                               'ON': 1,
                               'OFF': 0
                           },
                           vals=vals.Enum('ON', 'OFF'))

        self.add_parameter('display_enabled',
                           label='Display enabled',
                           set_cmd='DISPlay:STATe {}',
                           get_cmd='DISPlay:STATe?',
                           val_mapping={
                               True: 1,
                               False: 0
                           },
                           docstring=textwrap.dedent("""\
            Disables or enables the front panel display. When disabled,
            the display dims, and all annunciators are disabled. However,
            the screen remains on.

            Disabling the display improves command execution speed from the
            remote interface and provides basic security.

            Displaying text with `display_text` parameter will work even
            when the display is disabled."""))

        self.add_parameter('display_text',
                           label='Display text',
                           set_cmd='DISPLAY:TEXT "{}"',
                           get_cmd='DISPLAY:TEXT?',
                           get_parser=lambda s: s.strip('"'),
                           vals=vals.Strings(),
                           docstring=textwrap.dedent("""\
            Displays the given text on the screen. Specifying empty string
            moves the display back to its normal state. The same can be
            achieved by calling `display_clear`."""))

        self.add_parameter('autozero',
                           label='Autozero',
                           set_cmd='SENSe:VOLTage:DC:ZERO:AUTO {}',
                           get_cmd='SENSe:VOLTage:DC:ZERO:AUTO?',
                           val_mapping={
                               'ON': 1,
                               'OFF': 0,
                               'ONCE': 'ONCE'
                           },
                           vals=vals.Enum('ON', 'OFF', 'ONCE'),
                           docstring=textwrap.dedent("""\
            Disables or enables the autozero mode for DC voltage and ratio
            measurements.

            ON:   the DMM internally measures the offset following each
                  measurement. It then subtracts that measurement from the
                  preceding reading. This prevents offset voltages present on
                  the DMM’s input circuitry from affecting measurement
                  accuracy.
            OFF:  the instrument uses the last measured zero measurement and
                  subtracts it from each measurement. It takes a new zero
                  measurement each time you change the function, range or
                  integration time.
            ONCE: the instrument takes one zero measurement and sets
                  autozero OFF. The zero measurement taken is used for all
                  subsequent measurements until the next change to the
                  function, range or integration time. If the specified
                  integration time is less than 1 PLC, the zero measurement
                  is taken at 1 PLC to optimize noise rejection. Subsequent
                  measurements are taken at the specified fast (< 1 PLC)
                  integration time."""))

        ####################################
        # TRIGGERING

        if self.model in ['34465A', '34470A']:
            _max_trigger_count = 1e9
        else:
            _max_trigger_count = 1e6

        self.add_parameter('trigger_count',
                           label='Trigger Count',
                           set_cmd='TRIGger:COUNt {}',
                           get_cmd='TRIGger:COUNt?',
                           get_parser=float,
                           vals=vals.MultiType(
                               vals.Numbers(1, _max_trigger_count),
                               vals.Enum('MIN', 'MAX', 'DEF', 'INF')),
                           docstring=textwrap.dedent("""\
            Selects the number of triggers that are accepted by the
            instrument before returning to the "idle" trigger state.

            You can use the specified trigger count in conjunction with
            `sample_count`. In this case, the number of measurements
            returned is the sample count multiplied by the trigger count.

            A variable trigger count is not available from the front panel.
            However, when you return to remote control of the instrument,
            the trigger count returns to the previous value you selected."""))

        self.add_parameter('trigger_delay',
                           label='Trigger Delay',
                           unit='s',
                           set_cmd='TRIGger:DELay {}',
                           get_cmd='TRIGger:DELay?',
                           vals=vals.MultiType(vals.Numbers(0, 3600),
                                               vals.Enum('MIN', 'MAX', 'DEF')),
                           get_parser=float,
                           docstring=textwrap.dedent("""\
            Sets the delay between the trigger signal and the first
            measurement. This may be useful in applications where you want
            to allow the input to settle before taking a measurement or for
            pacing a burst of measurements.

            Step size for DC measurements is approximately 1 µs. For AC
            measurements, step size depends on AC bandwidth.

            Selecting a specific trigger delay disables the automatic
            trigger delay."""))

        self.add_parameter('auto_trigger_delay_enabled',
                           label='Auto Trigger Delay Enabled',
                           set_cmd='TRIGger:DELay:AUTO {}',
                           get_cmd='TRIGger:DELay:AUTO?',
                           get_parser=int,
                           val_mapping={
                               True: 1,
                               False: 0
                           },
                           docstring=textwrap.dedent("""\
            Disables or enables automatic trigger delay. If enabled,
            the instrument determines the delay based on function, range,
            and integration time or bandwidth.

            Selecting a specific trigger delay using `trigger_delay` disables
            the automatic trigger delay."""))

        self.add_parameter('trigger_slope',
                           label='Trigger Slope',
                           set_cmd='TRIGger:SLOPe {}',
                           get_cmd='TRIGger:SLOPe?',
                           vals=vals.Enum('POS', 'NEG'))

        if self.model in ['34465A', '34470A'] and self.has_DIG:
            self.add_parameter('trigger_level',
                               label='Trigger Level',
                               unit='V',
                               set_cmd='TRIGger:LEVel {}',
                               get_cmd='TRIGger:LEVel?',
                               get_parser=float,
                               vals=vals.MultiType(
                                   vals.Numbers(-1000, 1000),
                                   vals.Enum('MIN', 'MAX', 'DEF')),
                               docstring=textwrap.dedent("""\
                Sets the level on which a trigger occurs when level
                triggering is enabled (`trigger_source set to "INT").

                Note that for 100 mV to 100 V ranges and autorange is off,
                the trigger level can only be set within ±120% of the
                range."""))

        _trigger_source_docstring = textwrap.dedent("""\
            Selects the trigger source for measurements.

            IMMediate: The trigger signal is always present. When you place
                the instrument in the "wait-for-trigger" state, the trigger is
                issued immediately.

            BUS: The instrument is triggered by `trigger` method of this
                driver once the DMM is in the "wait-for-trigger" state.

            EXTernal: The instrument accepts hardware triggers applied to
                the rear-panel Ext Trig input and takes the specified number
                of measurements (`sample_count`), each time a TTL pulse
                specified by `trigger_slope` is received. If the
                instrument receives an external trigger before it is ready,
                it buffers one trigger.""")
        _trigger_source_vals = vals.Enum('IMM', 'EXT', 'BUS')

        if self.model in ['34465A', '34470A'] and self.has_DIG:
            _trigger_source_vals = vals.Enum('IMM', 'EXT', 'BUS', 'INT')
            # extra empty lines are needed for readability of the docstring
            _trigger_source_docstring += textwrap.dedent("""\


            INTernal: Provides level triggering capability. To trigger on a
                level on the input signal, select INTernal for the source,
                and set the level and slope with the `trigger_level` and
                `trigger_slope` parameters.""")

        self.add_parameter('trigger_source',
                           label='Trigger Source',
                           set_cmd='TRIGger:SOURce {}',
                           get_cmd='TRIGger:SOURce?',
                           vals=_trigger_source_vals,
                           docstring=_trigger_source_docstring)

        ####################################
        # SAMPLING

        if self.model in ['34465A', '34470A']:
            _max_sample_count = 1e9
        else:
            _max_sample_count = 1e6

        self.add_parameter('sample_count',
                           label='Sample Count',
                           set_cmd=partial(self._set_databuffer_setpoints,
                                           'SAMPle:COUNt {}'),
                           get_cmd='SAMPle:COUNt?',
                           vals=vals.MultiType(
                               vals.Numbers(1, _max_sample_count),
                               vals.Enum('MIN', 'MAX', 'DEF')),
                           get_parser=int,
                           docstring=textwrap.dedent("""\
            Specifies the number of measurements (samples) the instrument
            takes per trigger.

            MAX selects 1 billion readings. However, when pretrigger is
            selected, the maximum is 50,000 readings (without the MEM
            option) or 2,000,000 readings (with the MEM option)"""))

        if self.has_DIG:
            self.add_parameter('sample_count_pretrigger',
                               label='Sample Pretrigger Count',
                               set_cmd='SAMPle:COUNt:PRETrigger {}',
                               get_cmd='SAMPle:COUNt:PRETrigger?',
                               vals=vals.MultiType(
                                   vals.Numbers(0, 2e6 - 1),
                                   vals.Enum('MIN', 'MAX', 'DEF')),
                               get_parser=int,
                               docstring=textwrap.dedent("""\
                Allows collection of the data being digitized the trigger.
                Reserves memory for pretrigger samples up to the specified
                num. of pretrigger samples."""))

        if self.model in ['34465A', '34470A']:
            self.add_parameter('sample_source',
                               label='Sample Timing Source',
                               set_cmd='SAMPle:SOURce {}',
                               get_cmd='SAMPle:SOURce?',
                               vals=vals.Enum('IMM', 'TIM'),
                               docstring=('Determines sampling time, '
                                          'immediate or using sample_timer'))

        self.add_parameter('sample_timer',
                           label='Sample Timer',
                           set_cmd='SAMPle:TIMer {}',
                           get_cmd='SAMPle:TIMer?',
                           unit='s',
                           vals=vals.MultiType(vals.Numbers(0, 3600),
                                               vals.Enum('MIN', 'MAX', 'DEF')),
                           get_parser=float,
                           docstring=textwrap.dedent("""\
            The value is rounded by the instrument to the nearest step. For DC
            measurements, the step size is 1 µs. For AC measurements,
            it is AC bandwidth dependent.

            Special values are: MIN - recommended minimum, MAX - maximum,
            DEF - default. In order to obtain the actual value of the
            parameter that gets set when setting it to one of these special
            values, just call the get method of the parameter, or use
            corresponding parameters in this driver,
            like `sample_timer_minimum`.

            Specifying a value that is between the absolute minimum (assumes
            no range changes) and the recommended minimum value,
            may generate a timing violation error when making measurements.

            Applying a value less than the absolute minimum will generate an
            error."""))

        self.add_parameter('sample_timer_minimum',
                           label='Minimal recommended sample time',
                           get_cmd='SAMPle:TIMer? MIN',
                           get_parser=float,
                           unit='s',
                           docstring=textwrap.dedent("""\
            This value is measurement dependent. It depends on such things
            as the integration time, autozero on or off, autorange on or
            off, and the measurement range. Basically, the minimum is
            automatically determined by the instrument so that the sample
            interval is always greater than the sampling time.

            Since the minimum value changes depending on configuration, a
            command order dependency exists. You must completely configure
            the measurement before setting the sample timer to minimum,
            or you may generate an error. A complete configuration includes
            such things as math statistics or scaling.

            When using autorange, the minimum value is the recommended value,
            not the absolute minimum value. With autorange enabled, minimum
            value is calculated assuming a single range change will occur
            for every measurement (not multiple ranges, just one range up or
            down per measurement)."""))

        ####################################
        # The array parameter

        self.add_parameter('data_buffer', parameter_class=ArrayMeasurement)

        ####################################
        # Aperture parameters

        if self.model in ['34465A', '34470A']:
            # Define the extreme aperture time values for the 34465A and 34470A
            utility_freq = self.line_frequency()
            if utility_freq == 50:
                apt_times = {'34465A': [0.3e-3, 2], '34470A': [0.3e-3, 2]}
            elif utility_freq == 60:
                apt_times = {
                    '34465A': [0.3e-3, 1.67],
                    '34470A': [0.3e-3, 1.67]
                }
            if self.has_DIG:
                apt_times['34465A'][0] = 20e-6
                apt_times['34470A'][0] = 20e-6

            self.add_parameter('aperture_mode',
                               label='Aperture mode',
                               set_cmd='SENSe:VOLTage:DC:APERture:ENABled {}',
                               get_cmd='SENSe:VOLTage:DC:APERture:ENABled?',
                               val_mapping={
                                   'ON': 1,
                                   'OFF': 0
                               },
                               vals=vals.Enum('ON', 'OFF'),
                               docstring=textwrap.dedent("""\
                Enables the setting of integration time in seconds (called
                aperture time) for DC voltage measurements. If aperture time
                mode is disabled (default), the integration time is set in PLC
                (power-line cycles)."""))

            self.add_parameter('aperture_time',
                               label='Aperture time',
                               set_cmd=self._set_apt_time,
                               get_cmd='SENSe:VOLTage:DC:APERture?',
                               get_parser=float,
                               vals=vals.Numbers(*apt_times[self.model]),
                               docstring=textwrap.dedent("""\
                Specifies the integration time in seconds (called aperture
                time) with 2 µs resolution for DC voltage measurements.

                Use this command for precise control of the DMM's
                integration time. Use `NPLC` for better power-line noise
                rejection characteristics (NPLC > 1).

                Setting the aperture time automatically enables the aperture
                mode."""))

        ####################################
        # Connect message

        if not silent:
            self.connect_message()
Пример #16
0
    def __init__(self, parent: "QDac", name: str, channum: int):
        """
        Args:
            parent: The instrument to which the channel belongs.
            name: The name of the channel
            channum: The number of the channel (1-24 or 1-48)
        """
        super().__init__(parent, name)

        # Add the parameters
        self.add_parameter(
            name='v',
            label=f'Channel {channum} voltage',
            unit='V',
            set_cmd=partial(self._parent._set_voltage, channum),
            get_cmd=f'set {channum}',
            get_parser=float,
            # Initial range. Updated on init and during
            # operation:
            vals=vals.Numbers(-9.99, 9.99))

        self.add_parameter(name='mode',
                           label=f'Channel {channum} mode.',
                           set_cmd=partial(self._parent._set_mode, channum),
                           get_cmd=None,
                           vals=vals.Enum(*list(Mode)))

        self.add_parameter(name='i',
                           label=f'Channel {channum} current',
                           get_cmd=f'get {channum}',
                           unit='A',
                           get_parser=self._parent._current_parser)

        self.add_parameter(name='slope',
                           label=f'Channel {channum} slope',
                           unit='V/s',
                           set_cmd=partial(self._parent._setslope, channum),
                           get_cmd=partial(self._parent._getslope, channum),
                           vals=vals.MultiType(vals.Enum('Inf'),
                                               vals.Numbers(1e-3, 10000)))

        self.add_parameter(
            name='sync',
            label=f'Channel {channum} sync output',
            set_cmd=partial(self._parent._setsync, channum),
            get_cmd=partial(self._parent._getsync, channum),
            vals=vals.Ints(0, 4)  # Updated at qdac init
        )

        self.add_parameter(name='sync_delay',
                           label=f'Channel {channum} sync pulse delay',
                           unit='s',
                           get_cmd=None,
                           set_cmd=None,
                           vals=vals.Numbers(0, 10000),
                           initial_value=0)

        self.add_parameter(name='sync_duration',
                           label=f'Channel {channum} sync pulse duration',
                           unit='s',
                           get_cmd=None,
                           set_cmd=None,
                           vals=vals.Numbers(0.001, 10000),
                           initial_value=0.01)
Пример #17
0
    def __init__(self, parent: '_Keysight_344xxA', name: str, **kwargs):
        super(Trigger, self).__init__(parent, name, **kwargs)

        if self.parent.is_34465A_34470A:
            _max_trigger_count = 1e9
        else:
            _max_trigger_count = 1e6

        self.add_parameter('count',
                           label='Trigger Count',
                           set_cmd='TRIGger:COUNt {}',
                           get_cmd='TRIGger:COUNt?',
                           get_parser=float,
                           vals=vals.MultiType(
                               vals.Numbers(1, _max_trigger_count),
                               vals.Enum('MIN', 'MAX', 'DEF', 'INF')),
                           docstring=textwrap.dedent("""\
            Selects the number of triggers that are accepted by the 
            instrument before returning to the "idle" trigger state.

            You can use the specified trigger count in conjunction with 
            `sample_count`. In this case, the number of measurements 
            returned is the sample count multiplied by the trigger count.

            A variable trigger count is not available from the front panel. 
            However, when you return to remote control of the instrument, 
            the trigger count returns to the previous value you selected."""))

        self.add_parameter('delay',
                           label='Trigger Delay',
                           unit='s',
                           set_cmd='TRIGger:DELay {}',
                           get_cmd='TRIGger:DELay?',
                           vals=vals.MultiType(vals.Numbers(0, 3600),
                                               vals.Enum('MIN', 'MAX', 'DEF')),
                           get_parser=float,
                           docstring=textwrap.dedent("""\
            Sets the delay between the trigger signal and the first 
            measurement. This may be useful in applications where you want 
            to allow the input to settle before taking a measurement or for 
            pacing a burst of measurements.

            Step size for DC measurements is approximately 1 µs. For AC 
            measurements, step size depends on AC bandwidth.

            Selecting a specific trigger delay disables the automatic 
            trigger delay."""))

        self.add_parameter('auto_delay_enabled',
                           label='Auto Trigger Delay Enabled',
                           set_cmd='TRIGger:DELay:AUTO {}',
                           get_cmd='TRIGger:DELay:AUTO?',
                           get_parser=int,
                           val_mapping={
                               True: 1,
                               False: 0
                           },
                           docstring=textwrap.dedent("""\
            Disables or enables automatic trigger delay. If enabled, 
            the instrument determines the delay based on function, range, 
            and integration time or bandwidth.

            Selecting a specific trigger delay using `trigger.delay` disables 
            the automatic trigger delay."""))

        self.add_parameter('slope',
                           label='Trigger Slope',
                           set_cmd='TRIGger:SLOPe {}',
                           get_cmd='TRIGger:SLOPe?',
                           vals=vals.Enum('POS', 'NEG'))

        if self.parent.is_34465A_34470A and self.parent.has_DIG:
            self.add_parameter('level',
                               label='Trigger Level',
                               unit='V',
                               set_cmd='TRIGger:LEVel {}',
                               get_cmd='TRIGger:LEVel?',
                               get_parser=float,
                               vals=vals.MultiType(
                                   vals.Numbers(-1000, 1000),
                                   vals.Enum('MIN', 'MAX', 'DEF')),
                               docstring=textwrap.dedent("""\
                Sets the level on which a trigger occurs when level 
                triggering is enabled (`trigger.source` set to "INT").

                Note that for 100 mV to 100 V ranges and autorange is off, 
                the trigger level can only be set within ±120% of the 
                range."""))

        _trigger_source_docstring = textwrap.dedent("""\
            Selects the trigger source for measurements.

            IMMediate: The trigger signal is always present. When you place 
                the instrument in the "wait-for-trigger" state, the trigger is 
                issued immediately.

            BUS: The instrument is triggered by `trigger.force` method of this 
                driver once the DMM is in the "wait-for-trigger" state.

            EXTernal: The instrument accepts hardware triggers applied to 
                the rear-panel Ext Trig input and takes the specified number 
                of measurements (`sample_count`), each time a TTL pulse 
                specified by `trigger.slope` is received. If the 
                instrument receives an external trigger before it is ready, 
                it buffers one trigger.""")
        _trigger_source_vals = vals.Enum('IMM', 'EXT', 'BUS')

        if self.parent.is_34465A_34470A and self.parent.has_DIG:
            _trigger_source_vals = vals.Enum('IMM', 'EXT', 'BUS', 'INT')
            # extra empty lines are needed for readability of the docstring
            _trigger_source_docstring += textwrap.dedent("""\


            INTernal: Provides level triggering capability. To trigger on a 
                level on the input signal, select INTernal for the source, 
                and set the level and slope with the `trigger.level` and 
                `trigger.slope` parameters.""")

        self.add_parameter('source',
                           label='Trigger Source',
                           set_cmd='TRIGger:SOURce {}',
                           get_cmd='TRIGger:SOURce?',
                           vals=_trigger_source_vals,
                           docstring=_trigger_source_docstring)
Пример #18
0
    def __init__(self, name, **kwargs):
        dll_path = 'C:\\WINDOWS\\System32\\ATSApi.dll'
        super().__init__(name, dll_path=dll_path, **kwargs)

        # add parameters

        # ----- Parameters for the configuration of the board -----
        self.add_parameter(name='clock_source',
                           parameter_class=TraceParameter,
                           get_cmd=None,
                           label='Clock Source',
                           unit=None,
                           initial_value='INTERNAL_CLOCK',
                           val_mapping={'INTERNAL_CLOCK': 1,
                                       'FAST_EXTERNAL_CLOCK': 2,
                                       'EXTERNAL_CLOCK_10MHz_REF': 7})
        self.add_parameter(name='external_sample_rate',
                           get_cmd=None,
                           parameter_class=TraceParameter,
                           label='External Sample Rate',
                           unit='S/s',
                           vals=validators.MultiType(validators.Ints(300000000, 2000000000),
                                                     validators.Enum('UNDEFINED')),
                           initial_value='UNDEFINED')
        self.add_parameter(name='sample_rate',
                           get_cmd=None,
                           parameter_class=TraceParameter,
                           label='Internal Sample Rate',
                           unit='S/s',
                           initial_value='UNDEFINED',
                           val_mapping={1_000: 1,
                                        2_000: 2,
                                        5_000: 4,
                                       10_000: 8,
                                       20_000: 10,
                                       50_000: 12,
                                      100_000: 14,
                                      200_000: 16,
                                      500_000: 18,
                                    1_000_000: 20,
                                    2_000_000: 24,
                                    5_000_000: 26,
                                   10_000_000: 28,
                                   20_000_000: 30,
                                   25_000_000: 33,
                                   50_000_000: 34,
                                  100_000_000: 36,
                                  125_000_000: 37,
                                  160_000_000: 38,
                                  180_000_000: 39,
                                  200_000_000: 40,
                                  250_000_000: 43,
                                  500_000_000: 48,
                                  800_000_000: 50,
                                1_000_000_000: 53,
                                1_200_000_000: 55,
                                1_500_000_000: 58,
                                1_800_000_000: 61,
                                2_000_000_000: 63,
                                2_400_000_000: 106,
                                3_000_000_000: 117,
                                3_600_000_000: 123,
                                4_000_000_000: 128,
                             'EXTERNAL_CLOCK': 64,
                                  'UNDEFINED': 'UNDEFINED'})
Пример #19
0
    def __init__(self,
                 name: str,
                 address: str,
                 silent: bool = False,
                 **kwargs):
        """
        Create an instance of the instrument.

        Args:
            name: Name used by QCoDeS. Appears in the DataSet
            address: Visa-resolvable instrument address.
            silent: If True, the connect_message of the instrument
                is supressed. Default: False
        """

        super().__init__(name, address, terminator='\n', **kwargs)

        idn = self.IDN.get()
        self.model = idn['model']

        self.is_34465A_34470A = self.model in ['34465A', '34470A']

        ####################################
        # Instrument specifications

        self.has_DIG = 'DIG' in self._licenses()

        PLCs = {
            '34460A': [0.02, 0.2, 1, 10, 100],
            '34461A': [0.02, 0.2, 1, 10, 100],
            '34465A': [0.02, 0.06, 0.2, 1, 10, 100],
            '34470A': [0.02, 0.06, 0.2, 1, 10, 100]
        }
        if self.has_DIG:
            PLCs['34465A'] = [0.001, 0.002, 0.006] + PLCs['34465A']
            PLCs['34470A'] = [0.001, 0.002, 0.006] + PLCs['34470A']

        ranges = {
            '34460A': [10**n for n in range(-3, 9)],  # 1 m to 100 M
            '34461A': [10**n for n in range(-3, 9)],  # 1 m to 100 M
            '34465A': [10**n for n in range(-3, 10)],  # 1 m to 1 G
            '34470A': [10**n for n in range(-3, 10)],  # 1 m to 1 G
        }

        # The resolution factor order matches the order of PLCs
        res_factors = {
            '34460A': [300e-6, 100e-6, 30e-6, 10e-6, 3e-6],
            '34461A': [100e-6, 10e-6, 3e-6, 1e-6, 0.3e-6],
            '34465A': [3e-6, 1.5e-6, 0.7e-6, 0.3e-6, 0.1e-6, 0.03e-6],
            '34470A': [1e-6, 0.5e-6, 0.3e-6, 0.1e-6, 0.03e-6, 0.01e-6]
        }
        if self.has_DIG:
            res_factors['34465A'] = [30e-6, 15e-6, 6e-6
                                     ] + res_factors['34465A']
            res_factors['34470A'] = [30e-6, 10e-6, 3e-6
                                     ] + res_factors['34470A']

        self._resolution_factors = res_factors[self.model]
        self.ranges = ranges[self.model]
        self.NPLC_list = PLCs[self.model]

        ####################################
        # PARAMETERS

        self.add_parameter('line_frequency',
                           get_cmd='SYSTem:LFRequency?',
                           get_parser=int,
                           set_cmd=False,
                           label='Line Frequency',
                           unit='Hz',
                           docstring=('The frequency of the power line where '
                                      'the instrument is plugged'))

        self.add_parameter('NPLC',
                           get_cmd='SENSe:VOLTage:DC:NPLC?',
                           get_parser=float,
                           set_cmd=self._set_NPLC,
                           vals=vals.Enum(*self.NPLC_list),
                           label='Integration time',
                           unit='NPLC',
                           docstring=textwrap.dedent("""\
            Sets the integration time in number of power line cycles (PLC) 
            for DC voltage and ratio measurements. Integration time is the 
            period that the instrument's analog-to-digital (A/D) converter 
            samples the input signal for a measurement. A longer integration 
            time gives better measurement resolution but slower measurement 
            speed.
            
            Only integration times of 1, 10, or 100 PLC provide normal mode 
            (line frequency noise) rejection.
            
            Setting the integration time also sets the measurement 
            resolution."""))

        self.add_parameter('range',
                           get_cmd='SENSe:VOLTage:DC:RANGe?',
                           get_parser=float,
                           set_cmd='SENSe:VOLTage:DC:RANGe {:f}',
                           vals=vals.Enum(*self.ranges))

        self.add_parameter('resolution',
                           get_cmd='SENSe:VOLTage:DC:RESolution?',
                           get_parser=float,
                           set_cmd=self._set_resolution,
                           label='Resolution',
                           unit='V',
                           vals=vals.MultiType(vals.Numbers(0),
                                               vals.Enum('MIN', 'MAX', 'DEF')),
                           docstring=textwrap.dedent("""\
            Selects the measurement resolution for DC voltage and ratio 
            measurements. The resolution is specified in the same units as the 
            selected measurement function, not in number of digits.
            
            You can also specify MIN (best resolution) or MAX (worst 
            resolution).
            
            To achieve normal mode (line frequency noise) rejection, 
            use a resolution that corresponds to an integration time that is 
            an integral number of power line cycles.
            
            Refer to "Resolution Table" or "Range, Resolution and NPLC" 
            sections of the instrument's manual for the available ranges for 
            the resolution values."""))

        self.add_parameter('autorange',
                           label='Autorange',
                           set_cmd='SENSe:VOLTage:DC:RANGe:AUTO {}',
                           get_cmd='SENSe:VOLTage:DC:RANGe:AUTO?',
                           val_mapping={
                               'ON': 1,
                               'OFF': 0
                           },
                           vals=vals.Enum('ON', 'OFF'))

        self.add_parameter('autozero',
                           label='Autozero',
                           set_cmd='SENSe:VOLTage:DC:ZERO:AUTO {}',
                           get_cmd='SENSe:VOLTage:DC:ZERO:AUTO?',
                           val_mapping={
                               'ON': 1,
                               'OFF': 0,
                               'ONCE': 'ONCE'
                           },
                           vals=vals.Enum('ON', 'OFF', 'ONCE'),
                           docstring=textwrap.dedent("""\
            Disables or enables the autozero mode for DC voltage and ratio 
            measurements.
            
            ON:   the DMM internally measures the offset following each 
                  measurement. It then subtracts that measurement from the 
                  preceding reading. This prevents offset voltages present on
                  the DMM’s input circuitry from affecting measurement 
                  accuracy.
            OFF:  the instrument uses the last measured zero measurement and 
                  subtracts it from each measurement. It takes a new zero 
                  measurement each time you change the function, range or 
                  integration time.
            ONCE: the instrument takes one zero measurement and sets 
                  autozero OFF. The zero measurement taken is used for all 
                  subsequent measurements until the next change to the 
                  function, range or integration time. If the specified 
                  integration time is less than 1 PLC, the zero measurement 
                  is taken at 1 PLC to optimize noise rejection. Subsequent 
                  measurements are taken at the specified fast (< 1 PLC) 
                  integration time."""))

        ####################################
        # Aperture parameters

        if self.is_34465A_34470A:
            # Define the extreme aperture time values for the 34465A and 34470A
            utility_freq = self.line_frequency()
            if utility_freq == 50:
                apt_times = {'34465A': [0.3e-3, 2], '34470A': [0.3e-3, 2]}
            elif utility_freq == 60:
                apt_times = {
                    '34465A': [0.3e-3, 1.67],
                    '34470A': [0.3e-3, 1.67]
                }
            if self.has_DIG:
                apt_times['34465A'][0] = 20e-6
                apt_times['34470A'][0] = 20e-6

            self.add_parameter('aperture_mode',
                               label='Aperture mode',
                               set_cmd='SENSe:VOLTage:DC:APERture:ENABled {}',
                               get_cmd='SENSe:VOLTage:DC:APERture:ENABled?',
                               val_mapping={
                                   'ON': 1,
                                   'OFF': 0
                               },
                               vals=vals.Enum('ON', 'OFF'),
                               docstring=textwrap.dedent("""\
                Enables the setting of integration time in seconds (called 
                aperture time) for DC voltage measurements. If aperture time 
                mode is disabled (default), the integration time is set in PLC 
                (power-line cycles)."""))

            self.add_parameter('aperture_time',
                               label='Aperture time',
                               set_cmd=self._set_apt_time,
                               get_cmd='SENSe:VOLTage:DC:APERture?',
                               get_parser=float,
                               vals=vals.Numbers(*apt_times[self.model]),
                               docstring=textwrap.dedent("""\
                Specifies the integration time in seconds (called aperture 
                time) with 2 µs resolution for DC voltage measurements.
                
                Use this command for precise control of the DMM's 
                integration time. Use `NPLC` for better power-line noise 
                rejection characteristics (NPLC > 1).

                Setting the aperture time automatically enables the aperture 
                mode."""))

        ####################################
        # Submodules

        self.add_submodule('display', Display(self, 'display'))
        self.add_submodule('trigger', Trigger(self, 'trigger'))
        self.add_submodule('sample', Sample(self, 'sample'))

        ####################################
        # Measuring parameter

        self.add_parameter('volt',
                           get_cmd=self._get_voltage,
                           label='Voltage',
                           unit='V')

        ####################################
        # Connect message

        if not silent:
            self.connect_message()
Пример #20
0
    def __init__(self, name: str, daq_card_name: str,
                 xy_channel_names: Tuple[str, str], clock_rate: float,
                 scan_speed_V_per_s: float, **kwargs):
        """
        Create an instance of the instrument.

        Args:
            name (str): The internal QCoDeS name of the instrument
            daq_card_name (str): The device name from the list
                system = nidaqmx.system.System.local()
                [device.name for device in system.devices]
        """

        super().__init__(name, **kwargs)

        self._daq_card = PXI_6251(daq_card_name, **kwargs)

        self._daq_card.add_task("ao_task")

        self._daq_card.ao_task.add_ao_volt_channel('X', xy_channel_names[0])
        self._daq_card.ao_task.add_ao_volt_channel('Y', xy_channel_names[1])

        self._daq_card.ao_task._task.out_stream.regen_mode = RegenerationMode.DONT_ALLOW_REGENERATION

        self._daq_card.ao_task.add_sample_clock(
            clock_rate, sample_mode=AcquisitionType.FINITE)

        self._daq_card.ao_task._task.register_done_event(
            self.task_done_callback)

        self._pos = (None, None)
        self._target_pos = (None, None)

        self.add_parameter(name='x_min',
                           label='x min value',
                           unit='V',
                           set_cmd=self._daq_card.ao_task.X.ao_min.set,
                           get_cmd=self._daq_card.ao_task.X.ao_min.get,
                           vals=vals.Numbers())

        self.add_parameter(name='x_max',
                           label='x max value',
                           unit='V',
                           set_cmd=self._daq_card.ao_task.X.ao_max.set,
                           get_cmd=self._daq_card.ao_task.X.ao_max.get,
                           vals=vals.Numbers())

        self.add_parameter(name='y_min',
                           label='y min value',
                           unit='V',
                           set_cmd=self._daq_card.ao_task.Y.ao_min.set,
                           get_cmd=self._daq_card.ao_task.Y.ao_min.get,
                           vals=vals.Numbers())

        self.add_parameter(name='y_max',
                           label='y max value',
                           unit='V',
                           set_cmd=self._daq_card.ao_task.Y.ao_max.set,
                           get_cmd=self._daq_card.ao_task.Y.ao_max.get,
                           vals=vals.Numbers())

        self.add_parameter(name='scan_speed',
                           parameter_class=ManualParameter,
                           initial_value=scan_speed_V_per_s,
                           label='scanning speed',
                           unit='V_per_s',
                           vals=vals.MultiType(vals.Numbers(),
                                               vals.Enum(None)))

        self.add_parameter(
            name='samp_rate',
            label='sampling rate',
            unit='samples/s',
            set_cmd=self._daq_card.ao_task.clock.samp_clk_rate.set,
            get_cmd=self._daq_card.ao_task.clock.samp_clk_rate.get,
            vals=vals.Numbers(min_value=0,
                              max_value=self._daq_card.ao_task._task.timing.
                              samp_clk_max_rate))

        self.add_parameter(
            name='N_samp',
            label='N samples',
            unit='',
            set_cmd=self._daq_card.ao_task.clock.samp_quant_samp_per_chan.set,
            get_cmd=self._daq_card.ao_task.clock.samp_quant_samp_per_chan.get,
            vals=vals.Ints(min_value=0))