Beispiel #1
0
    def __init__(self, name: str, address: str, **kwargs: Any) -> None:
        super().__init__(name, address, terminator='\n', **kwargs)

        self.add_parameter('start_freq',
                           label='Sweep start frequency',
                           unit='Hz',
                           set_cmd=partial(self.invalidate_trace,
                                           'STAR {} HZ'),
                           get_cmd='STAR?',
                           get_parser=float,
                           vals=vals.Numbers(30000, 6000000000))

        self.add_parameter('stop_freq',
                           label='Sweep stop frequency',
                           unit='Hz',
                           set_cmd=partial(self.invalidate_trace,
                                           'STOP {} HZ'),
                           get_cmd='STOP?',
                           get_parser=float,
                           vals=vals.Numbers(30000, 6000000000))

        self.add_parameter('averaging',
                           label='Averaging state',
                           set_cmd='AVERO{}',
                           get_cmd='AVERO?',
                           val_mapping={
                               'ON': 1,
                               'OFF': 0
                           })

        self.add_parameter('number_of_averages',
                           label='Number of averages',
                           set_cmd='AVERFACT{}',
                           get_cmd='AVERFACT?',
                           get_parser=HPIntParser,
                           vals=vals.Ints(0, 999))

        self.add_parameter('trace_points',
                           label='Number of points in trace',
                           set_cmd=partial(self.invalidate_trace, 'POIN{}'),
                           get_cmd='POIN?',
                           get_parser=HPIntParser,
                           vals=vals.Enum(3, 11, 26, 51, 101, 201, 401, 801,
                                          1601))

        self.add_parameter(
            'sweep_time',
            label='Sweep time',
            set_cmd='SWET{}',
            get_cmd='SWET?',
            unit='s',
            get_parser=float,
            vals=vals.Numbers(0.01, 86400),
        )

        self.add_parameter('output_power',
                           label='Output power',
                           unit='dBm',
                           set_cmd='POWE{}',
                           get_cmd='POWE?',
                           get_parser=float,
                           vals=vals.Numbers(-85, 20))

        self.add_parameter('s_parameter',
                           label='S-parameter',
                           set_cmd=self._s_parameter_setter,
                           get_cmd=self._s_parameter_getter)

        # DISPLAY / Y SCALE PARAMETERS
        self.add_parameter('display_format',
                           label='Display format',
                           set_cmd=self._display_format_setter,
                           get_cmd=self._display_format_getter)

        # TODO: update this on startup and via display format
        self.add_parameter(
            'display_reference',
            label='Display reference level',
            unit=None,  # will be set by display_format
            get_cmd='REFV?',
            set_cmd='REFV{}',
            get_parser=float,
            vals=vals.Numbers(-500, 500))

        self.add_parameter(
            'display_scale',
            label='Display scale',
            unit=None,  # will be set by display_format
            get_cmd='SCAL?',
            set_cmd='SCAL{}',
            get_parser=float,
            vals=vals.Numbers(-500, 500))

        self.add_parameter(name='trace', parameter_class=HP8753DTrace)

        # Startup
        self.startup()
        self.connect_message()
    def __init__(self, name, alt_dll_path=None, **kwargs):
        dll_path = 'C:\\WINDOWS\\System32\\ATSApi.dll'
        #        dll_path = 'C:\\WINDOWS\\system32\\ATS_Average_DLL.dll'  #additional dll for specific needs (ie GetAverregedBuffer)

        if alt_dll_path == None:  # check if alt_dll has been chosen
            alt_dll_path = dll_path

        super().__init__(name,
                         dll_path=dll_path,
                         alt_dll_path=alt_dll_path,
                         **kwargs)
        # add parameters

        # ----- Parameters for the configuration of the board -----
        self.add_parameter(name='clock_source',
                           parameter_class=TraceParameter,
                           label='Clock Source',
                           unit=None,
                           initial_value='INTERNAL_CLOCK',
                           val_mapping={
                               'INTERNAL_CLOCK': 1,
                               'SLOW_EXTERNAL_CLOCK': 4,
                               'EXTERNAL_CLOCK_AC': 5,
                               'EXTERNAL_CLOCK_10_MHz_REF': 7
                           })

        self.add_parameter(name='external_sample_rate',
                           get_cmd=None,
                           parameter_class=TraceParameter,
                           label='External Sample Rate',
                           unit='S/s',
                           vals=validators.Enum(1_000_000_000),
                           initial_value=None)

        self.add_parameter(name='sample_rate',
                           parameter_class=TraceParameter,
                           label='Sample Rate',
                           unit='S/s',
                           initial_value=1000000000,
                           val_mapping={
                               1000: 0x1,
                               2000: 0x2,
                               5000: 0x4,
                               10000: 0x8,
                               20000: 0xA,
                               50000: 0xC,
                               100000: 0xE,
                               200000: 0x10,
                               500000: 0x12,
                               1000000: 0x14,
                               2000000: 0x18,
                               5000000: 0x1A,
                               10000000: 0x1C,
                               20000000: 0x1E,
                               50000000: 0x22,
                               100000000: 0x24,
                               250000000: 0x2B,
                               500000000: 0x30,
                               1000000000: 0x35,
                               'EXTERNAL_CLOCK': 0x40,
                               '1GHz_REFERENCE_CLOCK': 1000000000
                           })

        self.add_parameter(name='clock_edge',
                           parameter_class=TraceParameter,
                           label='Clock Edge',
                           unit=None,
                           initial_value='CLOCK_EDGE_RISING',
                           val_mapping={
                               'CLOCK_EDGE_RISING': 0,
                               'CLOCK_EDGE_FALLING': 1
                           })

        self.add_parameter(name='decimation',
                           parameter_class=TraceParameter,
                           label='Decimation',
                           unit=None,
                           initial_value=0,
                           vals=validators.Ints(0, 100000))

        for i in ['1', '2']:
            self.add_parameter(name='coupling' + i,
                               parameter_class=TraceParameter,
                               label='Coupling channel ' + i,
                               unit=None,
                               initial_value='AC',
                               val_mapping={
                                   'AC': 1,
                                   'DC': 2
                               })
            self.add_parameter(name='channel_range' + i,
                               parameter_class=TraceParameter,
                               label='Range channel ' + i,
                               unit='V',
                               initial_value=4,
                               val_mapping={
                                   0.04: 2,
                                   0.1: 5,
                                   0.2: 6,
                                   0.4: 7,
                                   1.0: 10,
                                   2.0: 11,
                                   4.0: 12
                               })
            self.add_parameter(name='impedance' + i,
                               parameter_class=TraceParameter,
                               label='Impedance channel ' + i,
                               unit='Ohm',
                               initial_value=50,
                               val_mapping={
                                   1000000: 1,
                                   50: 2
                               })
            self.add_parameter(name='bwlimit' + i,
                               parameter_class=TraceParameter,
                               label='Bandwidth limit channel ' + i,
                               unit=None,
                               initial_value='DISABLED',
                               val_mapping={
                                   'DISABLED': 0,
                                   'ENABLED': 1
                               })

        self.add_parameter(name='trigger_operation',
                           parameter_class=TraceParameter,
                           label='Trigger Operation',
                           unit=None,
                           initial_value='TRIG_ENGINE_OP_J',
                           val_mapping={
                               'TRIG_ENGINE_OP_J': 0,
                               'TRIG_ENGINE_OP_K': 1,
                               'TRIG_ENGINE_OP_J_OR_K': 2,
                               'TRIG_ENGINE_OP_J_AND_K': 3,
                               'TRIG_ENGINE_OP_J_XOR_K': 4,
                               'TRIG_ENGINE_OP_J_AND_NOT_K': 5,
                               'TRIG_ENGINE_OP_NOT_J_AND_K': 6
                           })
        for i in ['1', '2']:
            self.add_parameter(name='trigger_engine' + i,
                               parameter_class=TraceParameter,
                               label='Trigger Engine ' + i,
                               unit=None,
                               initial_value='TRIG_ENGINE_' +
                               ('J' if i == 0 else 'K'),
                               val_mapping={
                                   'TRIG_ENGINE_J': 0,
                                   'TRIG_ENGINE_K': 1
                               })
            self.add_parameter(name='trigger_source' + i,
                               parameter_class=TraceParameter,
                               label='Trigger Source ' + i,
                               unit=None,
                               initial_value='DISABLE',
                               val_mapping={
                                   'CHANNEL_A': 0,
                                   'CHANNEL_B': 1,
                                   'EXTERNAL': 2,
                                   'DISABLE': 3
                               })
            self.add_parameter(name='trigger_slope' + i,
                               parameter_class=TraceParameter,
                               label='Trigger Slope ' + i,
                               unit=None,
                               initial_value='TRIG_SLOPE_POSITIVE',
                               val_mapping={
                                   'TRIG_SLOPE_POSITIVE': 1,
                                   'TRIG_SLOPE_NEGATIVE': 2
                               })
            self.add_parameter(name='trigger_level' + i,
                               parameter_class=TraceParameter,
                               label='Trigger Level ' + i,
                               unit=None,
                               initial_value=128,
                               vals=validators.Ints(0, 255))

        self.add_parameter(name='external_trigger_coupling',
                           parameter_class=TraceParameter,
                           label='External Trigger Coupling',
                           unit=None,
                           initial_value='AC',
                           val_mapping={
                               'AC': 1,
                               'DC': 2
                           })
        self.add_parameter(name='external_trigger_range',
                           parameter_class=TraceParameter,
                           label='External Trigger Range',
                           unit=None,
                           initial_value='ETR_5V',
                           val_mapping={
                               'ETR_5V': 0,
                               'ETR_1V': 1
                           })
        self.add_parameter(name='trigger_delay',
                           parameter_class=TraceParameter,
                           label='Trigger Delay',
                           unit='Sample clock cycles',
                           initial_value=0,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='timeout_ticks',
                           parameter_class=TraceParameter,
                           label='Timeout Ticks',
                           unit='10 us',
                           initial_value=0,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='aux_io_mode',
                           parameter_class=TraceParameter,
                           label='AUX I/O Mode',
                           unit=None,
                           initial_value='AUX_IN_AUXILIARY',
                           val_mapping={
                               'AUX_OUT_TRIGGER': 0,
                               'AUX_IN_TRIGGER_ENABLE': 1,
                               'AUX_IN_AUXILIARY': 13
                           })

        self.add_parameter(name='aux_io_param',
                           parameter_class=TraceParameter,
                           label='AUX I/O Param',
                           unit=None,
                           initial_value='NONE',
                           val_mapping={
                               'NONE': 0,
                               'TRIG_SLOPE_POSITIVE': 1,
                               'TRIG_SLOPE_NEGATIVE': 2
                           })

        # ----- Parameters for the acquire function -----
        self.add_parameter(name='mode',
                           label='Acquisition mode',
                           unit=None,
                           initial_value='NPT',
                           get_cmd=None,
                           set_cmd=None,
                           val_mapping={
                               'NPT': 0x200,
                               'TS': 0x400,
                               'AVG': 0x600
                           })

        # samples_per_record must be a multiple of of some number (64 in the
        # case of ATS9870) and and has some minimum (256 in the case of ATS9870)
        # These values can be found in the ATS-SDK programmar's guide
        self.add_parameter(name='samples_per_record',
                           label='Samples per Record',
                           unit=None,
                           initial_value=96000,
                           get_cmd=None,
                           set_cmd=None,
                           vals=validators.Multiples(divisor=64,
                                                     min_value=256))

        self.add_parameter(name='records_per_buffer',
                           label='Records per Buffer',
                           unit=None,
                           initial_value=1,
                           get_cmd=None,
                           set_cmd=None,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='buffers_per_acquisition',
                           label='Buffers per Acquisition',
                           unit=None,
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=1,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='channel_selection',
                           label='Channel Selection',
                           unit=None,
                           get_cmd=None,
                           set_cmd=None,
                           initial_value='AB',
                           val_mapping={
                               'A': 1,
                               'B': 2,
                               'AB': 3
                           })
        self.add_parameter(name='transfer_offset',
                           label='Transfer Offset',
                           unit='Samples',
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=0,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='external_startcapture',
                           label='External Startcapture',
                           unit=None,
                           get_cmd=None,
                           set_cmd=None,
                           initial_value='ENABLED',
                           val_mapping={
                               'DISABLED': 0X0,
                               'ENABLED': 0x1
                           })
        self.add_parameter(name='enable_record_headers',
                           label='Enable Record Headers',
                           unit=None,
                           get_cmd=None,
                           set_cmd=None,
                           initial_value='DISABLED',
                           val_mapping={
                               'DISABLED': 0x0,
                               'ENABLED': 0x8
                           })
        self.add_parameter(name='alloc_buffers',
                           label='Alloc Buffers',
                           unit=None,
                           get_cmd=None,
                           set_cmd=None,
                           initial_value='DISABLED',
                           val_mapping={
                               'DISABLED': 0x0,
                               'ENABLED': 0x20
                           })
        self.add_parameter(name='fifo_only_streaming',
                           label='Fifo Only Streaming',
                           unit=None,
                           get_cmd=None,
                           set_cmd=None,
                           initial_value='DISABLED',
                           val_mapping={
                               'DISABLED': 0x0,
                               'ENABLED': 0x800
                           })
        self.add_parameter(name='interleave_samples',
                           label='Interleave Samples',
                           unit=None,
                           get_cmd=None,
                           set_cmd=None,
                           initial_value='DISABLED',
                           val_mapping={
                               'DISABLED': 0x0,
                               'ENABLED': 0x1000
                           })
        self.add_parameter(name='get_processed_data',
                           label='Get Processed Data',
                           unit=None,
                           get_cmd=None,
                           set_cmd=None,
                           initial_value='DISABLED',
                           val_mapping={
                               'DISABLED': 0x0,
                               'ENABLED': 0x2000
                           })
        self.add_parameter(name='allocated_buffers',
                           label='Allocated Buffers',
                           unit=None,
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=1,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='buffer_timeout',
                           label='Buffer Timeout',
                           unit='ms',
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=1000,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='dmaBufferCount',
                           label='dma Buffer Count',
                           unit=None,
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=8,
                           vals=validators.Ints(min_value=2))
        self.add_parameter(name='number_of_averaging',
                           label='number of averaging',
                           unit=None,
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=1,
                           vals=validators.Ints(min_value=1))

        model = self.get_idn()['model']
        if model != 'ATS9870':
            raise Exception("The Alazar board kind is not 'ATS9870',"
                            " found '" + str(model) + "' instead.")
Beispiel #3
0
class DacChannel(InstrumentChannel, DacReader):
    """
    A single DAC channel of the DECADAC
    """
    _CHANNEL_VAL = vals.Ints(0, 3)

    def __init__(self, parent, name, channel, min_val=-5, max_val=5):
        super().__init__(parent, name)

        # Validate slot and channel values
        self._CHANNEL_VAL.validate(channel)
        self._channel = channel
        self._slot = self.parent._slot

        # Calculate base address for querying channel parameters
        # Note that the following values can be found using these offsets
        # 0: Interrupt Period
        # 4: DAC High Limit
        # 5: DAC Low Limit
        # 6: Slope (double)
        # 8: DAC Value (double)
        self._base_addr = 1536 + (16 * 4) * self._slot + 16 * self._channel

        # Store min/max voltages
        assert (min_val < max_val)
        self.min_val = min_val
        self.max_val = max_val

        # Add channel parameters
        # Note we will use the older addresses to read the value from the dac
        # rather than the newer 'd' command for backwards compatibility
        self._volt_val = vals.Numbers(self.min_val, self.max_val)
        self.add_parameter("volt",
                           get_cmd=partial(self._query_address,
                                           self._base_addr + 9, 1),
                           get_parser=self._dac_code_to_v,
                           set_cmd=self._set_dac,
                           set_parser=self._dac_v_to_code,
                           vals=self._volt_val,
                           label="channel {}".format(channel + self._slot * 4),
                           unit="V")
        # The limit commands are used to sweep dac voltages. They are not
        # safety features.
        self.add_parameter("lower_ramp_limit",
                           get_cmd=partial(self._query_address,
                                           self._base_addr + 5),
                           get_parser=self._dac_code_to_v,
                           set_cmd="L{};",
                           set_parser=self._dac_v_to_code,
                           vals=self._volt_val,
                           label="Lower_Ramp_Limit",
                           unit="V")
        self.add_parameter("upper_ramp_limit",
                           get_cmd=partial(self._query_address,
                                           self._base_addr + 4),
                           get_parser=self._dac_code_to_v,
                           set_cmd="U{};",
                           set_parser=self._dac_v_to_code,
                           vals=self._volt_val,
                           label="Upper_Ramp_Limit",
                           unit="V")
        self.add_parameter("update_period",
                           get_cmd=partial(self._query_address,
                                           self._base_addr),
                           get_parser=int,
                           set_cmd="T{};",
                           set_parser=int,
                           vals=vals.Ints(50, 65535),
                           label="Update_Period",
                           unit="us")
        self.add_parameter("slope",
                           get_cmd=partial(self._query_address,
                                           self._base_addr + 6, 2),
                           get_parser=int,
                           set_cmd="S{};",
                           set_parser=int,
                           vals=vals.Ints(-(2**32), 2**32),
                           label="Ramp_Slope")

        # Manual parameters to control whether DAC channels should ramp to
        # voltages or jump
        self._ramp_val = vals.Numbers(0, 10)
        self.add_parameter("enable_ramp",
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=False,
                           vals=vals.Bool())
        self.add_parameter("ramp_rate",
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=0.1,
                           vals=self._ramp_val,
                           unit="V/s")

        # Add ramp function to the list of functions
        self.add_function("ramp",
                          call_cmd=self._ramp,
                          args=(self._volt_val, self._ramp_val))

        # If we have access to the VERSADAC (slot) EEPROM, we can set the
        # initial value of the channel.
        # NOTE: these values will be overwritten by a K3 calibration
        if self.parent._VERSA_EEPROM_available:
            _INITIAL_ADDR = [6, 8, 32774, 32776]
            self.add_parameter("initial_value",
                               get_cmd=partial(self._query_address,
                                               _INITIAL_ADDR[self._channel],
                                               versa_eeprom=True),
                               get_parser=self._dac_code_to_v,
                               set_cmd=partial(self._write_address,
                                               _INITIAL_ADDR[self._channel],
                                               versa_eeprom=True),
                               set_parser=self._dac_v_to_code,
                               vals=vals.Numbers(self.min_val, self.max_val))

    def _ramp(self, val, rate, block=True):
        """
        Ramp the DAC to a given voltage.

        Params:
            val (float): The voltage to ramp to in volts

            rate (float): The ramp rate in units of volts/s

            block (bool): Should the call block until the ramp is complete?
        """

        # We need to know the current dac value (in raw units), as well as the
        # update rate
        c_volt = self.volt.get()  # Current Voltage
        if c_volt == val:
            # If we are already at the right voltage, we don't need to ramp
            return
        c_val = self._dac_v_to_code(c_volt)  # Current voltage in DAC units
        e_val = self._dac_v_to_code(val)  # Endpoint in DAC units
        # Number of refreshes per second
        t_rate = 1 / (self.update_period.get() * 1e-6)
        # Number of seconds to ramp
        secs = abs((c_volt - val) / rate)

        # The formula to calculate the slope is: Number of DAC steps divided by
        # the number of time steps in the ramp multiplied by 65536
        slope = int(((e_val - c_val) / (t_rate * secs)) * 65536)

        # Now let's set up our limits and ramo slope
        if slope > 0:
            self.upper_ramp_limit.set(val)
        else:
            self.lower_ramp_limit.set(val)
        self.slope.set(slope)

        # Block until the ramp is complete is block is True
        if block:
            while self.slope.get() != 0:
                pass

    def _set_dac(self, code):
        """
        Set the voltage on the dac channel, ramping if the enable_rate
        parameter is set for this channel.

        Params:
            code (int): the DAC code to set the voltage to
        """
        if self.enable_ramp.get():
            self._ramp(self._dac_code_to_v(code), rate=self.ramp_rate.get())
        else:
            code = int(code)
            self._set_channel()
            self.ask_raw("U65535;L0;D{};".format(code))

    def write(self, cmd):
        """
        Overload write to set channel prior to any channel operations.
        Since all commands are echoed back, we must keep track of responses
        as well, otherwise commands receive the wrong response.
        """
        self._set_channel()
        return self.ask_raw(cmd)

    def ask(self, cmd):
        """
        Overload ask to set channel prior to operations
        """
        self._set_channel()
        return self.ask_raw(cmd)
