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