Example #1
0
    def __init__(self, name, **kwargs):
        super().__init__(name, **kwargs)

        channels = ChannelList(self,
                               "TempSensors",
                               DummyChannel,
                               snapshotable=False)
        for chan_name in ('A', 'B', 'C', 'D', 'E', 'F'):
            channel = DummyChannel(self, f'Chan{chan_name}', chan_name)
            channels.append(channel)
            self.add_submodule(chan_name, channel)
        self.add_submodule("channels", channels.to_channel_tuple())
Example #2
0
    def __init__(self, name, channel_names=None, **kwargs):
        super().__init__(name, **kwargs)

        channels = ChannelList(self,
                               "TempSensors",
                               DummyChannel,
                               snapshotable=False)

        if channel_names is None:
            channel_ids = ("A", "B", "C", "D", "E", "F")
            channel_names = tuple(f"Chan{chan_name}"
                                  for chan_name in channel_ids)
        else:
            channel_ids = channel_names
        for chan_name, chan_id in zip(channel_names, channel_ids):
            channel = DummyChannel(self, chan_name, chan_id)
            channels.append(channel)
            self.add_submodule(chan_id, channel)
        self.add_submodule("channels", channels.to_channel_tuple())
Example #3
0
    def __init__(self, name: str = 'mdac', num_channels: int = 10, **kwargs):
        """
        Create a dummy instrument that can be used for testing

        Args:
            name: name for the instrument
            gates: list of names that is used to create parameters for
                            the instrument
        """
        super().__init__(name, **kwargs)

        # make gates
        channels = ChannelList(self, "channels", MockDACChannel)
        for n in range(num_channels):
            num = str(n + 1).zfill(2)
            chan_name = f"ch{num}"
            channel = MockDACChannel(parent=self, name=chan_name, num=num)
            channels.append(channel)
            self.add_submodule(chan_name, channel)
        self.add_submodule("channels", channels.to_channel_tuple())
Example #4
0
    def __init__(self, name: str, address: str, port: int = 23):
        super().__init__(name, address, port)
        self.flush_connection()

        channels = ChannelList(self,
                               "Channels",
                               MC_channel,
                               snapshotable=False)

        _chanlist = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
        _max_channel_number = int(self.IDN()['model'][3])
        _chanlist = _chanlist[0:_max_channel_number]

        for c in _chanlist:
            channel = MC_channel(self, f'channel_{c}', c)
            channels.append(channel)
            self.add_submodule(f"channel_{c}", channel)
        self.add_submodule("channels", channels.to_channel_tuple())

        self.connect_message()
Example #5
0
    def add_channels(self) -> None:
        channels = ChannelList(self,
                               "Channels",
                               self.CHANNEL_CLASS,
                               snapshotable=False)

        _chanlist = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
        self._deprecated_attributes: Dict[str, str] = {
            f'channel_{k}': k
            for k in _chanlist
        }

        _max_channel_number = self.get_number_of_channels()
        _chanlist = _chanlist[0:_max_channel_number]

        for c in _chanlist:
            channel = self.CHANNEL_CLASS(self, f'channel_{c}', c)
            channels.append(channel)
            attribute_name = f'channel_{c}'
            self.add_submodule(attribute_name, channel)
            self.add_submodule(c, channel)
            self._deprecated_attributes[attribute_name] = c
        self.add_submodule("channels", channels.to_channel_tuple())