Beispiel #4
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
                           )
Beispiel #5
0
class DacSlot(InstrumentChannel, DacReader):
    """
    A single DAC Slot of the DECADAC
    """
    _SLOT_VAL = vals.Ints(0, 4)
    SLOT_MODE_DEFAULT = "Coarse"

    def __init__(self, parent, name, slot, min_val=-5, max_val=5):
        super().__init__(parent, name)

        # Validate slot and channel values
        self._SLOT_VAL.validate(slot)
        self._slot = slot

        # Store whether we have access to the VERSADAC EEPROM
        self._VERSA_EEPROM_available = self.parent._VERSA_EEPROM_available

        # Create a list of channels in the slot
        channels = ChannelList(self, "Slot_Channels", parent.DAC_CHANNEL_CLASS)
        for i in range(4):
            channels.append(
                parent.DAC_CHANNEL_CLASS(self,
                                         f"Chan{i}",
                                         i,
                                         min_val=min_val,
                                         max_val=max_val))
        self.add_submodule("channels", channels)
        # Set the slot mode. Valid modes are:
        #   Off: Channel outputs are disconnected from the input, grounded
        #       with 10MOhm.
        #   Fine: 2-channel mode. Channels 0 and 1 are output, use 2 and 3
        #       for fine adjustment of Channels 0 and 1 respectively
        #   Coarse: All 4 channels are used as output
        #   FineCald: Calibrated 2-channel mode, with 0 and 1 output, 2 and 3
        #       used automatically for fine adjustment. This mode only works
        #       for calibrated DecaDAC's
        #
        # Unfortunately there is no known way of reading the slot mode hence
        # this will be set in initialization
        if self.parent._cal_supported:
            slot_modes = {"Off": 0, "Fine": 1, "Coarse": 2, "FineCald": 3}
        else:
            slot_modes = {"Off": 0, "Fine": 1, "Coarse": 2}
        self.add_parameter('slot_mode',
                           get_cmd="m;",
                           get_parser=self._dac_parse,
                           set_cmd="M{};",
                           val_mapping=slot_modes)

        # Enable all slots in coarse mode.
        self.slot_mode.set(self.SLOT_MODE_DEFAULT)

    def write(self, cmd):
        """
        Overload write to set channel prior to any channel operations.
        Since all commands are echoed back, we must keep track of responses
        as well, otherwise commands receive the wrong response.
        """
        self._set_slot()
        return self.ask_raw(cmd)

    def ask(self, cmd):
        """
        Overload ask to set channel prior to operations
        """
        self._set_slot()
        return self.ask_raw(cmd)
