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

        # Allow access to channels either by referring to the channel name
        # or through a channel list, i.e. instr.A.temperature() and
        # instr.channels[0].temperature() refer to the same parameter.
        # Note that `snapshotable` is set to false in order to avoid duplicate
        # snapshotting which otherwise will happen because each channel is also
        # added as a submodule to the instrument.
        channels = ChannelList(self,
                               "TempSensors",
                               self.CHANNEL_CLASS,
                               snapshotable=False)
        for name, command in self.channel_name_command.items():
            channel = self.CHANNEL_CLASS(self, name, command)
            channels.append(channel)
            self.add_submodule(name, channel)
        self.add_submodule("channels", channels.to_channel_tuple())

        self.connect_message()
Beispiel #2
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 = 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 = ''

        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')
Beispiel #3
0
    def __init__(
        self,
        name: str,
        address: str,
        init_s_params: bool = True,
        reset_channels: bool = True,
        **kwargs: Any,
    ) -> None:

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

        # TODO(JHN) I could not find a way to get max and min freq from
        # the API, if that is possible replace below with that
        # See page 1025 in the manual. 7.3.15.10 for details of max/min freq
        # no attempt to support ZNB40, not clear without one how the format
        # is due to variants
        fullmodel = self.get_idn()["model"]
        if fullmodel is not None:
            model = fullmodel.split("-")[0]
        else:
            raise RuntimeError("Could not determine ZNB model")
        # format seems to be ZNB8-4Port
        m_frequency = {
            "ZNB4": (9e3, 4.5e9),
            "ZNB8": (9e3, 8.5e9),
            "ZNB20": (100e3, 20e9),
            "ZNB40": (10e6, 40e9),
        }
        if model not in m_frequency.keys():
            raise RuntimeError(f"Unsupported ZNB model {model}")
        self._min_freq: float
        self._max_freq: float
        self._min_freq, self._max_freq = m_frequency[model]

        self.add_parameter(name="num_ports",
                           get_cmd="INST:PORT:COUN?",
                           get_parser=int)
        num_ports = self.num_ports()

        self.add_parameter(
            name="rf_power",
            get_cmd="OUTP1?",
            set_cmd="OUTP1 {}",
            val_mapping={True: "1\n", False: "0\n"},
        )
        self.add_function("reset", call_cmd="*RST")
        self.add_function("tooltip_on", call_cmd="SYST:ERR:DISP ON")
        self.add_function("tooltip_off", call_cmd="SYST:ERR:DISP OFF")
        self.add_function("cont_meas_on", call_cmd="INIT:CONT:ALL ON")
        self.add_function("cont_meas_off", call_cmd="INIT:CONT:ALL OFF")
        self.add_function("update_display_once", call_cmd="SYST:DISP:UPD ONCE")
        self.add_function("update_display_on", call_cmd="SYST:DISP:UPD ON")
        self.add_function("update_display_off", call_cmd="SYST:DISP:UPD OFF")
        self.add_function(
            "display_sij_split",
            call_cmd=f"DISP:LAY GRID;:DISP:LAY:GRID {num_ports},{num_ports}",
        )
        self.add_function(
            "display_single_window", call_cmd="DISP:LAY GRID;:DISP:LAY:GRID 1,1"
        )
        self.add_function(
            "display_dual_window", call_cmd="DISP:LAY GRID;:DISP:LAY:GRID 2,1"
        )
        self.add_function("rf_off", call_cmd="OUTP1 OFF")
        self.add_function("rf_on", call_cmd="OUTP1 ON")
        if reset_channels:
            self.reset()
            self.clear_channels()
        channels = ChannelList(
            self, "VNAChannels", self.CHANNEL_CLASS, snapshotable=True
        )
        self.add_submodule("channels", channels)
        if init_s_params:
            for i in range(1, num_ports + 1):
                for j in range(1, num_ports + 1):
                    ch_name = "S" + str(i) + str(j)
                    self.add_channel(ch_name)
            self.display_sij_split()
            self.channels.autoscale()

        self.update_display_on()
        if reset_channels:
            self.rf_off()
        self.connect_message()