Example #6
0
    def __init__(self,
                 name: str,
                 address: str,
                 timeout: float = 20,
                 **kwargs: Any):
        """
        Initialises the DS4000.

        Args:
            name: Name of the instrument used by QCoDeS
            address: Instrument address as used by VISA
            timeout: visa timeout, in secs. long default (180)
                to accommodate large waveforms
        """

        # Init VisaInstrument. device_clear MUST NOT be issued, otherwise communications hangs
        # due a bug in firmware
        super().__init__(name,
                         address,
                         device_clear=False,
                         timeout=timeout,
                         **kwargs)
        self.connect_message()

        self._check_firmware_version()

        # functions
        self.add_function('run',
                          call_cmd=':RUN',
                          docstring='Start acquisition')
        self.add_function('stop',
                          call_cmd=':STOP',
                          docstring='Stop acquisition')
        self.add_function('single',
                          call_cmd=':SINGle',
                          docstring='Single trace acquisition')
        self.add_function('force_trigger',
                          call_cmd='TFORce',
                          docstring='Force trigger event')
        self.add_function("auto_scale",
                          call_cmd=":AUToscale",
                          docstring="Perform autoscale")

        # general parameters
        self.add_parameter('trigger_type',
                           label='Type of the trigger',
                           get_cmd=':TRIGger:MODE?',
                           set_cmd=':TRIGger:MODE {}',
                           vals=vals.Enum('EDGE', 'PULS', 'RUNT', 'NEDG',
                                          'SLOP', 'VID', 'PATT', 'RS232',
                                          'IIC', 'SPI', 'CAN', 'FLEX', 'USB'))
        self.add_parameter('trigger_mode',
                           label='Mode of the trigger',
                           get_cmd=':TRIGger:SWEep?',
                           set_cmd=':TRIGger:SWEep {}',
                           vals=vals.Enum('AUTO', 'NORM', 'SING'))
        self.add_parameter("time_base",
                           label="Horizontal time base",
                           get_cmd=":TIMebase:MAIN:SCALe?",
                           set_cmd=":TIMebase:MAIN:SCALe {}",
                           get_parser=float,
                           unit="s/div")
        self.add_parameter("sample_point_count",
                           label="Number of the waveform points",
                           get_cmd=":WAVeform:POINts?",
                           set_cmd=":WAVeform:POINts {}",
                           get_parser=int,
                           vals=Ints(min_value=1))
        self.add_parameter("enable_auto_scale",
                           label="Enable or disable autoscale",
                           get_cmd=":SYSTem:AUToscale?",
                           set_cmd=":SYSTem:AUToscale {}",
                           get_parser=bool,
                           vals=Bool())

        channels = ChannelList(self,
                               "Channels",
                               RigolDS4000Channel,
                               snapshotable=False)

        for channel_number in range(1, 5):
            channel = RigolDS4000Channel(self, f"ch{channel_number}",
                                         channel_number)
            channels.append(channel)

        self.add_submodule("channels", channels.to_channel_tuple())