Beispiel #6
0
    def __init__(self, parent: 'B1520A', name: str, **kwargs: Any):
        super().__init__(parent, name, **kwargs)

        self.add_parameter(name='sweep_auto_abort',
                           set_cmd=self._set_sweep_auto_abort,
                           get_cmd=self._get_sweep_auto_abort,
                           set_parser=constants.Abort,
                           get_parser=constants.Abort,
                           vals=vals.Enum(*list(constants.Abort)),
                           initial_cache_value=constants.Abort.ENABLED,
                           docstring=textwrap.dedent("""
                           enables or disables the automatic abort function 
                           for the CV (DC bias) sweep measurement (MM18) and 
                           the pulsed bias sweep measurement (MM20). The 
                           automatic abort function stops the measurement 
                           when one of the following conditions occurs:
                               - NULL loop unbalance condition
                               - IV amplifier saturation condition
                               - Overflow on the AD converter
                           """))

        self.add_parameter(name='post_sweep_voltage_condition',
                           set_cmd=self._set_post_sweep_voltage_condition,
                           get_cmd=self._get_post_sweep_voltage_condition,
                           set_parser=constants.WMDCV.Post,
                           get_parser=constants.WMDCV.Post,
                           vals=vals.Enum(*list(constants.WMDCV.Post)),
                           initial_cache_value=constants.WMDCV.Post.START,
                           docstring=textwrap.dedent("""
                           This command also sets the post measurement 
                           condition of the MFCMU. After the measurement is 
                           normally completed, the DC bias sweep source 
                           forces the value specified by the post parameter, 
                           and the pulsed bias sweep source forces 
                           the pulse base value.
                           If the measurement is stopped by the automatic  
                           abort function, the DC bias sweep source forces 
                           the start value, and the pulsed bias sweep source 
                           forces the pulse base value after sweep.
                           """))

        self.add_parameter(name='hold_time',
                           initial_value=0.0,
                           vals=vals.Numbers(0, 655.35),
                           unit='s',
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                           Hold time (in seconds) that is the 
                           wait time after starting measurement 
                           and before starting delay time for 
                           the first step 0 to 655.35, with 10 
                           ms resolution. Numeric expression.
                          """))

        self.add_parameter(name='delay',
                           initial_value=0.0,
                           vals=vals.Numbers(0, 65.535),
                           unit='s',
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                           Delay time (in seconds) that is the wait time after
                           starting to force a step output and before 
                            starting a step measurement. 0 to 65.535, 
                            with 0.1 ms resolution. Numeric expression.
                            """))

        self.add_parameter(name='step_delay',
                           initial_value=0.0,
                           vals=vals.Numbers(0, 1),
                           unit='s',
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                            Step delay time (in seconds) that is the wait time
                            after starting a step measurement and before  
                            starting to force the next step output. 0 to 1, 
                            with 0.1 ms resolution. Numeric expression. If 
                            this parameter is not set, step delay will be 0. If 
                            step delay is shorter than the measurement time, 
                            the B1500 waits until the measurement completes, 
                            then forces the next step output.
                            """))

        self.add_parameter(name='trigger_delay',
                           initial_value=0.0,
                           unit='s',
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                            Step source trigger delay time (in seconds) that
                            is the wait time after completing a step output 
                            setup and before sending a step output setup 
                            completion trigger. 0 to the value of ``delay``, 
                            with 0.1 ms resolution. Numeric expression. If this
                            parameter is not set, trigger delay will be 0.
                            """))

        self.add_parameter(name='measure_delay',
                           initial_value=0.0,
                           unit='s',
                           vals=vals.Numbers(0, 65.535),
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                           Step measurement trigger delay time (in seconds)
                           that is the wait time after receiving a start step 
                           measurement trigger and before starting a step 
                           measurement. 0 to 65.535, with 0.1 ms resolution. 
                           Numeric expression. If this parameter is not set, 
                           measure delay will be 0.
                           """))

        self._set_sweep_delays_group = Group([self.hold_time,
                                       self.delay,
                                       self.step_delay,
                                       self.trigger_delay,
                                       self.measure_delay],
                                      set_cmd='WTDCV '
                                              '{hold_time},'
                                              '{delay},'
                                              '{step_delay},'
                                              '{trigger_delay},'
                                              '{measure_delay}',
                                      get_cmd=self._get_sweep_delays(),
                                      get_parser=self._get_sweep_delays_parser)

        self.add_parameter(name='sweep_mode',
                           initial_value=constants.SweepMode.LINEAR,
                           vals=vals.Enum(*list(constants.SweepMode)),
                           set_parser=constants.SweepMode,
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                   Sweep mode. 
                       1: Linear sweep (single stair, start to stop.)
                       2: Log sweep (single stair, start to stop.)
                       3: Linear sweep (double stair, start to stop to start.)
                       4: Log sweep (double stair, start to stop to start.)
                                  """))

        self.add_parameter(name='sweep_start',
                           initial_value=0.0,
                           unit='V',
                           vals=vals.Numbers(-25, 25),
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                   Start value of the DC bias sweep (in V). For the log  sweep, 
                   start and stop must have the same polarity.
                                  """))

        self.add_parameter(name='sweep_end',
                           initial_value=0.0,
                           unit='V',
                           vals=vals.Numbers(-25, 25),
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                   Stop value of the DC bias sweep (in V). For the log sweep, 
                   start and stop must have the same polarity.
                                  """))

        self.add_parameter(name='sweep_steps',
                           initial_value=1,
                           vals=vals.Ints(1, 1001),
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                   Number of steps for staircase sweep. Possible  values from 1 to 
                   1001"""))

        self.add_parameter(name='_chan',
                           initial_value=self.parent.channels[0],
                           parameter_class=GroupParameter)

        self._set_sweep_steps_group = Group(
            [self._chan,
             self.sweep_mode,
             self.sweep_start,
             self.sweep_end,
             self.sweep_steps],
            set_cmd='WDCV '
                    '{_chan},'
                    '{sweep_mode},'
                    '{sweep_start},'
                    '{sweep_end},'
                    '{sweep_steps}',
            get_cmd=self._get_sweep_steps(),
            get_parser=self._get_sweep_steps_parser
        )
Beispiel #7
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 = 460800
        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
        self.num_chans = num_chans

        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._update_currents = update_currents

        # 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)
        self._params_to_skip_update = []
        for i in self.chan_range:
            self._params_to_skip_update.append('ch{:02}_v'.format(i))
            self._params_to_skip_update.append('ch{:02}_i'.format(i))
            self._params_to_skip_update.append('ch{:02}_vrange'.format(i))
            self._params_to_skip_update.append('ch{:02}_irange'.format(i))
            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',
                               get_cmd=None,
                               set_cmd=None,
                               initial_value=0)

            self.add_parameter(
                name='ch{:02}_sync_duration'.format(i),
                label='Channel {} sync pulse duration'.format(i),
                unit='s',
                get_cmd=None,
                set_cmd=None,
                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
                           })

        self.add_parameter(
            name='fast_voltage_set',
            label='fast voltage set',
            get_cmd=None,
            set_cmd=None,
            vals=vals.Bool(),
            initial_value=False,
            docstring=
            """"Toggles if DC voltage set should unset any ramp attached to this channel.
                                     If you enable this you should ensure thay any function generator is unset
                                     from the channel before setting voltage"""
        )
        # 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')
    def add_parameters_from_file(self, filename: str):
        """
        Takes in a node_doc JSON file auto generates parameters based on
        the contents of this file.
        """
        f = open(filename).read()
        node_pars = json.loads(f)
        for par in node_pars.values():
            node = par['Node'].split('/')
            # The parfile is valid for all devices of a certain type
            # so the device name has to be split out.
            parname = '_'.join(node[2:]).lower()
            parfunc = "/" + self._devname + "/" + "/".join(node[2:])

            # This block provides the mapping between the ZI node and QCoDes
            # parameter.
            par_kw = {}
            par_kw['name'] = parname
            if par['Unit'] != 'None':
                par_kw['unit'] = par['Unit']
            else:
                par_kw['unit'] = 'arb. unit'

            par_kw['docstring'] = par['Description']
            if "Options" in par.keys():
                # options can be done better, this is not sorted
                par_kw['docstring'] += '\nOptions:\n' + str(par['Options'])

            # Creates type dependent get/set methods
            if par['Type'] == 'Integer (64 bit)':
                par_kw['set_cmd'] = self._gen_set_func(self._dev.seti, parfunc)
                par_kw['get_cmd'] = self._gen_get_func(self._dev.geti, parfunc)
                # min/max not implemented yet for ZI auto docstrings #352
                par_kw['vals'] = vals.Ints()

            elif par['Type'] == 'Double':
                par_kw['set_cmd'] = self._gen_set_func(self._dev.setd, parfunc)
                par_kw['get_cmd'] = self._gen_get_func(self._dev.getd, parfunc)
                # min/max not implemented yet for ZI auto docstrings #352
                par_kw['vals'] = vals.Numbers()

            elif par['Type'] == 'ZIVectorData':
                par_kw['set_cmd'] = self._gen_set_func(self._dev.setv, parfunc)
                par_kw['get_cmd'] = self._gen_get_func(self._dev.getv, parfunc)
                # min/max not implemented yet for ZI auto docstrings #352
                par_kw['vals'] = vals.Arrays()

            elif par['Type'] == 'CoreString':
                par_kw['get_cmd'] = self._gen_get_func(self._dev.getd, parfunc)
                par_kw['set_cmd'] = None  # Not implemented
                par_kw['vals'] = vals.Strings()

            else:
                raise NotImplementedError

            # If not readable/writable the methods are removed after the type
            # dependent loop to keep this more readable.
            if 'Read' not in par['Properties']:
                par_kw['get_cmd'] = None
            if 'Write' not in par['Properties']:
                par_kw['set_cmd'] = None
            self.add_parameter(**par_kw)
Beispiel #9
0
    def __init__(self, name, address, **kwargs):
        super().__init__(name,
                         address,
                         terminator='\r\n',
                         timeout=10,
                         **kwargs)
        self.channel_mapping = {
            'T0': 0,
            'T1': 1,
            'A': 2,
            'B': 3,
            'C': 4,
            'D': 5,
            'E': 6,
            'F': 7,
            'G': 8,
            'H': 9
        }
        self.output_mapping = {'T0': 0, 'AB': 1, 'CD': 2, 'EF': 3, 'GH': 4}
        # self.display_mapping = {
        #     'trig_rate': 0,
        #     'trig_thresh': 1,
        #     'trig_single_shot': 2,
        #     'trig_line': 3,
        #     'advanced_trig_enable': 4,
        #     'trig_holdoff': 5,
        #     'prescale_config': 6,
        #     'burst_mode': 7,
        #     'burst_delay': 8,
        #     'burst_count': 9,
        #     'burst_period': 10,
        #     'channel_delay': 11,
        #     'channel_output_levels': 12,
        #     'channel_output_polarity': 13,
        #     'burst_T0_config': 14
        # }
        self.prescale_mapping = {'trig': 0, 'AB': 1, 'CD': 2, 'EF': 3, 'GH': 4}
        self.trig_mapping = {
            'internal': 0,
            'ext_rising': 1,
            'ext_falling': 2,
            'single_ext_rising': 3,
            'single_ext_falling': 4,
            'single': 5,
            'line': 6
        }
        self.polarity_mapping = {'-': 0, '+': 1}

        self.add_parameter('trig_holdoff',
                           label='Trigger holdoff',
                           unit='s',
                           get_cmd='HOLD?',
                           get_parser=float,
                           set_cmd='HOLD {}')

        #: Prescale parameters
        for k, v in self.prescale_mapping.items():
            if v > 0:
                self.add_parameter(
                    'phase_{}'.format(k),
                    label='Prescale phase factor {}'.format(k),
                    unit='',
                    get_cmd=lambda ch=k: self._get_phase_prescale(ch),
                    get_parser=int,
                    set_cmd=lambda val, ch=k: self._set_phase_prescale(
                        val, channel=ch),
                    vals=vals.Ints(min_value=0))

            self.add_parameter(
                'prescale_{}'.format(v),
                label='Prescale factor {}'.format(v),
                unit='',
                get_cmd=lambda ch=k: self._get_prescale(ch),
                get_parser=int,
                set_cmd=lambda val, ch=k: self._set_prescale(val, channel=ch),
                vals=vals.Ints(min_value=0))

        #: Trigger parameters
        self.add_parameter('trig_level',
                           label='Trigger level',
                           unit='V',
                           get_cmd='TLVL?',
                           get_parser=float,
                           set_cmd='TLVL {}',
                           vals=vals.Numbers())
        self.add_parameter('trig_rate',
                           label='Trigger rate',
                           unit='Hz',
                           get_cmd='TRAT?',
                           get_parser=float,
                           set_cmd='TRAT {}',
                           vals=vals.Numbers(min_value=0))
        self.add_parameter('trig_source',
                           label='Trigger source',
                           unit='',
                           get_cmd=self._get_trig_source,
                           get_parser=str,
                           set_cmd=self._set_trig_source,
                           vals=vals.Enum(tuple(self.trig_mapping.keys())))

        #: Burst parameters
        self.add_parameter('burst_count',
                           label='Burst count',
                           unit='',
                           get_cmd='BURC?',
                           get_parser=int,
                           set_cmd='BURC {}',
                           vals=vals.Ints(min_value=0))
        self.add_parameter('burst_delay',
                           label='Burst delay',
                           unit='s',
                           get_cmd='BURD?',
                           get_parser=float,
                           set_cmd='BURD {}',
                           vals=vals.Numbers(min_value=0))
        self.add_parameter('burst_period',
                           label='Burst period',
                           unit='s',
                           get_cmd='BURP?',
                           get_parser=float,
                           set_cmd='BURC {}',
                           vals=vals.Numbers(min_value=100e-9,
                                             max_value=2000 - 10e-9))
        self.add_parameter('burst_T0_config',
                           label='Burst T0 configuration',
                           unit='',
                           get_cmd='BURT?',
                           get_parser=int,
                           set_cmd='BURT {}',
                           vals=vals.Enum(0, 1))

        #: Channel parameters
        for ch, idx in self.channel_mapping.items():
            if idx > 1:
                self.add_parameter(
                    'delay_{}'.format(ch),
                    label='{} delay'.format(ch),
                    unit='s',
                    get_cmd=lambda c=ch: self._get_delay(channel=c),
                    get_parser=str,
                    set_cmd=lambda src_delay, c=ch: self._set_delay(src_delay,
                                                                    target=c),
                    vals=vals.Strings())
                self.add_parameter(
                    'channel_link_{}'.format(ch),
                    label='Channel linked to {}'.format(ch),
                    unit='',
                    get_cmd=lambda c=ch: self._get_link(channel=c),
                    get_parser=int,
                    set_cmd=lambda d, c=ch: self._set_link(d, channel=c),
                    vals=vals.Enum(
                        tuple(k for k in self.channel_mapping if k != 'T1')))

        #: Output parameters
        for out, idx in self.output_mapping.items():
            self.add_parameter(
                'amp_out_{}'.format(out),
                label='Output {} amplitude'.format(out),
                unit='V',
                get_cmd=lambda o=out: self._get_amp(output=o),
                get_parser=float,
                set_cmd=lambda lvl, o=out: self._set_amp(lvl, output=o),
                vals=vals.Numbers())
            self.add_parameter(
                'offset_out_{}'.format(out),
                label='Output {} offset'.format(out),
                unit='V',
                get_cmd=lambda o=out: self._get_offset(output=o),
                get_parser=float,
                set_cmd=lambda lvl, o=out: self._set_offset(lvl, output=o),
                vals=vals.Numbers())
            self.add_parameter(
                'polarity_out_{}'.format(out),
                label='Output {} polarity'.format(out),
                unit='',
                get_cmd=lambda o=out: self._get_polarity(output=o),
                get_parser=int,
                set_cmd=lambda lvl, o=out: self._set_offset(lvl, output=o),
                vals=vals.Enum(0, 1))

        self.snapshot(update=True)
        self.connect_message()
Beispiel #10
0
    def __init__(self, name, **kwargs):
        dll_path = 'C:\\WINDOWS\\System32\\ATSApi.dll'
        super().__init__(name, dll_path=dll_path, **kwargs)

        self._bwlimit_support = False

        # add parameters
        self.channels = ['A', 'B', 'C', 'D']

        # ----- Parameters for the configuration of the board -----
        self.add_parameter(name='clock_source',
                           parameter_class=AlazarParameter,
                           label='Clock Source',
                           unit=None,
                           value='internal_clock',
                           byte_to_value_dict={
                               1: 'internal_clock',
                               4: 'slow_external_clock',
                               5: 'external_clock_AC',
                               7: 'external_clock_10_MHz_ref'
                           })
        self.add_parameter(name='sample_rate',
                           parameter_class=AlazarParameter,
                           label='Sample Rate',
                           unit='S/s',
                           value=100000,
                           byte_to_value_dict={
                               0x1: 1000,
                               0x2: 2000,
                               0x4: 5000,
                               0x8: 10000,
                               0xA: 20000,
                               0xC: 50000,
                               0xE: 100000,
                               0x10: 200000,
                               0x12: 500000,
                               0x14: 1000000,
                               0x18: 2000000,
                               0x1A: 5000000,
                               0x1C: 10000000,
                               0x1E: 20000000,
                               0x22: 50000000,
                               0x24: 100000000,
                               0x25: 125000000,
                               0x40: 'external_clock',
                               1000000000: '1GHz_reference_clock'
                           })
        self.add_parameter(name='clock_edge',
                           parameter_class=AlazarParameter,
                           label='Clock Edge',
                           unit=None,
                           value='rising',
                           byte_to_value_dict={
                               0: 'rising',
                               1: 'falling'
                           })

        self.add_parameter(name='decimation',
                           parameter_class=AlazarParameter,
                           label='Decimation',
                           unit=None,
                           value=0,
                           vals=validators.Ints(0, 100000))

        # Acquisition channel parameters
        for ch in self.channels:
            self.add_parameter(name='coupling' + ch,
                               parameter_class=AlazarParameter,
                               label='Coupling channel ' + ch,
                               unit=None,
                               value='DC',
                               byte_to_value_dict={
                                   1: 'AC',
                                   2: 'DC'
                               })
            self.add_parameter(name='channel_range' + ch,
                               parameter_class=AlazarParameter,
                               label='Range channel ' + ch,
                               unit='V',
                               value=1,
                               byte_to_value_dict={
                                   5: 0.1,
                                   6: 0.2,
                                   7: 0.4,
                                   10: 1.,
                                   11: 2.,
                                   12: 4.
                               })
            self.add_parameter(name='impedance' + ch,
                               parameter_class=AlazarParameter,
                               label='Impedance channel ' + ch,
                               unit='Ohm',
                               value=50,
                               byte_to_value_dict={2: 50})

        # Trigger parameters
        self.add_parameter(name='trigger_operation',
                           parameter_class=AlazarParameter,
                           label='Trigger Operation',
                           unit=None,
                           value='J',
                           byte_to_value_dict={
                               0: 'J',
                               1: 'K',
                               2: 'J_or_K',
                               3: 'J_and_K',
                               4: 'J_xor_K',
                               5: 'J_and_not_K',
                               6: 'not_J_and_K'
                           })
        for i in ['1', '2']:
            self.add_parameter(name='trigger_engine' + i,
                               parameter_class=AlazarParameter,
                               label='Trigger Engine ' + i,
                               unit=None,
                               value=('J' if i == '1' else 'K'),
                               byte_to_value_dict={
                                   0: 'J',
                                   1: 'K'
                               })
            self.add_parameter(name='trigger_source' + i,
                               parameter_class=AlazarParameter,
                               label='Trigger Source ' + i,
                               unit=None,
                               value='disable',
                               byte_to_value_dict={
                                   0: 'A',
                                   1: 'B',
                                   2: 'trig_in',
                                   3: 'disable',
                                   4: 'C',
                                   5: 'D'
                               })
            self.add_parameter(name='trigger_slope' + i,
                               parameter_class=AlazarParameter,
                               label='Trigger Slope ' + i,
                               unit=None,
                               value='positive',
                               byte_to_value_dict={
                                   1: 'positive',
                                   2: 'negative'
                               })
            self.add_parameter(name='trigger_level' + i,
                               parameter_class=AlazarParameter,
                               label='Trigger Level ' + i,
                               unit=None,
                               value=150,
                               vals=validators.Ints(0, 255))

        self.add_parameter(name='external_trigger_coupling',
                           parameter_class=AlazarParameter,
                           label='External Trigger Coupling',
                           unit=None,
                           value='AC',
                           byte_to_value_dict={
                               1: 'AC',
                               2: 'DC'
                           })
        self.add_parameter(name='external_trigger_range',
                           parameter_class=AlazarParameter,
                           label='External Trigger Range',
                           unit='V',
                           value=5,
                           byte_to_value_dict={
                               0: 5,
                               1: 1
                           })
        self.add_parameter(name='trigger_delay',
                           parameter_class=AlazarParameter,
                           label='Trigger Delay',
                           unit='Sample clock cycles',
                           value=0,
                           vals=validators.Ints(min_value=0))

        # NOTE: The board will wait for a for this amount of time for a
        # trigger event.  If a trigger event does not arrive, then the
        # board will automatically trigger. Set the trigger timeout value
        # to 0 to force the board to wait forever for a trigger event.
        #
        # IMPORTANT: The trigger timeout value should be set to zero after
        # appropriate trigger parameters have been determined, otherwise
        # the board may trigger if the timeout interval expires before a
        # hardware trigger event arrives.
        self.add_parameter(name='timeout_ticks',
                           parameter_class=AlazarParameter,
                           label='Timeout Ticks',
                           unit='10 us',
                           value=0,
                           vals=validators.Ints(min_value=0))

        # ----- Parameters for the acquire function -----
        self.add_parameter(name='mode',
                           parameter_class=AlazarParameter,
                           label='Acquisition mode',
                           unit=None,
                           value='NPT',
                           byte_to_value_dict={
                               0x100: 'CS',
                               0x200: 'NPT',
                               0x400: 'TS'
                           })

        # samples_per_record must be a multiple of 32, and 256 minimum!
        # TODO check if it is 32 or 16, manual is unclear
        self.add_parameter(name='samples_per_record',
                           parameter_class=AlazarParameter,
                           label='Samples per Record',
                           unit=None,
                           value=1024,
                           vals=validators.Multiples(divisor=16, min_value=16))

        self.add_parameter(name='records_per_buffer',
                           parameter_class=AlazarParameter,
                           label='Records per Buffer',
                           unit=None,
                           value=10,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='buffers_per_acquisition',
                           parameter_class=AlazarParameter,
                           label='Buffers per Acquisition',
                           unit=None,
                           value=10,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='channel_selection',
                           parameter_class=AlazarParameter,
                           label='Channel Selection',
                           unit=None,
                           value='AB',
                           byte_to_value_dict={
                               1: 'A',
                               2: 'B',
                               3: 'AB',
                               4: 'C',
                               5: 'AC',
                               6: 'BC',
                               8: 'D',
                               9: 'AD',
                               10: 'BD',
                               12: 'CD',
                               15: 'ABCD'
                           })
        self.add_parameter(name='transfer_offset',
                           parameter_class=AlazarParameter,
                           label='Transer Offset',
                           unit='Samples',
                           value=0,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='external_startcapture',
                           parameter_class=AlazarParameter,
                           label='External Startcapture',
                           unit=None,
                           value='enabled',
                           byte_to_value_dict={
                               0x0: 'disabled',
                               0x1: 'enabled'
                           })
        self.add_parameter(name='enable_record_headers',
                           parameter_class=AlazarParameter,
                           label='Enable Record Headers',
                           unit=None,
                           value='disabled',
                           byte_to_value_dict={
                               0x0: 'disabled',
                               0x8: 'enabled'
                           })
        self.add_parameter(name='alloc_buffers',
                           parameter_class=AlazarParameter,
                           label='Alloc Buffers',
                           unit=None,
                           value='disabled',
                           byte_to_value_dict={
                               0x0: 'disabled',
                               0x20: 'enabled'
                           })
        self.add_parameter(name='fifo_only_streaming',
                           parameter_class=AlazarParameter,
                           label='Fifo Only Streaming',
                           unit=None,
                           value='disabled',
                           byte_to_value_dict={
                               0x0: 'disabled',
                               0x800: 'enabled'
                           })
        self.add_parameter(name='interleave_samples',
                           parameter_class=AlazarParameter,
                           label='Interleave Samples',
                           unit=None,
                           value='disabled',
                           byte_to_value_dict={
                               0x0: 'disabled',
                               0x1000: 'enabled'
                           })
        self.add_parameter(name='get_processed_data',
                           parameter_class=AlazarParameter,
                           label='Get Processed Data',
                           unit=None,
                           value='disabled',
                           byte_to_value_dict={
                               0x0: 'disabled',
                               0x2000: 'enabled'
                           })

        self.add_parameter(name='allocated_buffers',
                           parameter_class=AlazarParameter,
                           label='Allocated Buffers',
                           unit=None,
                           value=2,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='buffer_timeout',
                           parameter_class=AlazarParameter,
                           label='Buffer Timeout',
                           unit='ms',
                           value=1000,
                           vals=validators.Ints(min_value=0))
    def __init__(self, parent: 'B1517A', name: str, **kwargs: Any):
        super().__init__(parent, name, **kwargs)
        self._sweep_step_parameters: SweepSteps = \
            {"sweep_mode": constants.SweepMode.LINEAR,
             "sweep_range": constants.VOutputRange.AUTO,
             "sweep_start": 0.0,
             "sweep_end": 0.0,
             "sweep_steps": 1,
             "current_compliance": None,
             "power_compliance": None}

        self.add_parameter(name='sweep_auto_abort',
                           set_cmd=self._set_sweep_auto_abort,
                           get_cmd=self._get_sweep_auto_abort,
                           set_parser=constants.Abort,
                           get_parser=constants.Abort,
                           vals=vals.Enum(*list(constants.Abort)),
                           initial_cache_value=constants.Abort.ENABLED,
                           docstring=textwrap.dedent("""
        The WM command enables or disables the automatic abort function for
        the staircase sweep sources and the pulsed sweep source. The
        automatic abort function stops the measurement when one of the
        following conditions occurs:
         - Compliance on the measurement channel
         - Compliance on the non-measurement channel
         - Overflow on the AD converter
         - Oscillation on any channel
        This command also sets the post measurement condition for the sweep
        sources. After the measurement is normally completed, the staircase
        sweep sources force the value specified by the post parameter,
        and the pulsed sweep source forces the pulse base value.

        If the measurement is stopped by the automatic abort function,
        the staircase sweep sources force the start value, and the pulsed
        sweep source forces the pulse base value after sweep.
        """))

        self.add_parameter(name='post_sweep_voltage_condition',
                           set_cmd=self._set_post_sweep_voltage_condition,
                           get_cmd=self._get_post_sweep_voltage_condition,
                           set_parser=constants.WM.Post,
                           get_parser=constants.WM.Post,
                           vals=vals.Enum(*list(constants.WM.Post)),
                           initial_cache_value=constants.WM.Post.START,
                           docstring=textwrap.dedent("""
        Source output value after the measurement is normally completed. If
        this parameter is not set, the sweep sources force the start value.
                                 """))

        self.add_parameter(name='hold_time',
                           initial_value=0.0,
                           vals=vals.Numbers(0, 655.35),
                           unit='s',
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                           Hold time (in seconds) that is the
                           wait time after starting measurement
                           and before starting delay time for
                           the first step 0 to 655.35 s, with 10
                           ms resolution. Numeric expression.
                          """))

        self.add_parameter(name='delay',
                           initial_value=0.0,
                           vals=vals.Numbers(0, 65.535),
                           unit='s',
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                           Delay time (in seconds) that is the wait time after
                           starting to force a step output and before
                            starting a step measurement. 0 to 65.535 s,
                            with 0.1 ms resolution. Numeric expression.
                            """))

        self.add_parameter(name='step_delay',
                           initial_value=0.0,
                           vals=vals.Numbers(0, 1),
                           unit='s',
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                            Step delay time (in seconds) that is the wait time
                            after starting a step measurement and before
                            starting to force the next step output. 0 to 1 s,
                            with 0.1 ms resolution. Numeric expression. If
                            this parameter is not set, step delay will be 0. If
                            step delay is shorter than the measurement time,
                            the B1500 waits until the measurement completes,
                            then forces the next step output.
                            """))

        self.add_parameter(name='trigger_delay',
                           initial_value=0.0,
                           unit='s',
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                            Step source trigger delay time (in seconds) that
                            is the wait time after completing a step output
                            setup and before sending a step output setup
                            completion trigger. 0 to the value of ``delay`` s,
                            with 0.1 ms resolution.
                            If this parameter is not set,
                            trigger delay will be 0.
                            """))

        self.add_parameter(name='measure_delay',
                           initial_value=0.0,
                           unit='s',
                           vals=vals.Numbers(0, 65.535),
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
                           Step measurement trigger delay time (in seconds)
                           that is the wait time after receiving a start step
                           measurement trigger and before starting a step
                           measurement. 0 to 65.535 s, with 0.1 ms resolution.
                           Numeric expression. If this parameter is not set,
                           measure delay will be 0.
                           """))

        self._set_sweep_delays_group = Group(
            [
                self.hold_time, self.delay, self.step_delay,
                self.trigger_delay, self.measure_delay
            ],
            set_cmd='WT '
            '{hold_time},'
            '{delay},'
            '{step_delay},'
            '{trigger_delay},'
            '{measure_delay}',
            get_cmd=self._get_sweep_delays(),
            get_parser=self._get_sweep_delays_parser)

        self.add_parameter(name='sweep_mode',
                           set_cmd=self._set_sweep_mode,
                           get_cmd=self._get_sweep_mode,
                           vals=vals.Enum(*list(constants.SweepMode)),
                           set_parser=constants.SweepMode,
                           snapshot_get=False,
                           docstring=textwrap.dedent("""
                 Sweep mode. Note that Only linear sweep (mode=1 or 3) is
                 available for the staircase sweep with pulsed bias.
                     1: Linear sweep (single stair, start to stop.)
                     2: Log sweep (single stair, start to stop.)
                     3: Linear sweep (double stair, start to stop to start.)
                     4: Log sweep (double stair, start to stop to start.)
                                """))

        self.add_parameter(name='sweep_range',
                           set_cmd=self._set_sweep_range,
                           get_cmd=self._get_sweep_range,
                           vals=vals.Enum(*list(constants.VOutputRange)),
                           set_parser=constants.VOutputRange,
                           snapshot_get=False,
                           docstring=textwrap.dedent("""
        Ranging type for staircase sweep voltage output. Integer expression.
        See Table 4-4 on page 20. The B1500 usually uses the minimum range
        that covers both start and stop values to force the staircase sweep
        voltage. However, if you set `power_compliance` and if the following
        formulas are true, the B1500 uses the minimum range that covers the
        output value, and changes the output range dynamically (20 V range or
        above). Range changing may cause 0 V output in a moment. For the
        limited auto ranging, the instrument never uses the range less than
        the specified range.
         - Icomp > maximum current for the output range
         - Pcomp/output voltage > maximum current for the output range
        """))

        self.add_parameter(name='sweep_start',
                           set_cmd=self._set_sweep_start,
                           get_cmd=self._get_sweep_start,
                           unit='V',
                           vals=vals.Numbers(-25, 25),
                           snapshot_get=False,
                           docstring=textwrap.dedent("""
        Start value of the stair case sweep (in V). For the log sweep,
        start and stop must have the same polarity.
                                """))

        self.add_parameter(name='sweep_end',
                           set_cmd=self._set_sweep_end,
                           get_cmd=self._get_sweep_end,
                           unit='V',
                           vals=vals.Numbers(-25, 25),
                           snapshot_get=False,
                           docstring=textwrap.dedent("""
        Stop value of the DC bias sweep (in V). For the log sweep,start and
        stop must have the same polarity.
                                """))

        self.add_parameter(name='sweep_steps',
                           set_cmd=self._set_sweep_steps,
                           get_cmd=self._get_sweep_steps,
                           vals=vals.Ints(1, 1001),
                           snapshot_get=False,
                           docstring=textwrap.dedent("""
        Number of steps for staircase sweep. Possible  values from 1 to
        1001"""))

        self.add_parameter(name='current_compliance',
                           set_cmd=self._set_current_compliance,
                           get_cmd=self._get_current_compliance,
                           unit='A',
                           vals=vals.Numbers(-40, 40),
                           snapshot_get=False,
                           docstring=textwrap.dedent("""
        Current compliance (in A). Refer to Manual 2016. See Table 4-7 on
        page 24, Table 4-9 on page 26, Table 4-12 on page 27, or Table 4-15
        on page 28 for each measurement resource type. If you do not set
        current_compliance, the previous value is used.
        Compliance polarity is automatically set to the same polarity as the
        output value, regardless of the specified Icomp.
        If the output value is 0, the compliance polarity is positive. If
        you set Pcomp, the maximum Icomp value for the measurement resource
        is allowed, regardless of the output range setting.
                           """))

        self.add_parameter(name='power_compliance',
                           set_cmd=self._set_power_compliance,
                           get_cmd=self._get_power_compliance,
                           unit='W',
                           vals=vals.Numbers(0.001, 80),
                           snapshot_get=False,
                           docstring=textwrap.dedent("""
        Power compliance (in W). Resolution: 0.001 W. If it is not entered,
        the power compliance is not set. This parameter is not available for
        HVSMU. 0.001 to 2 for MPSMU/HRSMU, 0.001 to 20 for HPSMU, 0.001 to
        40 for HCSMU, 0.001 to 80 for dual HCSMU, 0.001 to 3 for MCSMU,
        0.001 to 100 for UHVU
                           """))
