def _connect(self) -> None: """Connects the device to the data server. Instantiates the device controller from :mod:`zhinst-toolkit`, sets up the data server and connects the device the data server. This method is called from `__init__` of the :class:`BaseInstrument` class. """ self._controller = tk.HDAWG( self._name, self._serial, interface=self._interface, host=self._host, port=self._port, api=self._api, ) self._controller.setup() self._controller.connect_device(nodetree=False) self.connect_message() self._get_nodetree_dict() # initialize ChannelList of AWGs channel_list = ChannelList(self, "awgs", AWG) for i in range(4): channel_list.append(AWG(f"awg-{i}", i, self, self._controller)) channel_list.lock() self.add_submodule("awgs", channel_list)
def _init_awg_channels(self): # initialize ChannelList of AWGs channel_list = ChannelList(self, "awgs", AWG) for i in range(4): channel_list.append(AWG(f"awg-{i}", i, self, self._controller)) channel_list.lock() self.add_submodule("awgs", channel_list)
def _init_readout_channels(self): # init submodules for ReadoutChannels channel_list = ChannelList(self, "channels", Channel) for i in range(10): channel_list.append(Channel(f"ch-{i}", i, self, self._controller)) channel_list.lock() self.add_submodule("channels", channel_list)
def _init_qachannels(self): # init submodules for QAChannels num_qachannels = self._controller.num_qachannels() channel_list = ChannelList(self, "qachannels", QAChannel) for i in range(num_qachannels): channel_list.append( QAChannel(f"qachannel-{i}", i, self, self._controller)) channel_list.lock() self.add_submodule("qachannels", channel_list)
def __init__(self, name, address, silent=False, **kwargs): """ Args: name (string): The name of the instrument used internally by QCoDeS. Must be unique. address (string): The VISA resource name. silent (Optional[bool]): If True, no connect message is printed. """ warnings.warn( "This driver is old and will be removed " "from QCoDeS soon. Please use the " "WaveformGenerator_33XXX from the file " "instrument_drivers/Keysight/KeysightAgilent_33XXX" " instead.", UserWarning) super().__init__(name, address, **kwargs) channels = ChannelList(self, "Channels", KeysightChannel, snapshotable=False) for i in range(1, 3): channel = KeysightChannel(self, 'ch{}'.format(i), i) channels.append(channel) channels.lock() self.add_submodule('channels', channels) self.add_parameter('sync_source', label='Source of sync function', set_cmd='OUTPut:SYNC:SOURce {}', get_cmd='OUTPut:SYNC:SOURce?', val_mapping={ 1: 'CH1', 2: 'CH2' }, vals=vals.Enum(1, 2)) self.add_parameter('sync_output', label='Sync output state', set_cmd='OUTPut:SYNC {}', get_cmd='OUTPut:SYNC?', val_mapping={ 'ON': 1, 'OFF': 0 }, vals=vals.Enum('ON', 'OFF')) self.add_function('force_trigger', call_cmd='*TRG') self.add_function('sync_channel_phases', call_cmd='PHAS:SYNC') if not silent: self.connect_message()
def _init_integrations(self): # init submodules for Integration Units num_integrations = self._readout.device.num_integrations_per_qachannel( ) channel_list = ChannelList(self, "integrations", Integration) for i in range(num_integrations): channel_list.append( Integration(f"integration-{i}", i, self, self._readout)) channel_list.lock() self.add_submodule("integrations", channel_list) self._readout._init_integrations()
def __init__(self, name, address, **kwargs): super().__init__(name, address, 5, '\r\n', **kwargs) # configure the port if 'ASRL' not in address: self.visa_handle.baud_rate = 38400 # USB has no baud rate parameter self.visa_handle.stop_bits = pyvisa.constants.StopBits.one self.visa_handle.parity = pyvisa.constants.Parity.none self.visa_handle.read_termination = '\r\n' self.parameters.pop('IDN') # Get rid of this parameter # for security check the ID from the device self.idn = self.ask("ver") log.debug("Main version:", self.idn) if not self.idn.startswith("attocube ANC300"): raise RuntimeError("Invalid device ID found: " + str(self.idn)) # Now request all serial numbers of the axis modules. The first 6 chars are the id # of the module type. This will be used to enable special parameters. # Instantiate the axis channels only for available axis axischannels = ChannelList(self, "Anc300Channels", Anc300Axis, snapshotable=False) for ax in range(1, 7 + 1): try: tmp = self.ask('getser {}'.format(ax)) name = 'axis{}'.format(ax) axischan = Anc300Axis(self, name, ax, tmp[:6]) axischannels.append(axischan) self.add_submodule(name, axischan) except: pass axischannels.lock() self.add_submodule('axis_channels', axischannels) # instantiate the trigger channels even if they could not be tested triggerchannels = ChannelList(self, "Anc300Trigger", Anc300TriggerOut, snapshotable=False) for ax in [1, 2, 3]: name = 'trigger{}'.format(ax) trigchan = Anc300TriggerOut(self, name, ax) triggerchannels.append(trigchan) self.add_submodule(name, trigchan) triggerchannels.lock() self.add_submodule('trigger_channels', triggerchannels)
def __init__(self, name, address, port=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) channels.lock() self.add_submodule('channels', channels) self.connect_message()
def _add_submodules_recursively(self, parent, treedict: Dict) -> None: """ Recursively add submodules (ZINodes) for each node in the ZI node tree. At the leaves create a parameter. Create a ChannelList as submodules whenever a node is enumerated, e.g. 'dev8030/sigouts/*/on'. Arguments: parent (InstrumentChannel): parent QCoDeS object, either Instrument(-Channel) or ZINode treedict (dict): dictionary specifying the (sub-)tree of the ZI node hirarchy """ for key, value in treedict.items(): if all(isinstance(k, int) for k in value.keys()): # if enumerated node if "Node" in list(value.values())[0].keys(): # if at leave, don't create ChannelList but parameter with "{key}{i}" for k in value.keys(): self._add_parameter_from_dict(parent, f"{key}{k}", value[k]) else: # else, create ChannelList to hold all enumerated ZINodes channel_list = ChannelList(parent, key, ZINode) for k in value.keys(): ch_name = f"{key}{k}" ch = ZINode(parent, ch_name) channel_list.append(ch) self._add_submodules_recursively(ch, treedict[key][k]) channel_list.lock() parent.add_submodule(key, channel_list) else: # if not enumerated ZINode if "Node" in value.keys(): # if at leave add a parameter to the node self._add_parameter_from_dict(parent, key, value) else: # if not at leave, create ZINode as submodule module = ZINode(parent, key) parent.add_submodule(key, module) self._add_submodules_recursively(module, treedict[key])
def add_channels(self): channels = ChannelList( self, "Channels", self.CHANNEL_CLASS, snapshotable=False) _chanlist = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'] self._deprecated_attributes = { 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 channels.lock() self.add_submodule('channels', channels)
def __init__(self, name: str, library: ANC350v3Lib, inst_no: int = 0): super().__init__(name) if isinstance(library, ANC350v4Lib): self._version_no = 4 elif isinstance(library, ANC350v3Lib): self._version_no = 3 else: raise NotImplementedError( "Only version 3 and 4 of ANC350's driver-DLL are currently " "supported") self._lib = library self._device_no = inst_no self._device_handle = self._lib.connect(inst_no) axischannels = ChannelList(self, "Anc350Axis", Anc350Axis) for nr, axis in enumerate(['x', 'y', 'z']): axis_name = f"{axis}_axis" axischannel = Anc350Axis(parent=self, name=axis_name, axis=nr) axischannels.append(axischannel) self.add_submodule(axis_name, axischannel) axischannels.lock() self.add_submodule("axis_channels", axischannels)
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 }) self.add_parameter(name='fast_voltage_set', label='fast voltage set', get_cmd=None, set_cmd=None, vals=vals.Bool(), initial_value=False, docstring=""""Deprecated with no functionality""") # 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, 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) channels.lock() self.add_submodule('channels', channels)
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') # 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) data_channels.lock() self.add_submodule("data_channels", data_channels) # 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()
def __init__(self, name: str, address: str, num_channels: int, timeout: float = 10, **kwargs) -> None: """ Args: name: The name used internally by QCoDeS in the DataSet address: The VISA resource name of the instrument timeout: The VISA timeout time (in seconds) num_channels: Number of channels on the AWG """ self.num_channels = num_channels super().__init__(name, address, timeout=timeout, terminator='\n', **kwargs) # The 'model' value begins with 'AWG' self.model = self.IDN()['model'][3:] if self.model not in ['70001A', '70002A', '5208']: raise ValueError('Unknown model type: {}. Are you using ' 'the right driver for your instrument?' ''.format(self.model)) self.add_parameter('current_directory', label='Current file system directory', set_cmd='MMEMory:CDIRectory "{}"', get_cmd='MMEMory:CDIRectory?', vals=vals.Strings()) self.add_parameter('mode', label='Instrument operation mode', set_cmd='INSTrument:MODE {}', get_cmd='INSTrument:MODE?', vals=vals.Enum('AWG', 'FGEN')) ################################################## # Clock parameters self.add_parameter('sample_rate', label='Clock sample rate', set_cmd='CLOCk:SRATe {}', get_cmd='CLOCk:SRATe?', unit='Sa/s', get_parser=float, vals=SRValidator(self)) self.add_parameter('clock_source', label='Clock source', set_cmd='CLOCk:SOURce {}', get_cmd='CLOCk:SOURce?', val_mapping={ 'Internal': 'INT', 'Internal, 10 MHZ ref.': 'EFIX', 'Internal, variable ref.': 'EVAR', 'External': 'EXT' }) self.add_parameter('clock_external_frequency', label='External clock frequency', set_cmd='CLOCk:ECLock:FREQuency {}', get_cmd='CLOCk:ECLock:FREQuency?', get_parser=float, unit='Hz', vals=vals.Numbers(6.25e9, 12.5e9)) # We deem 2 channels too few for a channel list if self.num_channels > 2: chanlist = ChannelList(self, 'Channels', AWGChannel, snapshotable=False) for ch_num in range(1, num_channels + 1): ch_name = 'ch{}'.format(ch_num) channel = AWGChannel(self, ch_name, ch_num) self.add_submodule(ch_name, channel) if self.num_channels > 2: chanlist.append(channel) if self.num_channels > 2: chanlist.lock() self.add_submodule('channels', chanlist) # Folder on the AWG where to files are uplaoded by default self.wfmxFileFolder = "\\Users\\OEM\\Documents" self.seqxFileFolder = "\\Users\\OEM\Documents" self.current_directory(self.wfmxFileFolder) self.connect_message()
def __init__(self, name, address, update_currents=False, **kwargs): """ Instantiates the instrument. Args: name (str): The instrument name used by qcodes address (str): The VISA name of the resource update_currents (bool): 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 # 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) channels.lock() self.add_submodule('channels', channels) # 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')
def __init__(self, name, address, silent=False, **kwargs): """ Args: name (string): The name of the instrument used internally by QCoDeS. Must be unique. address (string): The VISA resource name. silent (Optional[bool]): If True, no connect message is printed. """ super().__init__(name, address, **kwargs) def errorparser(rawmssg): """ Parses the error message. Args: rawmssg (str): The raw return value of 'SYSTem:ERRor?' Returns: tuple (int, str): The error code and the error message. """ code = int(rawmssg.split(',')[0]) mssg = rawmssg.split(',')[1].strip().replace('"', '') return code, mssg channels = ChannelList(self, "Channels", KeysightChannel, snapshotable=False) for i in range(1, 3): channel = KeysightChannel(self, 'ch{}'.format(i), i) channels.append(channel) channels.lock() self.add_submodule('channels', channels) self.add_parameter('sync_source', label='Source of sync function', set_cmd='OUTPut:SYNC:SOURce {}', get_cmd='OUTPut:SYNC:SOURce?', val_mapping={ 1: 'CH1', 2: 'CH2' }, vals=vals.Enum(1, 2)) self.add_parameter('sync_output', label='Sync output state', set_cmd='OUTPut:SYNC {}', get_cmd='OUTPut:SYNC?', val_mapping={ 'ON': 1, 'OFF': 0 }, vals=vals.Enum('ON', 'OFF')) self.add_parameter('error', label='Error message', get_cmd='SYSTem:ERRor?', get_parser=errorparser) self.add_function('force_trigger', call_cmd='*TRG') self.add_function('sync_channel_phases', call_cmd='PHAS:SYNC') if not silent: self.connect_message()
def __init__(self, name, address, timeout=2, **kwargs): """ Initialises the Rigol DS1000 Args: name (str) of the instrument address (string) Visa address for the instrument timeout (float) visa timeout """ super().__init__(name, address, device_clear=False, timeout=timeout, **kwargs) self.connect_message() # 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') #acquire mode parameters self.add_parameter("acquire_type", label='type of aquire being used by oscilloscope', get_cmd=':ACQ:TYPE?', set_cmd='ACQ:TYPE {}', vals=vals.Enum('NORMAL', 'AVERAGE', 'PEAKDETECT')) self.add_parameter("acquire_mode", label="mode of aquisition being used by oscillioscope", get_cmd=':ACQ:MODE?', set_cmd=':ACQ:MODE {}', vals = vals.Enum('RTIM', 'ETIM') ) self.add_parameter("acquire_averages", label="the average number in averages mode", get_cmd=':ACQ:AVER?', set_cmd=':ACQ:AVER {}', vals=vals.Enum('2', '4', '8', '16', '32', '64', '128', '256')) #note to self: aquire sampling rate parameters to go under channel class self.add_parameter("acquire_mem_depth", label='depth of memory being used by oscilloscope', get_cmd=':ACQ:MEMDepth?', set_cmd=':ACQ:MEMDepth {}', vals = vals.Enum('LONG', 'NORM')) #display parameters self.add_parameter("display_type", label='display type between samples, either vector or dot', get_cmd=':DISP:TYPE?', set_cmd=':DISP:TYPE {}', vals = vals.Enum('VECT', 'DOTS')) self.add_parameter("display_grid", label='controls/queries if the oscilloscope display has a grid', get_cmd=':DISP:GRID?', set_cmd=':DISP:GRID {}', vals = vals.Enum('FULL', 'HALF', 'NONE')) self.add_parameter("display_persist", label="controls/queries if the waveform record point persists or refreshes", get_cmd=':DISP:PERS?', set_cmd=':DiSP:PERS {}', vals = vals.Enum('ON', 'OFF')) self.add_parameter("display_mnud", label="timing for menus hiding automatically", get_cmd=':DISP:MNUD?', set_cmd=':DISP:MNUD {}', vals = vals.Enum('1', '2', '5', '10', '20', 'Infinite') ) self.add_parameter("display_mnus", label="status of the menus", get_cmd=':DISP:MNUS?', set_cmd=':DISP:MNUS {}', vals = vals.Enum('ON', 'OFF')) #note to self - add display clear parameter self.add_parameter("display_brightness", label="set and get the brightness of the grid for the oscilloscope", get_cmd=':DISP:BRIG?', set_cmd=':DISP:BRIG {}', get_parser=int, vals=vals.Ints(0,32)) self.add_parameter("display_intensity", label="set the brightness of the waveform", get_cmd=':DISP:INT?', set_cmd=':DISP:INT {}', get_parser=int, vals=vals.Ints(0,32)) # Channel parameters channels = ChannelList(self, "Channels", RigolDS1000Channel, snapshotable=False) for channel_number in [1, 2]: channel = RigolDS1000Channel(self, "ch{}".format(channel_number), channel_number) channels.append(channel) for channel_number in ['MATH', 'FFT']: channel = RigolDS1000Channel(self, "ch_{}".format(channel_number), channel_number) channels.append(channel) channels.lock() self.add_submodule('channels', channels) #timebase parameters self.add_parameter("time_base_mode", label="the scan mode of the horizontal time base", get_cmd=":TIM:MODE?", set_cmd=":TIM:MODE {}", vals = vals.Enum('MAIN', 'DEL')) #note to self, decide how to deal with timebase offset parameter. self.add_parameter("time_base_offset", label="controls the main and delayed mode offset", get_cmd=":TIM:OFFS?", set_cmd=":TIM:OFFS {}", get_parser=float, unit="s") self.add_parameter("time_base_scale", label="the scale of the horizontal time base", get_cmd=":TIM:SCAL?", set_cmd=":TIM:SCAL {}", get_parser=float, unit="s/div") self.add_parameter("time_base_format", label="the format of the time base", get_cmd=":TIM:FORM?", set_cmd=":TIM:FORM {}", vals=vals.Enum('X-Y', 'Y-T', 'SCANNING') ) #trigger commands self.add_parameter("trigger_mode", label="sets and queries the trigger mode", get_cmd=":TRIG:MODE?", set_cmd=":TRIG:MODE {}", vals = vals.Enum('EDGE', 'PULSE', 'VIDEO', 'SLOPE', 'PATTERN','DURATION', 'ALTERNATION') ) self.add_parameter("trigger_source", label="sets and queries the trigger source", get_cmd = ":TRIG:{}:SOUR?".format(self.trigger_mode()), set_cmd = ":TRIG:{}:SOUR {}".format(self.trigger_mode(), "{}") #get_cmd = self.source_get_cmd, #set_cmd = self.source_set_cmd, ) self.add_parameter("trigger_level", label="sets and queries the trigger level", get_cmd=":TRIG:{}:LEV?".format(self.trigger_mode()), set_cmd=":TRIG:{}:LEV {}".format(self.trigger_mode(), "{}"), #get_cmd = self.level_get_cmd, get_parser = float, #set_cmd = self.level_set_cmd, unit = "V" #vals = vals.permissiveInts(-6*#vertical scale, 6*#vertical scale()) ) self.add_parameter("trigger_sweep", label="sets and queries the trigger sweep", get_cmd =":TRIG:{}:SWE?".format(self.trigger_mode()), set_cmd =":TRIG:{}:SWE {}".format(self.trigger_mode(), "{}"), #get_cmd = self.sweep_get_cmd, #set_cmd = self.sweep_set_cmd, vals = vals.Enum("AUTO","NORM","SING") ) self.add_parameter("trigger_coupling", label="sets and queries the coupling", get_cmd = ":TRIG:{}:COUP?".format(self.trigger_mode()), set_cmd = ":TRIG:{}:COUP {}".format(self.trigger_mode(), "{}"), vals = vals.Enum("DC","AC","HF","LF") ) self.add_parameter("trigger_holdoff", label="sets and queries the trigger holdoff", get_cmd = ":TRIG:HOLD?", set_cmd = ":TRIG:HOLD {}", get_parser = float, unit = 's' ) # Waveform self.add_parameter("waveform_points_mode", label="Number of the waveform points", get_cmd=":WAVEFORM:POINTS:MODE?", set_cmd=":WAVEFORM:POINTS:MODE {}", vals = vals.Enum("NORM","MAX","RAW"), get_parser=str, )
def __init__(self,name:str, address:str, num_chans:int=16, init_start:bool=False, synchronous_enable:bool=True, synchronous_delay:float=1, synchronous_threshold:float=1e-5, **kwargs: Any) -> None: """ Instantiate 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: 16 init_start: If true set all channels to 0V, 1.2V range and switch then on. synchronous_enable: If true, block the communication until the set voltage is reached. The communication is block through a simple while loop with a waiting time "synchronous_delay" at each iteration until the set voltage and the measured voltage difference is below "synchronous_threshold". synchronous_delay: Time between to voltage measurement in second. synchronous_threshold: Threshold to unblock communication in volt. Returns: ITest object """ super().__init__(name, address=address, terminator='\n', device_clear=False, **kwargs) self.idn = self.get_idn() self.num_chans = num_chans self.chan_range = range(1,self.num_chans+1) # Create the channels channels = ChannelList(parent=self, name='Channels', chan_type=iTestChannel, multichan_paramclass=iTestMultiChannelParameter) for i in self.chan_range: channel = iTestChannel(self, name='chan{:02}'.format(i), chan_num=i) channel.synchronous_enable(synchronous_enable) channel.synchronous_delay(synchronous_delay) channel.synchronous_threshold(synchronous_threshold) channels.append(channel) self.add_submodule('ch{:02}'.format(i),channel) channels.lock() self.add_submodule('channels',channels) if init_start: for channel in self.channels: channel.v.set(0) channel.v_range(1.2) channel.start() self.connect_message()
def _connect(self) -> None: """Connects the device to the data server. Instantiates the device controller from :mod:`zhinst-toolkit`, sets up the data server and connects the device the data server. This method is called from `__init__` of the :class:`BaseInstrument` class. """ self._controller = tk.UHFQA( self._name, self._serial, interface=self._interface, host=self._host, port=self._port, api=self._api, ) self._controller.setup() self._controller.connect_device(nodetree=False) self.connect_message() self._get_nodetree_dict() # init submodules for ReadoutChannels and AWG channel_list = ChannelList(self, "channels", Channel) for i in range(10): channel_list.append(Channel(f"ch-{i}", i, self, self._controller)) channel_list.lock() self.add_submodule("channels", channel_list) self.add_submodule("awg", AWG("awg", self, self._controller)) # add custom parameters as QCoDeS parameters self.add_parameter( "crosstalk_matrix", docstring= "The 10x10 crosstalk suppression matrix that multiplies the 10 signal paths. Can be set only partially.", get_cmd=self._controller.crosstalk_matrix, set_cmd=self._controller.crosstalk_matrix, label="Crosstalk Matrix", ) sources = [ "Crosstalk", "Integration", "Threshold", "Crosstalk Correlation", "Threshold Correlation", "Rotation", ] self.add_parameter( "result_source", docstring= f"The signal source for QA Results. Has to be one of {sources}.", get_cmd=self._controller.result_source, set_cmd=self._controller.result_source, label="Result Source", vals=vals.Enum(*sources), ) self.add_parameter( "integration_time", docstring= "The integration time used for demodulation in seconds. Can be up to 2.27 us when using weighted integration and up to 50 us in spectroscopy mode.", get_cmd=self._controller.integration_time, set_cmd=self._controller.integration_time, label="Integration Time", vals=vals.Numbers(0, 50e-6), ) self.add_parameter( "averaging_mode", docstring=self._controller.averaging_mode._description, get_cmd=self._controller.averaging_mode, set_cmd=self._controller.averaging_mode, label="Averaging Mode", vals=vals.Enum("Cyclic", "Sequential"), )