Example #7
0
    def __init__(
        self,
        name: str,
        address: str,
        timeout: float = 20,
        channels: int = 4,
        silence_pyvisapy_warning: bool = False,
        **kwargs: Any,
    ):
        """
        Initialises the oscilloscope.

        Args:
            name: Name of the instrument used by QCoDeS
            address: Instrument address as used by VISA
            timeout: Visa timeout, in secs.
            channels: The number of channels on the scope.
            silence_pyvisapy_warning: Don't warn about pyvisa-py at startup
        """
        super().__init__(name,
                         address,
                         timeout=timeout,
                         terminator="\n",
                         **kwargs)
        self.connect_message()

        # Check if we are using pyvisa-py as our visa lib and warn users that
        # this may cause long digitize operations to fail
        if (self.visa_handle.visalib.library_path == "py"
                and not silence_pyvisapy_warning):
            self.log.warning(
                "Timeout not handled correctly in pyvisa_py. This may cause"
                " long acquisitions to fail. Either use ni/keysight visalib"
                " or set timeout to longer than longest expected acquisition"
                " time.")

        # switch the response header off else none of our parameters will work
        self.write(":SYSTem:HEADer OFF")

        # Then set up the data format used to retrieve waveforms
        self.write(":WAVEFORM:FORMAT WORD")
        self.write(":WAVEFORM:BYTEORDER LSBFirst")
        self.write(":WAVEFORM:STREAMING ON")

        # Query the oscilloscope parameters
        # Set sample rate, bandwidth and memory depth limits
        self._query_capabilities()
        # Number of channels can't be queried on most older scopes. Use a parameter
        # for now.
        self.no_channels = channels

        # Run state
        self.run_mode = Parameter(
            name="run_mode",
            instrument=self,
            label="run mode",
            get_cmd=":RST?",
            vals=vals.Enum("RUN", "STOP", "SING"),
        )

        # Timing Parameters
        self.timebase_range = Parameter(
            name="timebase_range",
            instrument=self,
            label="Range of the time axis",
            unit="s",
            get_cmd=":TIM:RANG?",
            set_cmd=":TIM:RANG {}",
            vals=vals.Numbers(5e-12, 20),
            get_parser=float,
        )
        self.timebase_position = Parameter(
            name="timebase_position",
            instrument=self,
            label="Offset of the time axis",
            unit="s",
            get_cmd=":TIM:POS?",
            set_cmd=":TIM:POS {}",
            vals=vals.Numbers(),
            get_parser=float,
        )
        self.timebase_roll_enabled = Parameter(
            name="timebase_roll_enabled",
            instrument=self,
            label="Is rolling mode enabled",
            get_cmd=":TIM:ROLL:ENABLE?",
            set_cmd=":TIM:ROLL:ENABLE {}",
            val_mapping={
                True: 1,
                False: 0
            },
        )

        # Trigger
        self.trigger_mode = Parameter(
            name="trigger_mode",
            instrument=self,
            label="Trigger mode",
            get_cmd=":TRIG:MODE?",
        )
        self.trigger_sweep = Parameter(
            name="trigger_sweep",
            instrument=self,
            label="Trigger sweep mode",
            get_cmd=":TRIG:SWE?",
            set_cmd=":TRIG:SWE {}",
            vals=vals.Enum("AUTO", "TRIG"),
        )
        self.trigger_state = Parameter(
            name="trigger_state",
            instrument=self,
            label="Trigger state",
            get_cmd=":AST?",
            vals=vals.Enum("ARM", "TRIG", "ATRIG", "ADONE"),
            snapshot_value=False,
        )

        # Edge trigger parameters
        # Note that for now we only support parameterized edge triggers - this may
        # be something worth expanding.
        # To set trigger level, use the "trigger_level" parameter in each channel
        self.trigger_edge_source = Parameter(
            name="trigger_edge_source",
            instrument=self,
            label="Source channel for the edge trigger",
            get_cmd=":TRIGger:EDGE:SOURce?",
            set_cmd=":TRIGger:EDGE:SOURce {}",
            vals=vals.Enum(*([f"CHAN{i}" for i in range(1, 4 + 1)] +
                             [f"DIG{i}"
                              for i in range(16 + 1)] + ["AUX", "LINE"])),
        )
        self.trigger_edge_slope = Parameter(
            name="trigger_edge_slope",
            instrument=self,
            label="slope of the edge trigger",
            get_cmd=":TRIGger:EDGE:SLOPe?",
            set_cmd=":TRIGger:EDGE:SLOPe {}",
            vals=vals.Enum("POS", "POSITIVE", "NEG", "NEGATIVE", "EITH"),
        )
        self.trigger_level_aux = Parameter(
            name="trigger_level_aux",
            instrument=self,
            label="Tirgger level AUX",
            unit="V",
            get_cmd=":TRIGger:LEVel? AUX",
            set_cmd=":TRIGger:LEVel AUX,{}",
            get_parser=float,
            vals=vals.Numbers(),
        )

        # Aquisition
        # If sample points, rate and timebase_scale are set in an
        # incomensurate way, the scope only displays part of the waveform
        self.acquire_points = Parameter(
            name="acquire_points",
            instrument=self,
            label="sample points",
            get_cmd=":ACQ:POIN?",
            set_cmd=":ACQ:POIN {}",
            get_parser=int,
            vals=vals.Numbers(min_value=self.min_pts, max_value=self.max_pts),
        )
        self.sample_rate = Parameter(
            name="sample_rate",
            instrument=self,
            label="sample rate",
            get_cmd=":ACQ:SRAT?",
            set_cmd=":ACQ:SRAT {}",
            unit="Hz",
            get_parser=float,
            vals=vals.Numbers(min_value=self.min_srat,
                              max_value=self.max_srat),
        )
        # Note: newer scopes allow a per-channel bandwidth. This is not implemented yet.
        self.bandwidth = Parameter(
            name="bandwidth",
            instrument=self,
            label="bandwidth",
            get_cmd=":ACQ:BAND?",
            set_cmd=":ACQ:BAND {}",
            unit="Hz",
            get_parser=float,
            vals=vals.Numbers(min_value=self.min_bw, max_value=self.max_bw),
        )
        self.acquire_interpolate = Parameter(
            name="acquire_interpolate",
            instrument=self,
            get_cmd=":ACQ:INTerpolate?",
            set_cmd=":ACQuire:INTerpolate {}",
            vals=vals.Enum(0, 1, "INT1", "INT2", "INT4", "INT8", "INT16",
                           "INT32"),
        )
        self.acquire_mode = Parameter(
            name="acquire_mode",
            instrument=self,
            label="Acquisition mode",
            get_cmd="ACQuire:MODE?",
            set_cmd="ACQuire:MODE {}",
            vals=vals.Enum(
                "ETIMe",
                "RTIMe",
                "PDETect",
                "HRESolution",
                "SEGMented",
                "SEGPdetect",
                "SEGHres",
            ),
        )
        self.average = Parameter(
            name="average",
            instrument=self,
            label="Averages",
            get_cmd=self._get_avg,
            set_cmd=self._set_avg,
            vals=vals.Ints(min_value=1, max_value=10486575),
        )

        # Automatically digitize before acquiring a trace
        self.auto_digitize: Parameter = Parameter(
            name="auto_digitize",
            instrument=self,
            label="Auto digitize",
            set_cmd=None,
            get_cmd=None,
            val_mapping=create_on_off_val_mapping(),
            docstring=(
                "Digitize before each waveform download. "
                "If you need to acquire from multiple channels simultaneously "
                "or you wish to acquire with the scope running freely, "
                "set this value to False."),
            initial_value=True,
        )
        self.cache_setpoints: Parameter = Parameter(
            name="cache_setpoints",
            instrument=self,
            label="Cache setpoints",
            set_cmd=None,
            get_cmd=None,
            val_mapping=create_on_off_val_mapping(),
            docstring=
            ("Cache setpoints. If false, the preamble is queried before each"
             " acquisition, which may add latency to measurements. If you"
             " are taking repeated measurements, set this to True and update"
             " setpoints manually by calling `instr.chX.update_setpoints()`."),
            initial_value=False,
        )

        # Channels
        _channels = ChannelList(self,
                                "channels",
                                InfiniiumChannel,
                                snapshotable=False)
        for i in range(1, self.no_channels + 1):
            channel = InfiniiumChannel(self, f"chan{i}", i)
            _channels.append(channel)
            self.add_submodule(f"ch{i}", channel)
        self.add_submodule("channels", _channels.to_channel_tuple())

        # Functions
        _functions = ChannelList(self,
                                 "functions",
                                 InfiniiumFunction,
                                 snapshotable=False)
        for i in range(1, 16 + 1):
            function = InfiniiumFunction(self, f"func{i}", i)
            _functions.append(function)
            self.add_submodule(f"func{i}", function)
        # Have to call channel list "funcs" here as functions is a
        # reserved name in Instrument.
        self.add_submodule("funcs", _functions.to_channel_tuple())

        # Submodules
        meassubsys = UnboundMeasurement(self, "measure")
        self.add_submodule("measure", meassubsys)