Beispiel #12
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=AlazarParameter,
                           label='Clock Source',
                           unit=None,
                           value='INTERNAL_CLOCK',
                           byte_to_value_dict={
                               1: 'INTERNAL_CLOCK',
                               4: 'SLOW_EXTERNAL_CLOCK',
                               5: 'EXTERNAL_CLOCK_AC',
                               7: 'EXTERNAL_CLOCK_10_MHz_REF'
                           })
        self.add_parameter(name='sample_rate',
                           parameter_class=AlazarParameter,
                           label='Sample Rate',
                           unit='S/s',
                           value=1000000000,
                           byte_to_value_dict={
                               0x1: 1000,
                               0x2: 2000,
                               0x4: 5000,
                               0x8: 10000,
                               0xA: 20000,
                               0xC: 50000,
                               0xE: 100000,
                               0x10: 200000,
                               0x12: 500000,
                               0x14: 1000000,
                               0x18: 2000000,
                               0x1A: 5000000,
                               0x1C: 10000000,
                               0x1E: 20000000,
                               0x22: 50000000,
                               0x24: 100000000,
                               0x2B: 250000000,
                               0x30: 500000000,
                               0x35: 1000000000,
                               0x40: 'EXTERNAL_CLOCK',
                               1000000000: '1GHz_REFERENCE_CLOCK'
                           })
        self.add_parameter(name='clock_edge',
                           parameter_class=AlazarParameter,
                           label='Clock Edge',
                           unit=None,
                           value='CLOCK_EDGE_RISING',
                           byte_to_value_dict={
                               0: 'CLOCK_EDGE_RISING',
                               1: 'CLOCK_EDGE_FALLING'
                           })

        self.add_parameter(name='decimation',
                           parameter_class=AlazarParameter,
                           label='Decimation',
                           unit=None,
                           value=0,
                           vals=validators.Ints(0, 100000))

        for i in ['1', '2']:
            self.add_parameter(name='coupling' + i,
                               parameter_class=AlazarParameter,
                               label='Coupling channel ' + i,
                               unit=None,
                               value='AC',
                               byte_to_value_dict={
                                   1: 'AC',
                                   2: 'DC'
                               })
            self.add_parameter(name='channel_range' + i,
                               parameter_class=AlazarParameter,
                               label='Range channel ' + i,
                               unit='V',
                               value=4,
                               byte_to_value_dict={
                                   2: 0.04,
                                   5: 0.1,
                                   6: 0.2,
                                   7: 0.4,
                                   10: 1.,
                                   11: 2.,
                                   12: 4.
                               })
            self.add_parameter(name='impedance' + i,
                               parameter_class=AlazarParameter,
                               label='Impedance channel ' + i,
                               unit='Ohm',
                               value=50,
                               byte_to_value_dict={
                                   1: 1000000,
                                   2: 50
                               })
            self.add_parameter(name='bwlimit' + i,
                               parameter_class=AlazarParameter,
                               label='Bandwidth limit channel ' + i,
                               unit=None,
                               value='DISABLED',
                               byte_to_value_dict={
                                   0: 'DISABLED',
                                   1: 'ENABLED'
                               })

        self.add_parameter(name='trigger_operation',
                           parameter_class=AlazarParameter,
                           label='Trigger Operation',
                           unit=None,
                           value='TRIG_ENGINE_OP_J',
                           byte_to_value_dict={
                               0: 'TRIG_ENGINE_OP_J',
                               1: 'TRIG_ENGINE_OP_K',
                               2: 'TRIG_ENGINE_OP_J_OR_K',
                               3: 'TRIG_ENGINE_OP_J_AND_K',
                               4: 'TRIG_ENGINE_OP_J_XOR_K',
                               5: 'TRIG_ENGINE_OP_J_AND_NOT_K',
                               6: 'TRIG_ENGINE_OP_NOT_J_AND_K'
                           })
        for i in ['1', '2']:
            self.add_parameter(name='trigger_engine' + i,
                               parameter_class=AlazarParameter,
                               label='Trigger Engine ' + i,
                               unit=None,
                               value='TRIG_ENGINE_' + ('J' if i == 0 else 'K'),
                               byte_to_value_dict={
                                   0: 'TRIG_ENGINE_J',
                                   1: 'TRIG_ENGINE_K'
                               })
            self.add_parameter(name='trigger_source' + i,
                               parameter_class=AlazarParameter,
                               label='Trigger Source ' + i,
                               unit=None,
                               value='DISABLE',
                               byte_to_value_dict={
                                   0: 'CHANNEL_A',
                                   1: 'CHANNEL_B',
                                   2: 'EXTERNAL',
                                   3: 'DISABLE'
                               })
            self.add_parameter(name='trigger_slope' + i,
                               parameter_class=AlazarParameter,
                               label='Trigger Slope ' + i,
                               unit=None,
                               value='TRIG_SLOPE_POSITIVE',
                               byte_to_value_dict={
                                   1: 'TRIG_SLOPE_POSITIVE',
                                   2: 'TRIG_SLOPE_NEGATIVE'
                               })
            self.add_parameter(name='trigger_level' + i,
                               parameter_class=AlazarParameter,
                               label='Trigger Level ' + i,
                               unit=None,
                               value=128,
                               vals=validators.Ints(0, 255))

        self.add_parameter(name='external_trigger_coupling',
                           parameter_class=AlazarParameter,
                           label='External Trigger Coupling',
                           unit=None,
                           value='AC',
                           byte_to_value_dict={
                               1: 'AC',
                               2: 'DC'
                           })
        self.add_parameter(name='external_trigger_range',
                           parameter_class=AlazarParameter,
                           label='External Trigger Range',
                           unit=None,
                           value='ETR_5V',
                           byte_to_value_dict={
                               0: 'ETR_5V',
                               1: 'ETR_1V'
                           })
        self.add_parameter(name='trigger_delay',
                           parameter_class=AlazarParameter,
                           label='Trigger Delay',
                           unit='Sample clock cycles',
                           value=0,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='timeout_ticks',
                           parameter_class=AlazarParameter,
                           label='Timeout Ticks',
                           unit='10 us',
                           value=0,
                           vals=validators.Ints(min_value=0))

        # ----- Parameters for the acquire function -----
        self.add_parameter(name='mode',
                           parameter_class=AlazarParameter,
                           label='Acquisiton mode',
                           unit=None,
                           value='NPT',
                           byte_to_value_dict={
                               0x200: 'NPT',
                               0x400: 'TS'
                           })

        # samples_per_record must be a multiple of of some number (64 in the
        # case of ATS9870) and and has some minimum (256 in the case of ATS9870)
        # These values can be found in the ATS-SDK programmar's guide
        self.add_parameter(name='samples_per_record',
                           parameter_class=AlazarParameter,
                           label='Samples per Record',
                           unit=None,
                           value=96000,
                           vals=validators.Multiples(divisor=64,
                                                     min_value=256))

        # TODO(damazter) (M) figure out if this also has to be a multiple of
        # something,
        # I could not find this in the documentation but somehow I have the
        # feeling it still should be a multiple of something
        # NOTE by ramiro: At least in previous python implementations
        # (PycQED delft), this is an artifact for compatibility with
        # AWG sequencing, not particular to any ATS architecture.
        #                  ==> this is a construction imposed by the memory
        #                      strategy implemented on the python driver we
        #                      are writing, not limited by any actual ATS
        #                      feature.
        self.add_parameter(name='records_per_buffer',
                           parameter_class=AlazarParameter,
                           label='Records per Buffer',
                           unit=None,
                           value=1,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='buffers_per_acquisition',
                           parameter_class=AlazarParameter,
                           label='Buffers per Acquisition',
                           unit=None,
                           value=1,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='channel_selection',
                           parameter_class=AlazarParameter,
                           label='Channel Selection',
                           unit=None,
                           value='AB',
                           byte_to_value_dict={
                               1: 'A',
                               2: 'B',
                               3: 'AB'
                           })
        self.add_parameter(name='transfer_offset',
                           parameter_class=AlazarParameter,
                           label='Transer Offset',
                           unit='Samples',
                           value=0,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='external_startcapture',
                           parameter_class=AlazarParameter,
                           label='External Startcapture',
                           unit=None,
                           value='ENABLED',
                           byte_to_value_dict={
                               0x0: 'DISABLED',
                               0x1: 'ENABLED'
                           })
        self.add_parameter(name='enable_record_headers',
                           parameter_class=AlazarParameter,
                           label='Enable Record Headers',
                           unit=None,
                           value='DISABLED',
                           byte_to_value_dict={
                               0x0: 'DISABLED',
                               0x8: 'ENABLED'
                           })
        self.add_parameter(name='alloc_buffers',
                           parameter_class=AlazarParameter,
                           label='Alloc Buffers',
                           unit=None,
                           value='DISABLED',
                           byte_to_value_dict={
                               0x0: 'DISABLED',
                               0x20: 'ENABLED'
                           })
        self.add_parameter(name='fifo_only_streaming',
                           parameter_class=AlazarParameter,
                           label='Fifo Only Streaming',
                           unit=None,
                           value='DISABLED',
                           byte_to_value_dict={
                               0x0: 'DISABLED',
                               0x800: 'ENABLED'
                           })
        self.add_parameter(name='interleave_samples',
                           parameter_class=AlazarParameter,
                           label='Interleave Samples',
                           unit=None,
                           value='DISABLED',
                           byte_to_value_dict={
                               0x0: 'DISABLED',
                               0x1000: 'ENABLED'
                           })
        self.add_parameter(name='get_processed_data',
                           parameter_class=AlazarParameter,
                           label='Get Processed Data',
                           unit=None,
                           value='DISABLED',
                           byte_to_value_dict={
                               0x0: 'DISABLED',
                               0x2000: 'ENABLED'
                           })

        self.add_parameter(name='allocated_buffers',
                           parameter_class=AlazarParameter,
                           label='Allocated Buffers',
                           unit=None,
                           value=1,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='buffer_timeout',
                           parameter_class=AlazarParameter,
                           label='Buffer Timeout',
                           unit='ms',
                           value=1000,
                           vals=validators.Ints(min_value=0))

        model = self.get_idn()['model']
        if model != 'ATS9870':
            raise Exception("The Alazar board kind is not 'ATS9870',"
                            " found '" + str(model) + "' instead.")
Beispiel #13
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')))
    def __init__(self, instrument_name, **kwargs):
        super().__init__(instrument_name, **kwargs)
        self.pulse_sequence.allow_targeted_pulses = True
        self.pulse_sequence.allow_untargeted_pulses = False
        self.pulse_sequence.allow_pulse_overlap = False

        self._clk_freq = int(100e6)

        self.pulse_implementations = [
            TriggerPulseImplementation(pulse_requirements=[])
        ]

        self._data_channels = {
            f'trace_{k}': Channel(instrument_name=self.instrument_name(),
                                  name=f'trace_{k}',
                                  id=k,
                                  output=False,
                                  input=True)
            for k in range(8)
        }

        self._pxi_channels = {
            'pxi{}'.format(k): Channel(instrument_name=self.instrument_name(),
                                       name='pxi{}'.format(k),
                                       id=4000 + k,
                                       input_trigger=True,
                                       output=True,
                                       input=True)
            for k in range(8)
        }

        self._channels = {
            **self._data_channels,
            **self._pxi_channels,
        }

        self.add_parameter('blip_threshold',
                           parameter_class=ManualParameter,
                           vals=vals.Numbers(-3, 3),
                           unit='V',
                           docstring='The blip threshold in volts.')

        self.add_parameter(
            'full_scale_range',
            parameter_class=ManualParameter,
            vals=vals.Numbers(-3, 3),
            unit='V',
            docstring='The full scale range of the trace channel in volts.')

        self.add_parameter(
            'update_time',
            parameter_class=ManualParameter,
            vals=vals.Numbers(),
            unit='s',
            docstring=
            'The length of time in seconds after a blip required to perform the '
            'Bayesian update.')

        self.add_parameter(
            'timeout',
            parameter_class=ManualParameter,
            vals=vals.Numbers(),
            unit='s',
            docstring=
            'The duration since the Bayesian update starts from where you cancel the '
            'Bayesian update and continue with the experiment.')

        self.add_parameter(
            'trace_select',
            parameter_class=ManualParameter,
            vals=vals.Ints(0, 7),
            docstring='The channel you want to select from 0 to 7.')

        self.add_parameter(
            'pxi_channel',
            parameter_class=ManualParameter,
            vals=vals.Ints(4000, 4007),
            docstring='The PXI channel the trigger will be output on.')
Beispiel #15
0
    def __init__(self, parent: Instrument, name: str, channum: int) -> None:
        """
        Args:
            parent: The instrument to which the channel is attached
            name: The name of the channel
            channum: The number of the channel in question. Must match the
                actual number as used by the instrument (1..4)
        """

        if channum not in [1, 2, 3, 4]:
            raise ValueError('Invalid channel number! Must be 1, 2, 3, or 4.')

        self.channum = channum

        super().__init__(parent, name)

        self.add_parameter('state',
                           label=f'Channel {channum} state',
                           get_cmd=f'CHANnel{channum}:STATe?',
                           set_cmd=f'CHANnel{channum}:STATE {{}}',
                           vals=vals.Enum('ON', 'OFF'),
                           docstring='Switches the channel on or off')

        self.add_parameter('coupling',
                           label=f'Channel {channum} coupling',
                           get_cmd=f'CHANnel{channum}:COUPling?',
                           set_cmd=f'CHANnel{channum}:COUPling {{}}',
                           vals=vals.Enum('DC', 'DCLimit', 'AC'),
                           docstring=('Selects the connection of the channel'
                                      'signal. DC: 50 Ohm, DCLimit 1 MOhm, '
                                      'AC: Con. through DC capacitor'))

        self.add_parameter('ground',
                           label=f'Channel {channum} ground',
                           get_cmd=f'CHANnel{channum}:GND?',
                           set_cmd=f'CHANnel{channum}:GND {{}}',
                           vals=vals.Enum('ON', 'OFF'),
                           docstring=('Connects/disconnects the signal to/from'
                                      'the ground.'))

        # NB (WilliamHPNielsen): This parameter depends on other parameters and
        # should be dynamically updated accordingly. Cf. p 1178 of the manual
        self.add_parameter(
            'scale',
            label=f'Channel {channum} Y scale',
            unit='V/div',
            get_cmd=f'CHANnel{channum}:SCALe?',
            set_cmd=self._set_scale,
            get_parser=float,
        )

        self.add_parameter('range',
                           label=f'Channel {channum} Y range',
                           unit='V',
                           get_cmd=f'CHANnel{channum}:RANGe?',
                           set_cmd=self._set_range,
                           get_parser=float)

        # TODO (WilliamHPNielsen): would it be better to recast this in terms
        # of Volts?
        self.add_parameter('position',
                           label=f'Channel {channum} vert. pos.',
                           unit='div',
                           get_cmd=f'CHANnel{channum}:POSition?',
                           set_cmd=f'CHANnel{channum}:POSition {{}}',
                           get_parser=float,
                           vals=vals.Numbers(-5, 5),
                           docstring=('Positive values move the waveform up,'
                                      ' negative values move it down.'))

        self.add_parameter(
            'offset',
            label=f'Channel {channum} offset',
            unit='V',
            get_cmd=f'CHANnel{channum}:OFFSet?',
            set_cmd=f'CHANnel{channum}:OFFSet {{}}',
            get_parser=float,
        )

        self.add_parameter('invert',
                           label=f'Channel {channum} inverted',
                           get_cmd=f'CHANnel{channum}:INVert?',
                           set_cmd=f'CHANnel{channum}:INVert {{}}',
                           vals=vals.Enum('ON', 'OFF'))

        # TODO (WilliamHPNielsen): This parameter should be dynamically
        # validated since 800 MHz BW is only available for 50 Ohm coupling
        self.add_parameter('bandwidth',
                           label=f'Channel {channum} bandwidth',
                           get_cmd=f'CHANnel{channum}:BANDwidth?',
                           set_cmd=f'CHANnel{channum}:BANDwidth {{}}',
                           vals=vals.Enum('FULL', 'B800', 'B200', 'B20'))

        self.add_parameter('impedance',
                           label=f'Channel {channum} impedance',
                           unit='Ohm',
                           get_cmd=f'CHANnel{channum}:IMPedance?',
                           set_cmd=f'CHANnel{channum}:IMPedance {{}}',
                           vals=vals.Ints(1, 100000),
                           docstring=('Sets the impedance of the channel '
                                      'for power calculations and '
                                      'measurements.'))

        self.add_parameter('overload',
                           label=f'Channel {channum} overload',
                           get_cmd=f'CHANnel{channum}:OVERload?')

        self.add_parameter('arithmetics',
                           label=f'Channel {channum} arithmetics',
                           set_cmd=f'CHANnel{channum}:ARIThmetics {{}}',
                           get_cmd=f'CHANnel{channum}:ARIThmetics?',
                           val_mapping={
                               'AVERAGE': 'AVER',
                               'OFF': 'OFF',
                               'ENVELOPE': 'ENV'
                           })

        self.add_parameter('trace',
                           channum=self.channum,
                           parameter_class=ScopeTrace)

        self._trace_ready = False