Beispiel #4
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())
Beispiel #5
0
    def __init__(self,
                 name: str,
                 address: str,
                 timeout: float = 20,
                 **kwargs: Any):
        """
        Initialises the TPS2012.

        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
        """

        super().__init__(name, address, timeout=timeout, **kwargs)
        self.connect_message()

        # Scope trace boolean
        self.trace_ready = False

        # functions

        self.add_function('force_trigger',
                          call_cmd='TRIGger FORce',
                          docstring='Force trigger event')
        self.add_function('run',
                          call_cmd='ACQuire:STATE RUN',
                          docstring='Start acquisition')
        self.add_function('stop',
                          call_cmd='ACQuire:STATE STOP',
                          docstring='Stop acquisition')

        # general parameters
        self.add_parameter('trigger_type',
                           label='Type of the trigger',
                           get_cmd='TRIGger:MAIn:TYPe?',
                           set_cmd='TRIGger:MAIn:TYPe {}',
                           vals=vals.Enum('EDGE', 'VIDEO', 'PULSE'))
        self.add_parameter('trigger_source',
                           label='Source for the trigger',
                           get_cmd='TRIGger:MAIn:EDGE:SOURce?',
                           set_cmd='TRIGger:MAIn:EDGE:SOURce {}',
                           vals=vals.Enum('CH1', 'CH2'))
        self.add_parameter('trigger_edge_slope',
                           label='Slope for edge trigger',
                           get_cmd='TRIGger:MAIn:EDGE:SLOpe?',
                           set_cmd='TRIGger:MAIn:EDGE:SLOpe {}',
                           vals=vals.Enum('FALL', 'RISE'))
        self.add_parameter('trigger_level',
                           label='Trigger level',
                           unit='V',
                           get_cmd='TRIGger:MAIn:LEVel?',
                           set_cmd='TRIGger:MAIn:LEVel {}',
                           vals=vals.Numbers())
        self.add_parameter('data_source',
                           label='Data source',
                           get_cmd='DATa:SOUrce?',
                           set_cmd='DATa:SOURce {}',
                           vals=vals.Enum('CH1', 'CH2'))
        self.add_parameter('horizontal_scale',
                           label='Horizontal scale',
                           unit='s',
                           get_cmd='HORizontal:SCAle?',
                           set_cmd=self._set_timescale,
                           get_parser=float,
                           vals=vals.Enum(5e-9, 10e-9, 25e-9, 50e-9, 100e-9,
                                          250e-9, 500e-9, 1e-6, 2.5e-6, 5e-6,
                                          10e-6, 25e-6, 50e-6, 100e-6, 250e-6,
                                          500e-6, 1e-3, 2.5e-3, 5e-3, 10e-3,
                                          25e-3, 50e-3, 100e-3, 250e-3, 500e-3,
                                          1, 2.5, 5, 10, 25, 50))

        # channel-specific parameters
        channels = ChannelList(self,
                               "ScopeChannels",
                               TPS2012Channel,
                               snapshotable=False)
        for ch_num in range(1, 3):
            ch_name = f"ch{ch_num}"
            channel = TPS2012Channel(self, ch_name, ch_num)
            channels.append(channel)
            self.add_submodule(ch_name, channel)
        self.add_submodule("channels", channels.to_channel_tuple())

        # Necessary settings for parsing the binary curve data
        self.visa_handle.encoding = 'latin-1'
        log.info('Set VISA encoding to latin-1')
        self.write('DATa:ENCdg RPBinary')
        log.info('Set TPS2012 data encoding to RPBinary' +
                 ' (Positive Integer Binary)')
        self.write('DATa:WIDTh 2')
        log.info('Set TPS2012 data width to 2')