Example #8
0
    def __init__(self,
                 name: str,
                 address: str,
                 max_frequency: float,
                 reset: bool = False,
                 **kwargs: Any):
        super().__init__(name, address, terminator='\n', **kwargs)
        self._max_frequency = max_frequency
        # Reference commands
        self.add_parameter(name='frequency',
                           label='Frequency',
                           unit='Hz',
                           get_cmd='FREQ?',
                           set_cmd='FREQ {}',
                           get_parser=float,
                           vals=Numbers(min_value=1e-3,
                                        max_value=self._max_frequency))
        self.add_parameter(name='sine_outdc',
                           label='Sine out dc level',
                           unit='V',
                           get_cmd='SOFF?',
                           set_cmd='SOFF {}',
                           get_parser=float,
                           vals=Numbers(min_value=-5, max_value=5))
        self.add_parameter(name='amplitude',
                           label='Amplitude',
                           unit='V',
                           get_cmd='SLVL?',
                           set_cmd='SLVL {}',
                           get_parser=float,
                           vals=Numbers(min_value=0, max_value=2))
        self.add_parameter(name='harmonic',
                           label='Harmonic',
                           get_cmd='HARM?',
                           get_parser=int,
                           set_cmd='HARM {:d}',
                           vals=Ints(min_value=1, max_value=99))
        self.add_parameter(name='phase',
                           label='Phase',
                           unit='deg',
                           get_cmd='PHAS?',
                           set_cmd='PHAS {}',
                           get_parser=float,
                           vals=Numbers(min_value=-3.6e5, max_value=3.6e5))
        # Signal commands
        self.add_parameter(name='sensitivity',
                           label='Sensitivity',
                           get_cmd='SCAL?',
                           set_cmd='SCAL {:d}',
                           get_parser=self._get_sensitivity,
                           set_parser=self._set_sensitivity)
        self.add_parameter(name='filter_slope',
                           label='Filter slope',
                           unit='dB/oct',
                           get_cmd='OFSL?',
                           set_cmd='OFSL {}',
                           val_mapping={
                               6: 0,
                               12: 1,
                               18: 2,
                               24: 3
                           })
        self.add_parameter(name='sync_filter',
                           label='Sync filter',
                           get_cmd='SYNC?',
                           set_cmd='SYNC {}',
                           val_mapping={
                               'OFF': 0,
                               'ON': 1
                           })
        self.add_parameter(name='noise_bandwidth',
                           label='Noise bandwidth',
                           unit='Hz',
                           get_cmd='ENBW?',
                           get_parser=float)
        self.add_parameter(name='signal_strength',
                           label='Signal strength indicator',
                           get_cmd='ILVL?',
                           get_parser=int)
        self.add_parameter(name='signal_input',
                           label='Signal input',
                           get_cmd='IVMD?',
                           get_parser=self._get_input_config,
                           set_cmd='IVMD {}',
                           set_parser=self._set_input_config,
                           vals=Enum(*self._INPUT_SIGNAL_TO_N.keys()))
        self.add_parameter(name='input_range',
                           label='Input range',
                           unit='V',
                           get_cmd='IRNG?',
                           set_cmd='IRNG {}',
                           val_mapping={
                               1: 0,
                               300e-3: 1,
                               100e-3: 2,
                               30e-3: 3,
                               10e-3: 4
                           })
        self.add_parameter(name='input_config',
                           label='Input configuration',
                           get_cmd='ISRC?',
                           set_cmd='ISRC {}',
                           val_mapping={
                               'a': 0,
                               'a-b': 1
                           })
        self.add_parameter(name='input_shield',
                           label='Input shield',
                           get_cmd='IGND?',
                           set_cmd='IGND {}',
                           val_mapping={
                               'float': 0,
                               'ground': 1
                           })
        self.add_parameter(name='input_gain',
                           label='Input gain',
                           unit='ohm',
                           get_cmd='ICUR?',
                           set_cmd='ICUR {}',
                           val_mapping={
                               1e6: 0,
                               100e6: 1
                           })
        self.add_parameter(name='adv_filter',
                           label='Advanced filter',
                           get_cmd='ADVFILT?',
                           set_cmd='ADVFILT {}',
                           val_mapping={
                               'OFF': 0,
                               'ON': 1
                           })
        self.add_parameter(name='input_coupling',
                           label='Input coupling',
                           get_cmd='ICPL?',
                           set_cmd='ICPL {}',
                           val_mapping={
                               'ac': 0,
                               'dc': 1
                           })
        self.add_parameter(name='time_constant',
                           label='Time constant',
                           unit='s',
                           get_cmd='OFLT?',
                           set_cmd='OFLT {}',
                           val_mapping={
                               1e-6: 0,
                               3e-6: 1,
                               10e-6: 2,
                               30e-6: 3,
                               100e-6: 4,
                               300e-6: 5,
                               1e-3: 6,
                               3e-3: 7,
                               10e-3: 8,
                               30e-3: 9,
                               100e-3: 10,
                               300e-3: 11,
                               1: 12,
                               3: 13,
                               10: 14,
                               30: 15,
                               100: 16,
                               300: 17,
                               1e3: 18,
                               3e3: 19,
                               10e3: 20,
                               30e3: 21
                           })

        self.add_parameter(
            name="external_reference_trigger",
            label="External reference trigger mode",
            get_cmd="RTRG?",
            set_cmd="RTRG {}",
            val_mapping={
                "SIN": 0,
                "POS": 1,
                "POSTTL": 1,
                "NEG": 2,
                "NEGTTL": 2,
            },
            docstring="The triggering mode for synchronization of the "
            "internal reference signal with the externally provided "
            "one")

        self.add_parameter(name="reference_source",
                           label="Reference source",
                           get_cmd="RSRC?",
                           set_cmd="RSRC {}",
                           val_mapping={
                               "INT": 0,
                               "EXT": 1,
                               "DUAL": 2,
                               "CHOP": 3
                           },
                           docstring="The source of the reference signal")

        self.add_parameter(
            name="external_reference_trigger_input_resistance",
            label="External reference trigger input resistance",
            get_cmd="REFZ?",
            set_cmd="REFZ {}",
            val_mapping={
                "50": 0,
                "50OHMS": 0,
                0: 0,
                "1M": 1,
                "1MEG": 1,
                1: 1,
            },
            docstring="Input resistance of the input for the external "
            "reference signal")

        # Auto functions
        self.add_function('auto_range', call_cmd='ARNG')
        self.add_function('auto_scale', call_cmd='ASCL')
        self.add_function('auto_phase', call_cmd='APHS')

        # Data transfer
        # first 4 parameters from a list of 16 below.
        self.add_parameter('X',
                           label='In-phase Magnitude',
                           get_cmd='OUTP? 0',
                           get_parser=float,
                           unit='V')
        self.add_parameter('Y',
                           label='Out-phase Magnitude',
                           get_cmd='OUTP? 1',
                           get_parser=float,
                           unit='V')
        self.add_parameter('R',
                           label='Magnitude',
                           get_cmd='OUTP? 2',
                           get_parser=float,
                           unit='V')
        self.add_parameter('P',
                           label='Phase',
                           get_cmd='OUTP? 3',
                           get_parser=float,
                           unit='deg')
        self.add_parameter('complex_voltage',
                           label='Voltage',
                           get_cmd=self._get_complex_voltage,
                           unit='V',
                           vals=ComplexNumbers())

        # CH1/CH2 Output Commands
        self.add_parameter('X_offset',
                           label='X offset ',
                           unit='%',
                           get_cmd='COFP? 0',
                           set_cmd='COFP 0, {}',
                           get_parser=float,
                           vals=Numbers(min_value=-999.99, max_value=999.99))
        self.add_parameter('Y_offset',
                           label='Y offset',
                           unit='%',
                           get_cmd='COFP? 1',
                           set_cmd='COFP 1, {}',
                           get_parser=float,
                           vals=Numbers(min_value=-999.99, max_value=999.99))
        self.add_parameter('R_offset',
                           label='R offset',
                           unit='%',
                           get_cmd='COFP? 2',
                           set_cmd='COFP 2, {}',
                           get_parser=float,
                           vals=Numbers(min_value=-999.99, max_value=999.99))
        self.add_parameter('X_expand',
                           label='X expand multiplier',
                           get_cmd='CEXP? 0',
                           set_cmd='CEXP 0, {}',
                           val_mapping={
                               'OFF': '0',
                               'X10': '1',
                               'X100': '2'
                           })
        self.add_parameter('Y_expand',
                           label='Y expand multiplier',
                           get_cmd='CEXP? 1',
                           set_cmd='CEXP 1, {}',
                           val_mapping={
                               'OFF': 0,
                               'X10': 1,
                               'X100': 2
                           })
        self.add_parameter('R_expand',
                           label='R expand multiplier',
                           get_cmd='CEXP? 2',
                           set_cmd='CEXP 2, {}',
                           val_mapping={
                               'OFF': 0,
                               'X10': 1,
                               'X100': 2
                           })

        # Aux input/output
        for i in [0, 1, 2, 3]:
            self.add_parameter(f'aux_in{i}',
                               label=f'Aux input {i}',
                               get_cmd=f'OAUX? {i}',
                               get_parser=float,
                               unit='V')
            self.add_parameter(f'aux_out{i}',
                               label=f'Aux output {i}',
                               get_cmd=f'AUXV? {i}',
                               get_parser=float,
                               set_cmd=f'AUXV {i}, {{}}',
                               unit='V')

        # Data channels:
        # 'DAT1' (green), 'DAT2' (blue), 'DAT3' (yellow), 'DAT4' (orange)
        data_channels = ChannelList(self,
                                    "data_channels",
                                    SR86xDataChannel,
                                    snapshotable=False)
        for num, color in zip(range(self._N_DATA_CHANNELS),
                              ('green', 'blue', 'yellow', 'orange')):
            cmd_id = f"{num}"
            cmd_id_name = f"DAT{num + 1}"
            ch_name = f"data_channel_{num + 1}"

            data_channel = SR86xDataChannel(self, ch_name, cmd_id, cmd_id_name,
                                            color)

            data_channels.append(data_channel)
            self.add_submodule(ch_name, data_channel)

        self.add_submodule("data_channels", data_channels.to_channel_tuple())

        # Interface
        self.add_function('reset', call_cmd='*RST')

        self.add_function('disable_front_panel', call_cmd='OVRM 0')
        self.add_function('enable_front_panel', call_cmd='OVRM 1')

        buffer = SR86xBuffer(self, f"{self.name}_buffer")
        self.add_submodule("buffer", buffer)

        self.input_config()
        self.connect_message()
Example #9
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')
Example #10
0
    def __init__(self,
                 name: str,
                 address: str,
                 num_chans: int = 48,
                 update_currents: bool = True,
                 **kwargs: Any):
        """
        Instantiates the instrument.

        Args:
            name: The instrument name used by qcodes
            address: The VISA name of the resource
            num_chans: Number of channels to assign. Default: 48
            update_currents: 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
        assert isinstance(handle, SerialInstrument)
        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: List[Tuple[int, Union[str, float]]] = []
        # Function generators (used in _set_voltage)
        self._fgs = set(range(1, 9))
        self._assigned_fgs: Dict[int, int] = {}  # {chan: fg}
        # Sync channels
        self._syncoutputs: List[Tuple[int, int]] = [
        ]  # 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)
        self.add_submodule("channels", channels.to_channel_tuple())

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