Beispiel #16
0
    def __init__(self, name, **kw):
        super().__init__(name, **kw)

        self.add_parameter('channel',
                           initial_value=1,
                           vals=vals.Ints(),
                           parameter_class=ManualParameter)

        self.add_parameter(
            'kernel_list',
            initial_value=[],
            vals=vals.Lists(vals.Strings()),
            parameter_class=ConfigParameter,
            docstring='List of filenames of external kernels to be loaded')

        self.add_parameter('kernel_dir',
                           initial_value='kernels/',
                           vals=vals.Strings(),
                           parameter_class=ManualParameter,
                           docstring='Path for loading external kernels,' +
                           'such as room temperature correction kernels.')

        self.add_parameter('config_changed',
                           vals=vals.Bool(),
                           get_cmd=self._get_config_changed)
        self.add_parameter(
            'kernel',
            vals=vals.Arrays(),
            get_cmd=self._get_kernel,
            docstring=('Returns the predistortion kernel. \n' +
                       'Recalculates if the parameters changed,\n' +
                       'otherwise returns a precalculated kernel.\n' +
                       'Kernel is based on parameters in kernel object \n' +
                       'and files specified in the kernel list.'))

        self.add_parameter('skineffect_alpha',
                           unit='',
                           parameter_class=ConfigParameter,
                           initial_value=0,
                           vals=vals.Numbers())
        self.add_parameter('skineffect_length',
                           unit='s',
                           parameter_class=ConfigParameter,
                           initial_value=600e-9,
                           vals=vals.Numbers())

        self.add_parameter('decay_amp_1',
                           unit='',
                           initial_value=0,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())
        self.add_parameter('decay_tau_1',
                           unit='s',
                           initial_value=1e-9,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())
        self.add_parameter('decay_length_1',
                           unit='s',
                           initial_value=100e-9,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())
        self.add_parameter('decay_amp_2',
                           unit='',
                           initial_value=0,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())
        self.add_parameter('decay_tau_2',
                           unit='s',
                           initial_value=1e-9,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())
        self.add_parameter('decay_length_2',
                           unit='s',
                           initial_value=100e-9,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())

        self.add_parameter('bounce_amp_1',
                           unit='',
                           initial_value=0,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())
        self.add_parameter('bounce_tau_1',
                           unit='s',
                           initial_value=0,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())
        self.add_parameter('bounce_length_1',
                           unit='s',
                           initial_value=1e-9,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())

        self.add_parameter('bounce_amp_2',
                           unit='',
                           initial_value=0,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())
        self.add_parameter('bounce_tau_2',
                           unit='s',
                           initial_value=0,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())
        self.add_parameter('bounce_length_2',
                           unit='s',
                           initial_value=1e-9,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())

        self.add_parameter('poly_a',
                           unit='',
                           initial_value=0,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())
        self.add_parameter('poly_b',
                           unit='',
                           initial_value=0,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())
        self.add_parameter('poly_c',
                           unit='',
                           initial_value=1,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())
        self.add_parameter('poly_length',
                           unit='s',
                           initial_value=600e-9,
                           parameter_class=ConfigParameter,
                           vals=vals.Numbers())

        self.add_parameter('corrections_length',
                           unit='s',
                           parameter_class=ConfigParameter,
                           initial_value=10e-6,
                           vals=vals.Numbers())

        self.add_parameter('sampling_rate',
                           parameter_class=ManualParameter,
                           initial_value=1e9,
                           vals=vals.Numbers())
Beispiel #17
0
    def __init__(self,
                 name: str,
                 address: str,
                 model: Optional[str] = None,
                 timeout: float = 5.,
                 HD: bool = True,
                 terminator: str = '\n',
                 **kwargs: Any) -> None:
        """
        Args:
            name: name of the instrument
            address: VISA resource address
            model: The instrument model. For newer firmware versions,
                this can be auto-detected
            timeout: The VISA query timeout
            HD: Does the unit have the High Definition Option (allowing
                16 bit vertical resolution)
            terminator: Command termination character to strip from VISA
                commands.
        """
        super().__init__(name=name,
                         address=address,
                         timeout=timeout,
                         terminator=terminator,
                         **kwargs)

        # With firmware versions earlier than 3.65, it seems that the
        # model number can NOT be queried from the instrument
        # (at least fails with RTO1024, fw 2.52.1.1), so in that case
        # the user must provide the model manually.
        firmware_version = self.get_idn()['firmware']

        if LooseVersion(firmware_version) < LooseVersion('3'):
            log.warning('Old firmware version detected. This driver may '
                        'not be compatible. Please upgrade your firmware.')

        if LooseVersion(firmware_version) >= LooseVersion('3.65'):
            # strip just in case there is a newline character at the end
            self.model = self.ask('DIAGnostic:SERVice:WFAModel?').strip()
            if model is not None and model != self.model:
                warnings.warn("The model number provided by the user "
                              "does not match the instrument's response."
                              " I am going to assume that this oscilloscope "
                              f"is a model {self.model}")
        else:
            if model is None:
                raise ValueError('No model number provided. Please provide '
                                 'a model number (eg. "RTO1024").')
            else:
                self.model = model

        self.HD = HD

        # Now assign model-specific values
        self.num_chans = int(self.model[-1])
        self.num_meas = 8

        self._horisontal_divs = int(self.ask('TIMebase:DIVisions?'))

        self.add_parameter('display',
                           label='Display state',
                           set_cmd='SYSTem:DISPlay:UPDate {}',
                           val_mapping={
                               'remote': 0,
                               'view': 1
                           })

        # Triggering

        self.add_parameter('trigger_display',
                           label='Trigger display state',
                           set_cmd='DISPlay:TRIGger:LINes {}',
                           get_cmd='DISPlay:TRIGger:LINes?',
                           val_mapping={
                               'ON': 1,
                               'OFF': 0
                           })

        # TODO: (WilliamHPNielsen) There are more available trigger
        # settings than implemented here. See p. 1261 of the manual
        # here we just use trigger1, which is the A-trigger

        self.add_parameter('trigger_source',
                           label='Trigger source',
                           set_cmd='TRIGger1:SOURce {}',
                           get_cmd='TRIGger1:SOURce?',
                           val_mapping={
                               'CH1': 'CHAN1',
                               'CH2': 'CHAN2',
                               'CH3': 'CHAN3',
                               'CH4': 'CHAN4',
                               'EXT': 'EXT'
                           })

        self.add_parameter('trigger_mode',
                           label='Trigger mode',
                           set_cmd='TRIGger:MODE {}',
                           get_cmd='TRIGger1:SOURce?',
                           vals=vals.Enum('AUTO', 'NORMAL', 'FREERUN'),
                           docstring='Sets the trigger mode which determines'
                           ' the behaviour of the instrument if no'
                           ' trigger occurs.\n'
                           'Options: AUTO, NORMAL, FREERUN.',
                           unit='none')

        self.add_parameter('trigger_type',
                           label='Trigger type',
                           set_cmd='TRIGger1:TYPE {}',
                           get_cmd='TRIGger1:TYPE?',
                           val_mapping={
                               'EDGE': 'EDGE',
                               'GLITCH': 'GLIT',
                               'WIDTH': 'WIDT',
                               'RUNT': 'RUNT',
                               'WINDOW': 'WIND',
                               'TIMEOUT': 'TIM',
                               'INTERVAL': 'INT',
                               'SLEWRATE': 'SLEW',
                               'DATATOCLOCK': 'DAT',
                               'STATE': 'STAT',
                               'PATTERN': 'PATT',
                               'ANEDGE': 'ANED',
                               'SERPATTERN': 'SERP',
                               'NFC': 'NFC',
                               'TV': 'TV',
                               'CDR': 'CDR'
                           })
        # See manual p. 1262 for an explanation of trigger types

        self.add_parameter('trigger_level',
                           label='Trigger level',
                           set_cmd=self._set_trigger_level,
                           get_cmd=self._get_trigger_level)

        self.add_parameter('trigger_edge_slope',
                           label='Edge trigger slope',
                           set_cmd='TRIGger1:EDGE:SLOPe {}',
                           get_cmd='TRIGger1:EDGE:SLOPe?',
                           vals=vals.Enum('POS', 'NEG', 'EITH'))

        # Horizontal settings

        self.add_parameter('timebase_scale',
                           label='Timebase scale',
                           set_cmd=self._set_timebase_scale,
                           get_cmd='TIMebase:SCALe?',
                           unit='s/div',
                           get_parser=float,
                           vals=vals.Numbers(25e-12, 10000))

        self.add_parameter('timebase_range',
                           label='Timebase range',
                           set_cmd=self._set_timebase_range,
                           get_cmd='TIMebase:RANGe?',
                           unit='s',
                           get_parser=float,
                           vals=vals.Numbers(250e-12, 100e3))

        self.add_parameter('timebase_position',
                           label='Horizontal position',
                           set_cmd=self._set_timebase_position,
                           get_cmd='TIMEbase:HORizontal:POSition?',
                           get_parser=float,
                           unit='s',
                           vals=vals.Numbers(-100e24, 100e24))

        # Acquisition

        # I couldn't find a way to query the run mode, so we manually keep
        # track of it. It is very important when getting the trace to make
        # sense of completed_acquisitions.
        self.add_parameter('run_mode',
                           label='Run/acquisition mode of the scope',
                           get_cmd=None,
                           set_cmd=None)

        self.run_mode('RUN CONT')

        self.add_parameter('num_acquisitions',
                           label='Number of single acquisitions to perform',
                           get_cmd='ACQuire:COUNt?',
                           set_cmd='ACQuire:COUNt {}',
                           vals=vals.Ints(1, 16777215),
                           get_parser=int)

        self.add_parameter('completed_acquisitions',
                           label='Number of completed acquisitions',
                           get_cmd='ACQuire:CURRent?',
                           get_parser=int)

        self.add_parameter('sampling_rate',
                           label='Sample rate',
                           docstring='Number of averages for measuring '
                           'trace.',
                           unit='Sa/s',
                           get_cmd='ACQuire:POINts:ARATe' + '?',
                           get_parser=int)

        self.add_parameter('acquisition_sample_rate',
                           label='Acquisition sample rate',
                           unit='Sa/s',
                           docstring='recorded waveform samples per second',
                           get_cmd='ACQuire:SRATe' + '?',
                           set_cmd='ACQuire:SRATe ' + ' {:.2f}',
                           vals=vals.Numbers(2, 20e12),
                           get_parser=float)

        # Data

        self.add_parameter('dataformat',
                           label='Export data format',
                           set_cmd='FORMat:DATA {}',
                           get_cmd='FORMat:DATA?',
                           vals=vals.Enum('ASC,0', 'REAL,32', 'INT,8',
                                          'INT,16'))

        # High definition mode (might not be available on all instruments)

        if HD:
            self.add_parameter('high_definition_state',
                               label='High definition (16 bit) state',
                               set_cmd=self._set_hd_mode,
                               get_cmd='HDEFinition:STAte?',
                               val_mapping=create_on_off_val_mapping(
                                   on_val=1, off_val=0),
                               docstring='Sets the filter bandwidth for the'
                               ' high definition mode.\n'
                               'ON: high definition mode, up to 16'
                               ' bit digital resolution\n'
                               'Options: ON, OFF\n\n'
                               'Warning/Bug: By opening the HD '
                               'acquisition menu on the scope, '
                               'this value will be set to "ON".')

            self.add_parameter('high_definition_bandwidth',
                               label='High definition mode bandwidth',
                               set_cmd='HDEFinition:BWIDth {}',
                               get_cmd='HDEFinition:BWIDth?',
                               unit='Hz',
                               get_parser=float,
                               vals=vals.Numbers(1e4, 1e9))

        self.add_parameter('error_count',
                           label='Number of errors in the error stack',
                           get_cmd='SYSTem:ERRor:COUNt?',
                           unit='#',
                           get_parser=int)

        self.add_parameter('error_next',
                           label='Next error from the error stack',
                           get_cmd='SYSTem:ERRor:NEXT?',
                           get_parser=str)

        # Add the channels to the instrument
        for ch in range(1, self.num_chans + 1):
            chan = ScopeChannel(self, f'channel{ch}', ch)
            self.add_submodule(f'ch{ch}', chan)

        for measId in range(1, self.num_meas + 1):
            measCh = ScopeMeasurement(self, f'measurement{measId}', measId)
            self.add_submodule(f'meas{measId}', measCh)

        self.add_function('stop', call_cmd='STOP')
        self.add_function('reset', call_cmd='*RST')
        self.add_parameter('opc', get_cmd='*OPC?')
        self.add_parameter('stop_opc', get_cmd='STOP;*OPC?')
        self.add_parameter('status_operation',
                           get_cmd='STATus:OPERation:CONDition?',
                           get_parser=int)
        self.add_function('run_continues', call_cmd='RUNContinous')
        # starts the shutdown of the system
        self.add_function('system_shutdown', call_cmd='SYSTem:EXIT')

        self.connect_message()
Beispiel #18
0
    def __init__(self,
                 name: str,
                 address: str,
                 update_currents: bool = False,
                 **kwargs: Any):
        """
        Instantiates the instrument.

        Args:
            name: The instrument name used by qcodes
            address: The VISA name of the resource
            update_currents: Whether to query all channels for their
                current sensor value on startup, which takes about 0.5 sec
                per channel. Default: False.

        Returns:
            QDac object
        """

        super().__init__(name, address, **kwargs)
        handle = self.visa_handle
        self._get_status_performed = False

        assert isinstance(handle, SerialInstrument)
        # Communication setup + firmware check
        handle.baud_rate = 480600
        handle.parity = visa.constants.Parity(0)
        handle.data_bits = 8
        self.set_terminator('\n')
        handle.write_termination = '\n'
        self._write_response = ''
        firmware_version = self._get_firmware_version()
        if firmware_version < 1.07:
            LOG.warning(f"Firmware version: {firmware_version}")
            raise RuntimeError('''
                No QDevil QDAC detected or the firmware version is obsolete.
                This driver only supports version 1.07 or newer. Please
                contact [email protected] for a firmware update.
                ''')

        # Initialse basic information and internal book keeping
        self.num_chans = self._get_number_of_channels()
        num_boards = int(self.num_chans/8)
        self._output_n_lines = self.num_chans + 2
        self._chan_range = range(1, 1 + self.num_chans)
        self.channel_validator = vals.Ints(1, self.num_chans)
        self._reset_bookkeeping()

        # Add channels (and channel parameters)
        channels = ChannelList(self, "Channels", QDacChannel,
                               snapshotable=False,
                               multichan_paramclass=QDacMultiChannelParameter)

        for i in self._chan_range:
            channel = QDacChannel(self, f'chan{i:02}', i)
            channels.append(channel)
            self.add_submodule(f"ch{i:02}", channel)
        self.add_submodule("channels", channels.to_channel_tuple())

        # Updatechannel  sync port validator according to number of boards
        self._num_syns = max(num_boards-1, 1)
        for chan in self._chan_range:
            self.channels[chan-1].sync.vals = vals.Ints(0, self._num_syns)

        # Add non-channel parameters
        for board in range(num_boards):
            for sensor in range(3):
                label = f'Board {board}, Temperature {sensor}'
                self.add_parameter(name=f'temp{board}_{sensor}',
                                   label=label,
                                   unit='C',
                                   get_cmd=f'tem {board} {sensor}',
                                   get_parser=self._num_verbose)

        self.add_parameter(name='cal',
                           set_cmd='cal {}',
                           vals=vals.Ints(0, self.num_chans))

        self.add_parameter(name='mode_force',
                           label='Mode force',
                           get_cmd=None, set_cmd=None,
                           vals=vals.Bool(),
                           initial_value=False)

        # Due to a firmware bug in 1.07 voltage ranges are always reported
        # vebosely. So for future compatibility we set verbose True
        self.write('ver 1')
        self._update_voltage_ranges()
        # The driver require verbose mode off except for the above command
        self.write('ver 0')
        self._verbose = False  # Just so that the code can check the state
        self.connect_message()
        LOG.info('[*] Querying all channels for voltages and currents...')
        self._update_cache(update_currents=update_currents)
        self._update_currents = update_currents
        self._load_state()
        LOG.info('[+] Done')
Beispiel #19
0
    def __init__(
        self,
        parent: "ZNB",
        name: str,
        channel: int,
        vna_parameter: Optional[str] = None,
        existing_trace_to_bind_to: Optional[str] = None,
    ) -> None:
        """
        Args:
            parent: Instrument that this channel is bound to.
            name: Name to use for this channel.
            channel: channel on the VNA to use
            vna_parameter: Name of parameter on the vna that this should
                measure such as S12. If left empty this will fall back to
                `name`.
            existing_trace_to_bind_to: Name of an existing trace on the VNA.
                If supplied try to bind to an existing trace with this name
                rather than creating a new trace.

        """
        n = channel
        self._instrument_channel = channel
        # Additional wait when adjusting instrument timeout to sweep time.
        self._additional_wait = 1

        if vna_parameter is None:
            vna_parameter = name
        self._vna_parameter = vna_parameter
        super().__init__(parent, name)

        if existing_trace_to_bind_to is None:
            self._tracename = f"Trc{channel}"
        else:
            traces = self._parent.ask("CONFigure:TRACe:CATalog?")
            if existing_trace_to_bind_to not in traces:
                raise RuntimeError(f"Trying to bind to"
                                   f" {existing_trace_to_bind_to} "
                                   f"which is not in {traces}")
            self._tracename = existing_trace_to_bind_to

        # map hardware channel to measurement
        # hardware channels are mapped one to one to QCoDeS channels
        # we are not using sub traces within channels.
        if existing_trace_to_bind_to is None:
            self.write(f"CALC{self._instrument_channel}:PAR:SDEF"
                       f" '{self._tracename}', '{self._vna_parameter}'")

        # Source power is dependent on model, but not well documented.
        # Here we assume -60 dBm for ZNB20, the others are set,
        # due to lack of knowledge, to -80 dBm as of before the edit.
        full_modelname = self._parent.get_idn()["model"]
        if full_modelname is not None:
            model = full_modelname.split("-")[0]
        else:
            raise RuntimeError("Could not determine ZNB model")
        self._model_min_source_power = {
            "ZNB4": -80,
            "ZNB8": -80,
            "ZNB20": -60,
            "ZNB40": -60,
        }
        if model not in self._model_min_source_power.keys():
            raise RuntimeError(f"Unsupported ZNB model: {model}")
        self._min_source_power: float
        self._min_source_power = self._model_min_source_power[model]

        self.add_parameter(
            name="vna_parameter",
            label="VNA parameter",
            get_cmd=f"CALC{self._instrument_channel}:PAR:MEAS? "
            f"'{self._tracename}'",
            get_parser=self._strip,
        )
        self.add_parameter(
            name="power",
            label="Power",
            unit="dBm",
            get_cmd=f"SOUR{n}:POW?",
            set_cmd=f"SOUR{n}:POW {{:.4f}}",
            get_parser=float,
            vals=vals.Numbers(self._min_source_power, 25),
        )
        self.add_parameter(
            name="bandwidth",
            label="Bandwidth",
            unit="Hz",
            get_cmd=f"SENS{n}:BAND?",
            set_cmd=self._set_bandwidth,
            get_parser=int,
            vals=vals.Enum(*np.append(
                10**6, np.kron([1, 1.5, 2, 3, 5, 7], 10**np.arange(6)))),
            docstring="Measurement bandwidth of the IF filter. "
            "The inverse of this sets the integration "
            "time per point. "
            "There is an 'increased bandwidth option' "
            "(p. 4 of manual) that does not get taken "
            "into account here.",
        )
        self.add_parameter(
            name="avg",
            label="Averages",
            unit="",
            get_cmd=f"SENS{n}:AVER:COUN?",
            set_cmd=f"SENS{n}:AVER:COUN {{:.4f}}",
            get_parser=int,
            vals=vals.Ints(1, 5000),
        )
        self.add_parameter(
            name="start",
            get_cmd=f"SENS{n}:FREQ:START?",
            set_cmd=self._set_start,
            get_parser=float,
            vals=vals.Numbers(self._parent._min_freq,
                              self._parent._max_freq - 10),
        )
        self.add_parameter(
            name="stop",
            get_cmd=f"SENS{n}:FREQ:STOP?",
            set_cmd=self._set_stop,
            get_parser=float,
            vals=vals.Numbers(self._parent._min_freq + 1,
                              self._parent._max_freq),
        )
        self.add_parameter(
            name="center",
            get_cmd=f"SENS{n}:FREQ:CENT?",
            set_cmd=self._set_center,
            get_parser=float,
            vals=vals.Numbers(self._parent._min_freq + 0.5,
                              self._parent._max_freq - 10),
        )
        self.add_parameter(
            name="span",
            get_cmd=f"SENS{n}:FREQ:SPAN?",
            set_cmd=self._set_span,
            get_parser=float,
            vals=vals.Numbers(1,
                              self._parent._max_freq - self._parent._min_freq),
        )
        self.add_parameter(
            name="npts",
            get_cmd=f"SENS{n}:SWE:POIN?",
            set_cmd=self._set_npts,
            get_parser=int,
        )
        self.add_parameter(
            name="status",
            get_cmd=f"CONF:CHAN{n}:MEAS?",
            set_cmd=f"CONF:CHAN{n}:MEAS {{}}",
            get_parser=int,
        )
        self.add_parameter(
            name="format",
            get_cmd=partial(self._get_format, tracename=self._tracename),
            set_cmd=self._set_format,
            val_mapping={
                "dB": "MLOG\n",
                "Linear Magnitude": "MLIN\n",
                "Phase": "PHAS\n",
                "Unwr Phase": "UPH\n",
                "Polar": "POL\n",
                "Smith": "SMIT\n",
                "Inverse Smith": "ISM\n",
                "SWR": "SWR\n",
                "Real": "REAL\n",
                "Imaginary": "IMAG\n",
                "Delay": "GDEL\n",
                "Complex": "COMP\n",
            },
        )

        self.add_parameter(
            name="trace_mag_phase",
            start=self.start(),
            stop=self.stop(),
            npts=self.npts(),
            channel=n,
            parameter_class=FrequencySweepMagPhase,
        )
        self.add_parameter(
            name="trace",
            start=self.start(),
            stop=self.stop(),
            npts=self.npts(),
            channel=n,
            parameter_class=FrequencySweep,
        )
        self.add_parameter(
            name="electrical_delay",
            label="Electrical delay",
            get_cmd=f"SENS{n}:CORR:EDEL2:TIME?",
            set_cmd=f"SENS{n}:CORR:EDEL2:TIME {{}}",
            get_parser=float,
            unit="s",
        )
        self.add_parameter(
            name="sweep_time",
            label="Sweep time",
            get_cmd=f"SENS{n}:SWE:TIME?",
            get_parser=float,
            unit="s",
        )
        self.add_parameter(
            name="sweep_type",
            get_cmd=f"SENS{n}:SWE:TYPE?",
            set_cmd=self._set_sweep_type,
            val_mapping={
                "Linear": "LIN\n",
                "Logarithmic": "LOG\n",
                "Power": "POW\n",
                "CW_Time": "CW\n",
                "CW_Point": "POIN\n",
                "Segmented": "SEGM\n",
            },
            docstring="The sweep_type parameter is used to set "
            "the type of measurement sweeps. It "
            "allows switching the default linear "
            "VNA sweep type to other types. Note that "
            "at the moment only the linear and "
            "CW_Point modes have supporting "
            "measurement parameters.",
        )
        self.add_parameter(
            name="cw_frequency",
            get_cmd=f"SENS{n}:FREQ:CW?",
            set_cmd=self._set_cw_frequency,
            get_parser=float,
            vals=vals.Numbers(self._parent._min_freq + 0.5,
                              self._parent._max_freq - 10),
            docstring="Parameter for setting frequency and "
            "querying for it when VNA sweep type is "
            "set to CW_Point mode.",
        )

        self.add_parameter(
            "cw_check_sweep_first",
            parameter_class=ManualParameter,
            initial_value=True,
            vals=vals.Bool(),
            docstring="Parameter that enables a few commands "
            "which are called before each get in "
            "continuous wave mode checking whether "
            "the vna is setup correctly. Is recommended "
            "to be turned, but can be turned off if "
            "one wants to minimize overhead in fast "
            "measurements. ",
        )

        self.add_parameter(
            name="trace_fixed_frequency",
            npts=self.npts(),
            bandwidth=self.bandwidth(),
            parameter_class=FixedFrequencyTraceIQ,
        )
        self.add_parameter(name="point_fixed_frequency",
                           parameter_class=FixedFrequencyPointIQ)
        self.add_parameter(
            name="point_fixed_frequency_mag_phase",
            parameter_class=FixedFrequencyPointMagPhase,
        )
        self.add_parameter(
            name="averaging_enabled",
            initial_value=False,
            get_cmd=None,
            set_cmd=self._enable_averaging,
            vals=vals.Bool(),
            val_mapping=create_on_off_val_mapping(on_val="ON", off_val="OFF"),
        )
        self.add_parameter(
            name="auto_sweep_time_enabled",
            initial_value=False,
            get_cmd=None,
            set_cmd=self._enable_auto_sweep_time,
            vals=vals.Bool(),
            val_mapping=create_on_off_val_mapping(on_val="ON", off_val="OFF"),
            docstring="When enabled, the (minimum) sweep time is "
            "calculated internally using the other channel settings "
            "and zero delay",
        )

        self.add_function("set_electrical_delay_auto",
                          call_cmd=f"SENS{n}:CORR:EDEL:AUTO ONCE")
        self.add_function(
            "autoscale",
            call_cmd=f"DISPlay:TRACe1:Y:SCALe:AUTO ONCE, {self._tracename}",
        )
Beispiel #20
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
                        )
Beispiel #21
0
    def __init__(self,
                 name,
                 address,
                 num_chans=48,
                 update_currents=True,
                 **kwargs):
        """
        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, **kwargs)
        self._output_n_lines = 50
        handle = self.visa_handle
        self._get_status_performed = False
        # 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 = ''

        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)

        channels = ChannelList(self, "Channels", QDacChannel,
                               snapshotable=False,
                               multichan_paramclass=QDacMultiChannelParameter)

        for i in self.chan_range:
            channel = QDacChannel(self, f'chan{i:02}', i)
            channels.append(channel)
            # Should raise valueerror if name is invalid (silently fails now)
            self.add_submodule(f'ch{i:02}', channel)
        channels.lock()
        self.add_submodule('channels', channels)

        for board in range(6):
            for sensor in range(3):
                label = f'Board {board}, Temperature {sensor}'
                self.add_parameter(name=f'temp{board}_{sensor}',
                                   label=label,
                                   unit='C',
                                   get_cmd=f'tem {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(f'wav {chan} 0 1 0')

        self.verbose.set(False)
        self.connect_message()
        log.info('[*] Querying all channels for voltages and currents...')
        self._update_cache(readcurrents=update_currents)
        self._update_currents = update_currents
        log.info('[+] Done')
Beispiel #22
0
    def __init__(self,
                 parent: 'ZNB',
                 name: str,
                 channel: int,
                 vna_parameter: Optional[str] = None,
                 existing_trace_to_bind_to: Optional[str] = None) -> None:
        """
        Args:
            parent: Instrument that this channel is bound to.
            name: Name to use for this channel.
            channel: channel on the VNA to use
            vna_parameter: Name of parameter on the vna that this should
                measure such as S12. If left empty this will fall back to
                `name`.
            existing_trace_to_bind_to: Name of an existing trace on the VNA.
                If supplied try to bind to an existing trace with this name
                rather than creating a new trace.

        """
        n = channel
        self._instrument_channel = channel
        # Additional wait when adjusting instrument timeout to sweep time.
        self._additional_wait = 1

        if vna_parameter is None:
            vna_parameter = name
        self._vna_parameter = vna_parameter
        super().__init__(parent, name)

        if existing_trace_to_bind_to is None:
            self._tracename = f"Trc{channel}"
        else:
            traces = self._parent.ask("CONFigure:TRACe:CATalog?")
            if existing_trace_to_bind_to not in traces:
                raise RuntimeError(f"Trying to bind to"
                                   f" {existing_trace_to_bind_to} "
                                   f"which is not in {traces}")
            self._tracename = existing_trace_to_bind_to

        # map hardware channel to measurement
        # hardware channels are mapped one to one to QCoDeS channels
        # we are not using sub traces within channels.
        if existing_trace_to_bind_to is None:
            self.write(f"CALC{self._instrument_channel}:PAR:SDEF"
                       f" '{self._tracename}', '{self._vna_parameter}'")

        # Source power is dependent on model, but not well documented.
        # Here we assume -60 dBm for ZNB20, the others are set,
        # due to lack of knowledge, to -80 dBm as of before the edit.
        full_modelname = self._parent.get_idn()['model']
        if full_modelname is not None:
            model = full_modelname.split('-')[0]
        else:
            raise RuntimeError("Could not determine ZNB model")
        mSourcePower = {'ZNB4': -80, 'ZNB8': -80, 'ZNB20': -60, 'ZNB40': -60}
        if model not in mSourcePower.keys():
            raise RuntimeError(f"Unsupported ZNB model: {model}")
        self._min_source_power: float
        self._min_source_power = mSourcePower[model]

        self.add_parameter(name='vna_parameter',
                           label='VNA parameter',
                           get_cmd=f"CALC{self._instrument_channel}:"
                           f"PAR:MEAS? '{self._tracename}'",
                           get_parser=self._strip)
        self.add_parameter(name='power',
                           label='Power',
                           unit='dBm',
                           get_cmd=f'SOUR{n}:POW?',
                           set_cmd=f'SOUR{n}:POW {{:.4f}}',
                           get_parser=float,
                           vals=vals.Numbers(self._min_source_power, 25))
        # there is an 'increased bandwidth option' (p. 4 of manual) that does
        # not get taken into account here
        self.add_parameter(
            name='bandwidth',
            label='Bandwidth',
            unit='Hz',
            get_cmd=f'SENS{n}:BAND?',
            set_cmd=f'SENS{n}:BAND {{:.4f}}',
            get_parser=int,
            vals=vals.Enum(*np.append(
                10**6, np.kron([1, 1.5, 2, 3, 5, 7], 10**np.arange(6)))))
        self.add_parameter(name='avg',
                           label='Averages',
                           unit='',
                           get_cmd=f'SENS{n}:AVER:COUN?',
                           set_cmd=f'SENS{n}:AVER:COUN {{:.4f}}',
                           get_parser=int,
                           vals=vals.Ints(1, 5000))
        self.add_parameter(name='start',
                           get_cmd=f'SENS{n}:FREQ:START?',
                           set_cmd=self._set_start,
                           get_parser=float,
                           vals=vals.Numbers(self._parent._min_freq,
                                             self._parent._max_freq - 10))
        self.add_parameter(name='stop',
                           get_cmd=f'SENS{n}:FREQ:STOP?',
                           set_cmd=self._set_stop,
                           get_parser=float,
                           vals=vals.Numbers(self._parent._min_freq + 1,
                                             self._parent._max_freq))
        self.add_parameter(name='center',
                           get_cmd=f'SENS{n}:FREQ:CENT?',
                           set_cmd=self._set_center,
                           get_parser=float,
                           vals=vals.Numbers(self._parent._min_freq + 0.5,
                                             self._parent._max_freq - 10))
        self.add_parameter(
            name='span',
            get_cmd=f'SENS{n}:FREQ:SPAN?',
            set_cmd=self._set_span,
            get_parser=float,
            vals=vals.Numbers(1,
                              self._parent._max_freq - self._parent._min_freq))
        self.add_parameter(name='npts',
                           get_cmd=f'SENS{n}:SWE:POIN?',
                           set_cmd=self._set_npts,
                           get_parser=int)
        self.add_parameter(name='status',
                           get_cmd=f'CONF:CHAN{n}:MEAS?',
                           set_cmd=f'CONF:CHAN{n}:MEAS {{}}',
                           get_parser=int)
        self.add_parameter(name='format',
                           get_cmd=partial(self._get_format,
                                           tracename=self._tracename),
                           set_cmd=self._set_format,
                           val_mapping={
                               'dB': 'MLOG\n',
                               'Linear Magnitude': 'MLIN\n',
                               'Phase': 'PHAS\n',
                               'Unwr Phase': 'UPH\n',
                               'Polar': 'POL\n',
                               'Smith': 'SMIT\n',
                               'Inverse Smith': 'ISM\n',
                               'SWR': 'SWR\n',
                               'Real': 'REAL\n',
                               'Imaginary': 'IMAG\n',
                               'Delay': "GDEL\n",
                               'Complex': "COMP\n"
                           })

        self.add_parameter(name='trace_mag_phase',
                           start=self.start(),
                           stop=self.stop(),
                           npts=self.npts(),
                           channel=n,
                           parameter_class=FrequencySweepMagPhase)
        self.add_parameter(name='trace',
                           start=self.start(),
                           stop=self.stop(),
                           npts=self.npts(),
                           channel=n,
                           parameter_class=FrequencySweep)
        self.add_parameter(name='electrical_delay',
                           label='Electrical delay',
                           get_cmd=f'SENS{n}:CORR:EDEL2:TIME?',
                           set_cmd=f'SENS{n}:CORR:EDEL2:TIME {{}}',
                           get_parser=float,
                           unit='s')
        self.add_parameter(name='sweep_time',
                           label='Sweep time',
                           get_cmd=f'SENS{n}:SWE:TIME?',
                           get_parser=float,
                           unit='s')
        self.add_function('set_electrical_delay_auto',
                          call_cmd=f'SENS{n}:CORR:EDEL:AUTO ONCE')

        self.add_function('autoscale',
                          call_cmd='DISPlay:TRACe1:Y:SCALe:AUTO ONCE, '
                          f"{self._tracename}")
    def __init__(self, name, FPGA, **kwargs):
        super().__init__(name, **kwargs)

        self._clk_freq = int(100e6)
        self.FPGA = FPGA
        self.port = 0

        self.write_port_signals = {
            "reset": {
                "address": 0,
                'width': 1,
                'type': bool
            },
            "enable": {
                "address": 1,
                'width': 1,
                'type': bool
            },
            "blip_threshold": {
                "address": 2,
                'width': 1,
                'type': np.int16
            },
            "blip_t_wait": {
                "address": 3,
                'width': 1,
                'type': np.uint32
            },
            "blip_timeout": {
                "address": 4,
                'width': 1,
                'type': np.uint32
            },
            "trace_sel": {
                "address": 5,
                'width': 1,
                'type': np.uint8
            },
            "pxi_sel": {
                "address": 6,
                'width': 1,
                'type': np.uint8
            },
            "timer_threshold": {
                "address": 7,
                'width': 2,
                'type': list
            },
            "trigger_delay": {
                "address": 9,
                'width': 1,
                'type': np.uint32
            }
        }

        self.read_port_signals = {
            "update_counter": {
                "address": 0,
                'width': 1,
                'type': np.uint32
            },
            "timeout_counter": {
                "address": 1,
                'width': 1,
                'type': np.uint32
            },
            "trigger_counter": {
                "address": 2,
                'width': 1,
                'type': np.uint32
            },
            "timer_counter": {
                "address": 3,
                'width': 2,
                'type': np.uint64
            },
            "trace_out": {
                "address": 5,
                'width': 1,
                'type': np.int16
            },
            "bayesian_state": {
                "address": 6,
                'width': 1,
                'type': np.int16
            },
        }

        self.add_parameter(
            'blip_threshold',
            set_cmd=self._set_blip_threshold,
            vals=vals.Ints(-0x8000, 0x7FFF),
            docstring='The blip threshold in the range of [-0x8000, 0x7FFF].')

        self.add_parameter('blip_t_wait',
                           set_cmd=self._set_blip_t_wait,
                           vals=vals.Ints(0, 0xFFFFFFFF),
                           docstring='The blip timeout in samples.')
        self.add_parameter('blip_timeout',
                           set_cmd=self._set_blip_timeout,
                           vals=vals.Ints(0, 0xFFFFFFFF),
                           docstring='The blip timeout in samples.')
        self.add_parameter(
            'trace_select',
            set_cmd=self._set_trace_select,
            vals=vals.Ints(0, 7),
            docstring='The channel you want to select from 0 to 7.')

        self.add_parameter(
            'pxi_select',
            set_cmd=self._set_pxi_select,
            vals=vals.Ints(0, 7),
            docstring=
            'The PXI channel the trigger will be output on, from 0 to 7.')

        self.add_parameter(
            'timer_duration',
            set_cmd=self._set_timer_duration,
            vals=vals.Ints(0, int(2**48 - 1)),
            docstring=
            "The post-update timer duration to match pulse sequence duration.")
Beispiel #24
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()
Beispiel #25
0
    def __init__(self,
                 name: str,
                 dll_path: Optional[str] = None,
                 **kwargs: Any):
        """
        Args:
            name: Name of the instrument.
            dll_path: Path to ``sa_api.dll`` Defaults to the default dll within
                Spike installation
            **kwargs:
        """
        super().__init__(name, **kwargs)
        self._parameters_synced = False
        self._trace_updated = False
        log.info('Initializing instrument SignalHound USB 124B')
        self.dll = ct.CDLL(dll_path or self.dll_path)

        self._set_ctypes_argtypes()

        self.hf = Constants
        self.add_parameter('frequency',
                           label='Frequency',
                           unit='Hz',
                           initial_value=5e9,
                           vals=vals.Numbers(),
                           parameter_class=SweepTraceParameter,
                           docstring='Center frequency for sweep.'
                           'This is the set center, the actual '
                           'center may be subject to round off '
                           'compared to this value')
        self.add_parameter('span',
                           label='Span',
                           unit='Hz',
                           initial_value=.25e6,
                           vals=vals.Numbers(),
                           parameter_class=SweepTraceParameter,
                           docstring='Width of frequency span'
                           'This is the set span, the actual '
                           'span may be subject to round off '
                           'compared to this value')
        self.add_parameter('npts',
                           label='Number of Points',
                           get_cmd=self._get_npts,
                           set_cmd=False,
                           docstring='Number of points in frequency sweep.')
        self.add_parameter('avg',
                           label='Averages',
                           initial_value=1,
                           get_cmd=None,
                           set_cmd=None,
                           vals=vals.Ints(),
                           docstring='Number of averages to perform. '
                           'Averages are performed in software by '
                           'acquiring multiple sweeps')
        self.add_parameter('ref_lvl',
                           label='Reference power',
                           unit='dBm',
                           initial_value=0,
                           vals=vals.Numbers(max_value=20),
                           parameter_class=TraceParameter,
                           docstring="Setting reference level will "
                           "automatically select gain and attenuation"
                           "optimal for measuring at and below "
                           "this level")
        self.add_parameter(
            'external_reference',
            initial_value=False,
            vals=vals.Bool(),
            parameter_class=ExternalRefParameter,
            docstring='Use an external 10 MHz reference source. '
            'Note that Signal Hound does not support '
            'disabling external ref. To disable close '
            'the connection and restart.')
        self.add_parameter('device_type',
                           set_cmd=False,
                           get_cmd=self._get_device_type)
        self.add_parameter('device_mode',
                           get_cmd=lambda: 'sweeping',
                           set_cmd=False,
                           docstring='The driver currently only  '
                           'supports sweeping mode. '
                           'It is therefor not possible'
                           'to set this parameter to anything else')
        self.add_parameter('acquisition_mode',
                           get_cmd=lambda: 'average',
                           set_cmd=False,
                           docstring="The driver only supports averaging "
                           "mode it is therefor not possible to set"
                           "this parameter to anything else")
        self.add_parameter('rbw',
                           label='Resolution Bandwidth',
                           unit='Hz',
                           initial_value=1e3,
                           vals=vals.Numbers(0.1, 250e3),
                           parameter_class=TraceParameter,
                           docstring='Resolution Bandwidth (RBW) is'
                           'the bandwidth of '
                           'spectral energy represented in each '
                           'frequency bin')
        self.add_parameter('vbw',
                           label='Video Bandwidth',
                           unit='Hz',
                           initial_value=1e3,
                           vals=vals.Numbers(),
                           parameter_class=TraceParameter,
                           docstring='The video bandwidth (VBW) is applied '
                           'after the signal has been converted to '
                           'frequency domain as power, voltage, '
                           'or log units. It is implemented as a '
                           'simple rectangular window, averaging the '
                           'amplitude readings for each frequency '
                           'bin over several overlapping FFTs. '
                           'For best performance use RBW as the VBW.')

        self.add_parameter('reject_image',
                           label='Reject image',
                           unit='',
                           initial_value=True,
                           parameter_class=TraceParameter,
                           get_cmd=None,
                           docstring="Apply software filter to remove "
                           "undersampling mirroring",
                           vals=vals.Bool())
        self.add_parameter('sleep_time',
                           label='Sleep time',
                           unit='s',
                           initial_value=0.1,
                           get_cmd=None,
                           set_cmd=None,
                           docstring="Time to sleep before and after "
                           "getting data from the instrument",
                           vals=vals.Numbers(0))
        # We don't know the correct values of
        # the sweep parameters yet so we supply
        # some defaults. The correct will be set when we call configure below
        self.add_parameter(name='trace',
                           sweep_len=1,
                           start_freq=1,
                           stepsize=1,
                           parameter_class=FrequencySweep)
        self.add_parameter('power',
                           label='Power',
                           unit='dBm',
                           get_cmd=self._get_power_at_freq,
                           set_cmd=False,
                           docstring="The maximum power in a window of 250 kHz"
                           "around the specified  frequency with "
                           "Resolution bandwidth set to 1 kHz."
                           "The integration window is specified by "
                           "the VideoBandWidth (set by vbw)")
        # scale is defined after the trace and power parameter so that
        # it can change the units of those in it's set method when the
        # scale changes
        self.add_parameter('scale',
                           initial_value='log-scale',
                           vals=vals.Enum('log-scale', 'lin-scale',
                                          'log-full-scale', 'lin-full-scale'),
                           parameter_class=ScaleParameter)

        self.add_parameter('frequency_axis',
                           label='Frequency',
                           unit='Hz',
                           get_cmd=self._get_freq_axis,
                           set_cmd=False,
                           vals=vals.Arrays(shape=(self.npts, )),
                           snapshot_value=False)
        self.add_parameter('freq_sweep',
                           label='Power',
                           unit='depends on mode',
                           get_cmd=self._get_sweep_data,
                           set_cmd=False,
                           parameter_class=ParameterWithSetpoints,
                           vals=vals.Arrays(shape=(self.npts, )),
                           setpoints=(self.frequency_axis, ),
                           snapshot_value=False)

        self.openDevice()
        self.configure()

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

        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'))

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

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

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

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

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

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

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

        #####################################
        # 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()
Beispiel #27
0
    def __init__(self, parent: 'KeysightB1500', name: Optional[str], slot_nr,
                 **kwargs):
        super().__init__(parent, name, slot_nr, **kwargs)

        self.channels = (ChNr(slot_nr),)
        self.setup_fnc_already_run = False
        self._ranging_mode: Union[constants.RangingMode, int] = \
            constants.RangingMode.AUTO
        self._measurement_range_for_non_auto: Optional[int] = None

        self.add_parameter(name="voltage_dc",
                           unit="V",
                           set_cmd=self._set_voltage_dc,
                           get_cmd=self._get_voltage_dc
                           )

        self.add_parameter(name="voltage_ac",
                           unit="V",
                           set_cmd=self._set_voltage_ac,
                           get_cmd=self._get_voltage_ac
                           )

        self.add_parameter(name="frequency",
                           unit="Hz",
                           set_cmd=self._set_frequency,
                           get_cmd=self._get_frequency
                           )

        self.add_parameter(name="capacitance",
                           get_cmd=self._get_capacitance,
                           snapshot_value=False)

        self.add_submodule('correction', Correction(self, 'correction'))

        self.add_parameter(name="phase_compensation_mode",
                           set_cmd=self._set_phase_compensation_mode,
                           get_cmd=None,
                           set_parser=constants.ADJ.Mode,
                           docstring=textwrap.dedent("""
            This parameter selects the MFCMU phase compensation mode. This
            command initializes the MFCMU. The available modes are captured 
            in :class:`constants.ADJ.Mode`:
 
                - 0: Auto mode. Initial setting.
                - 1: Manual mode.
                - 2: Load adaptive mode.
    
            For mode=0, the KeysightB1500 sets the compensation data 
            automatically. For mode=1, execute the 
            :meth:`phase_compensation` method ( the ``ADJ?`` command) to  
            perform the phase compensation and set the compensation data. 
            For mode=2, the KeysightB1500 performs the phase compensation 
            before every measurement. It is useful when there are wide load 
            fluctuations by changing the bias and so on."""))

        self.add_submodule('cv_sweep', CVSweeper(self, 'cv_sweep'))

        self.add_parameter(name='sweep_mode',
                           initial_value=constants.SweepMode.LINEAR,
                           vals=vals.Enum(*list(constants.SweepMode)),
                           set_parser=constants.SweepMode,
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
            Sweep mode. 
                1: Linear sweep (single stair, start to stop.)
                2: Log sweep (single stair, start to stop.)
                3: Linear sweep (double stair, start to stop to start.)
                4: Log sweep (double stair, start to stop to start.)
                           """))

        self.add_parameter(name='sweep_start',
                           initial_value=0.0,
                           unit='V',
                           vals=vals.Numbers(-25, 25),
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
            Start value of the DC bias sweep (in V). For the log  sweep, 
            start and stop must have the same polarity.
                           """))

        self.add_parameter(name='sweep_end',
                           initial_value=0.0,
                           unit='V',
                           vals=vals.Numbers(-25, 25),
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
            Stop value of the DC bias sweep (in V). For the log sweep, 
            start and stop must have the same polarity.
                           """))

        self.add_parameter(name='sweep_steps',
                           initial_value=1,
                           vals=vals.Ints(1, 1001),
                           parameter_class=GroupParameter,
                           docstring=textwrap.dedent("""
            Number of steps for staircase sweep. Possible  values from 1 to 
            1001"""))

        self.add_parameter(name='chan',
                           initial_value=self.channels[0],
                           parameter_class=GroupParameter)

        self._set_sweep_steps_group = Group([self.chan,
                                      self.sweep_mode,
                                      self.sweep_start,
                                      self.sweep_end,
                                      self.sweep_steps],
                                     set_cmd='WDCV '
                                             '{chan},'
                                             '{sweep_mode},'
                                             '{sweep_start},'
                                             '{sweep_end},'
                                             '{sweep_steps}',
                                     get_cmd=self._get_sweep_steps(),
                                     get_parser=self._get_sweep_steps_parser)

        self.add_parameter(name='adc_coef',
                           initial_value=1,
                           parameter_class=GroupParameter,
                           vals=vals.Ints(1, 1023),
                           docstring=textwrap.dedent("""
            Coefficient used to define the number of averaging samples or 
            the averaging time. Integer expression.
                - For mode=0: 1 to 1023. Initial setting/default setting is 2.
                - For mode=2: 1 to 100. Initial setting/default setting is 1.
            """))

        self.add_parameter(name='adc_mode',
                           initial_value=constants.ACT.Mode.PLC,
                           parameter_class=GroupParameter,
                           vals=vals.Enum(*list(constants.ACT.Mode)),
                           set_parser=constants.ACT.Mode,
                           docstring=textwrap.dedent("""
            Sets the number of averaging samples or the averaging time set 
            to the A/D converter of the MFCMU
            
                ``constants.ACT.Mode.AUTO``: Auto mode. Defines the number 
                of averaging samples given by the following formula. Then 
                initial averaging is the number of averaging samples 
                automatically set by the B1500 and you cannot change. 
            
                Number of averaging samples = N x initial averaging
            
                ``constants.ACT.Mode.PLC``: Power line cycle (PLC) mode. 
                Defines the averaging time given by the following formula. 
            
                Averaging time = N / power line frequency
                                       """))

        self._adc_group = Group([self.adc_mode, self.adc_coef],
                                set_cmd='ACT {adc_mode},{adc_coef}',
                                get_cmd=self._get_adc_mode(),
                                get_parser=self._get_adc_mode_parser)

        self.add_parameter(name='ranging_mode',
                           set_cmd=self._set_ranging_mode,
                           vals=vals.Enum(*list(constants.RangingMode)),
                           set_parser=constants.RangingMode,
                           get_cmd=None,
                           docstring=textwrap.dedent("""
            Specifies the measurement range or the measurement ranging type 
            of the MFCMU. In the initial setting, the auto ranging is set. 
            The range changing occurs immediately after the trigger 
            (that is, during the measurements).
            Possible ranging modes are autorange and fixed range.
                           """))

        self.add_parameter(name='measurement_range_for_non_auto',
                           set_cmd=self._set_measurement_range_for_non_auto,
                           get_cmd=None,
                           docstring=textwrap.dedent("""
            Measurement range. Needs to set when ``ranging_mode`` is set to 
            PLC. The value shoudl be integer 0 or more. 50 ohm, 100 ohm, 
            300 ohm, 1 kilo ohm, 3 kilo ohm, 10 kilo ohm, 30 kilo ohm, 
            100 kilo ohm, and 300 kilo ohm are selectable. Available 
            measurement ranges depend on the output signal frequency set by 
            the FC command.
                           """))

        self.add_parameter(name="measurement_mode",
                           get_cmd=None,
                           set_cmd=self._set_measurement_mode,
                           set_parser=MM.Mode,
                           vals=vals.Enum(*list(MM.Mode)),
                           docstring=textwrap.dedent("""
            Set measurement mode for this module.

            It is recommended for this parameter to use values from 
            :class:`.constants.MM.Mode` enumeration.

            Refer to the documentation of ``MM`` command in the programming 
            guide for more information.
                            """))

        self.add_parameter(name='impedance_model',
                           set_cmd=self._set_impedance_model,
                           get_cmd=None,
                           vals=vals.Enum(
                               *list(constants.IMP.MeasurementMode)),
                           set_parser=constants.IMP.MeasurementMode,
                           initial_value=constants.IMP.MeasurementMode.Cp_D,
                           docstring=textwrap.dedent("""
            The IMP command specifies the parameter measured by the MFCMU. 
            Look at the ``constants.IMP.MeasurementMode`` for all the modes. 
                           """))

        self.add_parameter(name='ac_dc_volt_monitor',
                           set_cmd=self._set_ac_dc_volt_monitor,
                           get_cmd=None,
                           vals=vals.Ints(0, 1),
                           initial_value=False,
                           docstring=textwrap.dedent("""
            This command enables or disables the data monitor and data 
            output of the MFCMU AC voltage and DC voltage.
                0: Disables the data monitor and output. Initial setting.
                1: Enables the data monitor and output.                        
                           """))

        self.add_parameter(name='cv_sweep_voltages',
                           get_cmd=self._cv_sweep_voltages,
                           unit='V',
                           label='Voltage',
                           docstring=textwrap.dedent("""
            Outputs the tuple of voltages to sweep.  sweep_start, sweep_end 
            and sweep_step functions are used to define the values of 
            voltages. There are possible modes; linear sweep, log sweep, 
            linear 2 way sweep and log 2 way sweep. The  output of 
            sweep_mode method is used to decide which mode to use.  
                           """))

        self.add_parameter(name='run_sweep',
                           parameter_class=CVSweepMeasurement,
                           docstring=textwrap.dedent("""
            This is MultiParameter. Running the sweep runs the measurement 
            on the list of values of cv_sweep_voltages. The output is a 
            primary parameter (for ex Capacitance) and a secondary  
            parameter (for ex Dissipation) both of whom use the same 
            setpoint cv_sweep_voltages. The impedance_model defines exactly 
            what will be the primary and secondary parameter. The default 
            case is Capacitance and Dissipation.
                           """))
Beispiel #28
0
    def __init__(self, name, **kw):
        super().__init__(name, **kw)
        self.add_parameter('E_c',
                           unit='Hz',
                           parameter_class=ManualParameter,
                           vals=vals.Numbers())
        self.add_parameter('E_j',
                           unit='Hz',
                           parameter_class=ManualParameter,
                           vals=vals.Numbers())
        self.add_parameter(
            'anharmonicity',
            unit='Hz',
            label='Anharmonicity',
            docstring='Anharmonicity, negative by convention',
            parameter_class=ManualParameter,
            # typical target value
            initial_value=-300e6,
            vals=vals.Numbers())
        self.add_parameter('T1',
                           unit='s',
                           parameter_class=ManualParameter,
                           vals=vals.Numbers(0, 200e-6))
        self.add_parameter('T2_echo',
                           unit='s',
                           parameter_class=ManualParameter,
                           vals=vals.Numbers())
        self.add_parameter('T2_star',
                           unit='s',
                           parameter_class=ManualParameter,
                           vals=vals.Numbers())

        self.add_parameter('dac_voltage',
                           unit='mV',
                           parameter_class=ManualParameter)
        self.add_parameter('dac_sweet_spot',
                           unit='mV',
                           parameter_class=ManualParameter)
        self.add_parameter('dac_flux_coefficient',
                           unit='',
                           parameter_class=ManualParameter)
        self.add_parameter('asymmetry',
                           unit='',
                           initial_value=0,
                           parameter_class=ManualParameter)
        self.add_parameter('dac_channel',
                           vals=vals.Ints(),
                           parameter_class=ManualParameter)

        self.add_parameter('f_qubit',
                           label='qubit frequency',
                           unit='Hz',
                           parameter_class=ManualParameter)
        self.add_parameter('f_max',
                           label='qubit frequency',
                           unit='Hz',
                           parameter_class=ManualParameter)
        self.add_parameter('f_res',
                           label='resonator frequency',
                           unit='Hz',
                           parameter_class=ManualParameter)
        self.add_parameter('f_RO',
                           label='readout frequency',
                           unit='Hz',
                           parameter_class=ManualParameter)

        # Sequence/pulse parameters
        self.add_parameter('RO_pulse_delay',
                           unit='s',
                           parameter_class=ManualParameter)
        self.add_parameter('RO_pulse_length',
                           unit='s',
                           parameter_class=ManualParameter)
        self.add_parameter('RO_acq_marker_delay',
                           unit='s',
                           parameter_class=ManualParameter)
        self.add_parameter('RO_acq_marker_channel',
                           parameter_class=ManualParameter,
                           vals=vals.Strings())
        self.add_parameter('RO_amp', unit='V', parameter_class=ManualParameter)
        # Time between start of pulses
        self.add_parameter('pulse_delay',
                           unit='s',
                           initial_value=0,
                           vals=vals.Numbers(0, 1e-6),
                           parameter_class=ManualParameter)

        self.add_parameter(
            'f_qubit_calc_method',
            vals=vals.Enum('latest', 'dac', 'flux'),
            # in the future add 'tracked_dac', 'tracked_flux',
            initial_value='latest',
            parameter_class=ManualParameter)
        self.add_parameter('F_ssro',
                           initial_value=0,
                           label='RO assignment fidelity',
                           vals=vals.Numbers(0.0, 1.0),
                           parameter_class=ManualParameter)
        self.add_parameter('F_discr',
                           initial_value=0,
                           label='RO discrimination fidelity',
                           vals=vals.Numbers(0.0, 1.0),
                           parameter_class=ManualParameter)
        self.add_parameter('F_RB',
                           initial_value=0,
                           label='RB single qubit Clifford fidelity',
                           vals=vals.Numbers(0, 1.0),
                           parameter_class=ManualParameter)
        self.add_parameter('V_per_phi0',
                           initial_value=1,
                           label='V per phi0',
                           vals=vals.Numbers(),
                           docstring='Conversion between flux and voltage. '
                           'How many volts need to be applied to '
                           'have a flux of 1 phi0 (pulsed).',
                           parameter_class=ManualParameter)
        self.add_parameter('V_offset',
                           initial_value=0,
                           label='V offset',
                           vals=vals.Numbers(),
                           docstring='AWG voltage at which the sweet spot is '
                           'found (pulsed).',
                           parameter_class=ManualParameter)
Beispiel #29
0
    def __init__(self, parent, name, channel, min_val=-5, max_val=5):
        super().__init__(parent, name)

        # Validate slot and channel values
        self._CHANNEL_VAL.validate(channel)
        self._channel = channel
        self._slot = self.parent._slot

        # Calculate base address for querying channel parameters
        # Note that the following values can be found using these offsets
        # 0: Interrupt Period
        # 4: DAC High Limit
        # 5: DAC Low Limit
        # 6: Slope (double)
        # 8: DAC Value (double)
        self._base_addr = 1536 + (16 * 4) * self._slot + 16 * self._channel

        # Store min/max voltages
        assert (min_val < max_val)
        self.min_val = min_val
        self.max_val = max_val

        # Add channel parameters
        # Note we will use the older addresses to read the value from the dac
        # rather than the newer 'd' command for backwards compatibility
        self._volt_val = vals.Numbers(self.min_val, self.max_val)
        self.add_parameter("volt",
                           get_cmd=partial(self._query_address,
                                           self._base_addr + 9, 1),
                           get_parser=self._dac_code_to_v,
                           set_cmd=self._set_dac,
                           set_parser=self._dac_v_to_code,
                           vals=self._volt_val,
                           label="channel {}".format(channel + self._slot * 4),
                           unit="V")
        # The limit commands are used to sweep dac voltages. They are not
        # safety features.
        self.add_parameter("lower_ramp_limit",
                           get_cmd=partial(self._query_address,
                                           self._base_addr + 5),
                           get_parser=self._dac_code_to_v,
                           set_cmd="L{};",
                           set_parser=self._dac_v_to_code,
                           vals=self._volt_val,
                           label="Lower_Ramp_Limit",
                           unit="V")
        self.add_parameter("upper_ramp_limit",
                           get_cmd=partial(self._query_address,
                                           self._base_addr + 4),
                           get_parser=self._dac_code_to_v,
                           set_cmd="U{};",
                           set_parser=self._dac_v_to_code,
                           vals=self._volt_val,
                           label="Upper_Ramp_Limit",
                           unit="V")
        self.add_parameter("update_period",
                           get_cmd=partial(self._query_address,
                                           self._base_addr),
                           get_parser=int,
                           set_cmd="T{};",
                           set_parser=int,
                           vals=vals.Ints(50, 65535),
                           label="Update_Period",
                           unit="us")
        self.add_parameter("slope",
                           get_cmd=partial(self._query_address,
                                           self._base_addr + 6, 2),
                           get_parser=int,
                           set_cmd="S{};",
                           set_parser=int,
                           vals=vals.Ints(-(2**32), 2**32),
                           label="Ramp_Slope")

        # Manual parameters to control whether DAC channels should ramp to
        # voltages or jump
        self._ramp_val = vals.Numbers(0, 10)
        self.add_parameter("enable_ramp",
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=False,
                           vals=vals.Bool())
        self.add_parameter("ramp_rate",
                           get_cmd=None,
                           set_cmd=None,
                           initial_value=0.1,
                           vals=self._ramp_val,
                           unit="V/s")

        # Add ramp function to the list of functions
        self.add_function("ramp",
                          call_cmd=self._ramp,
                          args=(self._volt_val, self._ramp_val))

        # If we have access to the VERSADAC (slot) EEPROM, we can set the
        # initial value of the channel.
        # NOTE: these values will be overwritten by a K3 calibration
        if self.parent._VERSA_EEPROM_available:
            _INITIAL_ADDR = [6, 8, 32774, 32776]
            self.add_parameter("initial_value",
                               get_cmd=partial(self._query_address,
                                               _INITIAL_ADDR[self._channel],
                                               versa_eeprom=True),
                               get_parser=self._dac_code_to_v,
                               set_cmd=partial(self._write_address,
                                               _INITIAL_ADDR[self._channel],
                                               versa_eeprom=True),
                               set_parser=self._dac_v_to_code,
                               vals=vals.Numbers(self.min_val, self.max_val))
Beispiel #30
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=AlazarParameter,
                           label='Clock Source',
                           unit=None,
                           value='INTERNAL_CLOCK',
                           byte_to_value_dict={
                               1: 'INTERNAL_CLOCK',
                               2: 'FAST_EXTERNAL_CLOCK',
                               7: 'EXTERNAL_CLOCK_10MHz_REF'
                           })
        self.add_parameter(name='external_sample_rate',
                           parameter_class=AlazarParameter,
                           label='External Sample Rate',
                           unit='S/s',
                           vals=validators.Ints(300000000, 1800000000),
                           value=500000000)
        self.add_parameter(name='sample_rate',
                           parameter_class=AlazarParameter,
                           label='Internal Sample Rate',
                           unit='S/s',
                           value=500000000,
                           byte_to_value_dict={
                               0x00000001: 1000,
                               0x00000002: 2000,
                               0x00000004: 5000,
                               0x00000008: 10000,
                               0x0000000A: 20000,
                               0x0000000C: 50000,
                               0x0000000E: 100000,
                               0x00000010: 200000,
                               0x00000012: 500000,
                               0x00000014: 1000000,
                               0x00000018: 2000000,
                               0x0000001A: 5000000,
                               0x0000001C: 10000000,
                               0x0000001E: 20000000,
                               0x00000021: 25000000,
                               0x00000022: 50000000,
                               0x00000024: 100000000,
                               0x00000025: 125000000,
                               0x00000026: 160000000,
                               0x00000027: 180000000,
                               0x00000028: 200000000,
                               0x0000002B: 250000000,
                               0x00000030: 500000000,
                               0x00000032: 800000000,
                               0x00000035: 1000000000,
                               0x00000037: 1200000000,
                               0x0000003A: 1500000000,
                               0x0000003D: 1800000000,
                               0x0000003F: 2000000000,
                               0x0000006A: 2400000000,
                               0x00000075: 3000000000,
                               0x0000007B: 3600000000,
                               0x00000080: 4000000000,
                               0x00000040: 'EXTERNAL_CLOCK',
                           })
        self.add_parameter(name='clock_edge',
                           parameter_class=AlazarParameter,
                           label='Clock Edge',
                           unit=None,
                           value='CLOCK_EDGE_RISING',
                           byte_to_value_dict={
                               0: 'CLOCK_EDGE_RISING',
                               1: 'CLOCK_EDGE_FALLING'
                           })
        self.add_parameter(name='decimation',
                           parameter_class=AlazarParameter,
                           label='Decimation',
                           unit=None,
                           value=1,
                           vals=validators.Ints(0, 100000))

        for i in ['1', '2']:
            self.add_parameter(name='coupling' + i,
                               parameter_class=AlazarParameter,
                               label='Coupling channel ' + i,
                               unit=None,
                               value='DC',
                               byte_to_value_dict={
                                   1: 'AC',
                                   2: 'DC'
                               })
            self.add_parameter(name='channel_range' + i,
                               parameter_class=AlazarParameter,
                               label='Range channel ' + i,
                               unit='V',
                               value=0.4,
                               byte_to_value_dict={7: 0.4})
            self.add_parameter(name='impedance' + i,
                               parameter_class=AlazarParameter,
                               label='Impedance channel ' + i,
                               unit='Ohm',
                               value=50,
                               byte_to_value_dict={2: 50})

        self.add_parameter(name='trigger_operation',
                           parameter_class=AlazarParameter,
                           label='Trigger Operation',
                           unit=None,
                           value='TRIG_ENGINE_OP_J',
                           byte_to_value_dict={
                               0: 'TRIG_ENGINE_OP_J',
                               1: 'TRIG_ENGINE_OP_K',
                               2: 'TRIG_ENGINE_OP_J_OR_K',
                               3: 'TRIG_ENGINE_OP_J_AND_K',
                               4: 'TRIG_ENGINE_OP_J_XOR_K',
                               5: 'TRIG_ENGINE_OP_J_AND_NOT_K',
                               6: 'TRIG_ENGINE_OP_NOT_J_AND_K'
                           })
        for i in ['1', '2']:
            self.add_parameter(name='trigger_engine' + i,
                               parameter_class=AlazarParameter,
                               label='Trigger Engine ' + i,
                               unit=None,
                               value='TRIG_ENGINE_' + ('J' if i == 0 else 'K'),
                               byte_to_value_dict={
                                   0: 'TRIG_ENGINE_J',
                                   1: 'TRIG_ENGINE_K'
                               })
            self.add_parameter(name='trigger_source' + i,
                               parameter_class=AlazarParameter,
                               label='Trigger Source ' + i,
                               unit=None,
                               value='EXTERNAL',
                               byte_to_value_dict={
                                   0: 'CHANNEL_A',
                                   1: 'CHANNEL_B',
                                   2: 'EXTERNAL',
                                   3: 'DISABLE'
                               })
            self.add_parameter(name='trigger_slope' + i,
                               parameter_class=AlazarParameter,
                               label='Trigger Slope ' + i,
                               unit=None,
                               value='TRIG_SLOPE_POSITIVE',
                               byte_to_value_dict={
                                   1: 'TRIG_SLOPE_POSITIVE',
                                   2: 'TRIG_SLOPE_NEGATIVE'
                               })
            self.add_parameter(name='trigger_level' + i,
                               parameter_class=AlazarParameter,
                               label='Trigger Level ' + i,
                               unit=None,
                               value=140,
                               vals=validators.Ints(0, 255))

        self.add_parameter(name='external_trigger_coupling',
                           parameter_class=AlazarParameter,
                           label='External Trigger Coupling',
                           unit=None,
                           value='DC',
                           byte_to_value_dict={
                               1: 'AC',
                               2: 'DC'
                           })
        self.add_parameter(name='external_trigger_range',
                           parameter_class=AlazarParameter,
                           label='External Trigger Range',
                           unit=None,
                           value='ETR_2V5',
                           byte_to_value_dict={
                               0: 'ETR_5V',
                               1: 'ETR_1V',
                               2: 'ETR_TTL',
                               3: 'ETR_2V5'
                           })
        self.add_parameter(name='trigger_delay',
                           parameter_class=AlazarParameter,
                           label='Trigger Delay',
                           unit='Sample clock cycles',
                           value=0,
                           vals=validators.Ints(min_value=0))

        # NOTE: The board will wait for a for this amount of time for a
        # trigger event.  If a trigger event does not arrive, then the
        # board will automatically trigger. Set the trigger timeout value
        # to 0 to force the board to wait forever for a trigger event.
        #
        # IMPORTANT: The trigger timeout value should be set to zero after
        # appropriate trigger parameters have been determined, otherwise
        # the board may trigger if the timeout interval expires before a
        # hardware trigger event arrives.
        self.add_parameter(name='timeout_ticks',
                           parameter_class=AlazarParameter,
                           label='Timeout Ticks',
                           unit='10 us',
                           value=0,
                           vals=validators.Ints(min_value=0))

        self.add_parameter(name='aux_io_mode',
                           parameter_class=AlazarParameter,
                           label='AUX I/O Mode',
                           unit=None,
                           value='AUX_IN_AUXILIARY',
                           byte_to_value_dict={
                               0: 'AUX_OUT_TRIGGER',
                               1: 'AUX_IN_TRIGGER_ENABLE',
                               13: 'AUX_IN_AUXILIARY'
                           })

        self.add_parameter(name='aux_io_param',
                           parameter_class=AlazarParameter,
                           label='AUX I/O Param',
                           unit=None,
                           value='NONE',
                           byte_to_value_dict={
                               0: 'NONE',
                               1: 'TRIG_SLOPE_POSITIVE',
                               2: 'TRIG_SLOPE_NEGATIVE'
                           })

        # ----- Parameters for the acquire function -----
        self.add_parameter(name='mode',
                           parameter_class=AlazarParameter,
                           label='Acquisition mode',
                           unit=None,
                           value='NPT',
                           byte_to_value_dict={
                               0x200: 'NPT',
                               0x400: 'TS'
                           })
        self.add_parameter(name='samples_per_record',
                           parameter_class=AlazarParameter,
                           label='Samples per Record',
                           unit=None,
                           value=1024,
                           vals=validators.Multiples(
                               divisor=self.samples_divisor, min_value=256))
        self.add_parameter(name='records_per_buffer',
                           parameter_class=AlazarParameter,
                           label='Records per Buffer',
                           unit=None,
                           value=10,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='buffers_per_acquisition',
                           parameter_class=AlazarParameter,
                           label='Buffers per Acquisition',
                           unit=None,
                           value=10,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='channel_selection',
                           parameter_class=AlazarParameter,
                           label='Channel Selection',
                           unit=None,
                           value='AB',
                           byte_to_value_dict={
                               1: 'A',
                               2: 'B',
                               3: 'AB'
                           })
        self.add_parameter(name='transfer_offset',
                           parameter_class=AlazarParameter,
                           label='Transfer Offset',
                           unit='Samples',
                           value=0,
                           vals=validators.Ints(min_value=0))
        self.add_parameter(name='external_startcapture',
                           parameter_class=AlazarParameter,
                           label='External Startcapture',
                           unit=None,
                           value='ENABLED',
                           byte_to_value_dict={
                               0x0: 'DISABLED',
                               0x1: 'ENABLED'
                           })
        self.add_parameter(name='enable_record_headers',
                           parameter_class=AlazarParameter,
                           label='Enable Record Headers',
                           unit=None,
                           value='DISABLED',
                           byte_to_value_dict={
                               0x0: 'DISABLED',
                               0x8: 'ENABLED'
                           })
        self.add_parameter(name='alloc_buffers',
                           parameter_class=AlazarParameter,
                           label='Alloc Buffers',
                           unit=None,
                           value='DISABLED',
                           byte_to_value_dict={
                               0x0: 'DISABLED',
                               0x20: 'ENABLED'
                           })
        self.add_parameter(name='fifo_only_streaming',
                           parameter_class=AlazarParameter,
                           label='Fifo Only Streaming',
                           unit=None,
                           value='DISABLED',
                           byte_to_value_dict={
                               0x0: 'DISABLED',
                               0x800: 'ENABLED'
                           })
        self.add_parameter(name='interleave_samples',
                           parameter_class=AlazarParameter,
                           label='Interleave Samples',
                           unit=None,
                           value='DISABLED',
                           byte_to_value_dict={
                               0x0: 'DISABLED',
                               0x1000: 'ENABLED'
                           })
        self.add_parameter(name='get_processed_data',
                           parameter_class=AlazarParameter,
                           label='Get Processed Data',
                           unit=None,
                           value='DISABLED',
                           byte_to_value_dict={
                               0x0: 'DISABLED',
                               0x2000: 'ENABLED'
                           })
        self.add_parameter(name='allocated_buffers',
                           parameter_class=AlazarParameter,
                           label='Allocated Buffers',
                           unit=None,
                           value=4,
                           vals=validators.Ints(min_value=0))

        self.add_parameter(name='buffer_timeout',
                           parameter_class=AlazarParameter,
                           label='Buffer Timeout',
                           unit='ms',
                           value=1000,
                           vals=validators.Ints(min_value=0))

        model = self.get_idn()['model']
        if model != 'ATS9360':
            raise Exception("The Alazar board kind is not 'ATS9360',"
                            " found '" + str(model) + "' instead.")