def __init__(self, name, address, **kwargs): super().__init__(name, address, **kwargs) # Reference and phase self.add_parameter( 'phase', label='Phase', get_cmd='PHAS?', get_parser=float, # rawv - > float(rawv) set_cmd='PHAS {:.2f}', unit='deg', vals=Numbers(min_value=-360, max_value=360)) self.add_parameter('reference_source', label='Reference source', get_cmd='FMOD?', set_cmd='FMOD {}', val_mapping={ 'external': 0, 'internal': 1, }, vals=Enum('external', 'internal')) self.add_parameter('frequency', label='Frequency', get_cmd='FREQ?', get_parser=float, set_cmd='FREQ {:.4f}', unit='Hz', vals=Numbers(min_value=25e3, max_value=200e6)) # not implemented in rs844 # self.add_parameter('ext_trigger', # label='External trigger', # get_cmd='RSLP?', # set_cmd='RSLP {}', # val_mapping={ # 'sine': 0, # 'TTL rising': 1, # 'TTL falling': 2, # }) #2f mode, whatever that is self.add_parameter('secondharmonic', label='Secondharmonic', get_cmd='HARM?', set_cmd='HARM {}', val_mapping={ 'OFF': 0, 'ON': 1, }, vals=Enum('OFF', 'ON')) # can't cahnge amplitude from gpib? # self.add_parameter('amplitude', # label='Amplitude', # get_cmd='SLVL?', # get_parser=float, # set_cmd='SLVL {:.3f}', # unit='V', # vals=Numbers(min_value=0.004, max_value=5.000)) # # Input and filter # not implemented in rs844 # self.add_parameter('input_config', # label='Input configuration', # get_cmd='ISRC?', # get_parser=self._get_input_config, # set_cmd='ISRC {}', # set_parser=self._set_input_config, # vals=Enum(*self._INPUT_CONFIG_TO_N.keys())) # self.add_parameter('input_shield', # label='Input shield', # get_cmd='IGND?', # set_cmd='IGND {}', # val_mapping={ # 'float': 0, # 'ground': 1, # }) # self.add_parameter('input_coupling', # label='Input coupling', # get_cmd='ICPL?', # set_cmd='ICPL {}', # val_mapping={ # 'AC': 0, # 'DC': 1, # }) # self.add_parameter('notch_filter', # label='Notch filter', # get_cmd='ILIN?', # set_cmd='ILIN {}', # val_mapping={ # 'off': 0, # 'line in': 1, # '2x line in': 2, # 'both': 3, # }) # Gain and time constant self.add_parameter(name='sensitivity', label='Sensitivity', get_cmd='SENS?', set_cmd='SENS {:d}', get_parser=self._get_sensitivity, set_parser=self._set_sensitivity) self.add_parameter('relmode', label='Relmode', get_cmd='RMOD?', set_cmd='RMOD {}', val_mapping={ 'OFF': 0, 'ON': 1, }) self.add_parameter('time_constant', label='Time constant', get_cmd='OFLT?', set_cmd='OFLT {}', unit='s', val_mapping={ 0.0001: 0, 0.0003: 1, 0.001: 2, 0.003: 3, 0.01: 4, 0.03: 5, 0.1: 6, 0.3: 7, 1: 8, 3: 9, 10: 10, 30: 11, 100: 12, 300: 13, 1000.0: 14, 3000.0: 15, 10000.0: 16, 30000.0: 17 }) self.add_parameter('filter_slope', label='Filter slope', get_cmd='OFSL?', set_cmd='OFSL {}', unit='dB/oct', val_mapping={ 0: 0, 6: 1, 12: 2, 18: 3, 24: 4 }) # not implemented # self.add_parameter('sync_filter', # label='Sync filter', # get_cmd='SYNC?', # set_cmd='SYNC {}', # val_mapping={ # 'off': 0, # 'on': 1, # }) # not implemented in rs844 # def parse_offset_get(s): # parts = s.split(',') # return float(parts[0]), int(parts[1]) # # TODO: Parameters that can be set with multiple arguments # # For the OEXP command for example two arguments are needed # self.add_parameter('X_offset', # get_cmd='OEXP? 1', # get_parser=parse_offset_get) # self.add_parameter('Y_offset', # get_cmd='OEXP? 2', # get_parser=parse_offset_get) # self.add_parameter('R_offset', # get_cmd='OEXP? 3', # get_parser=parse_offset_get) # Aux input/output # only two aux for i in [1, 2]: self.add_parameter('aux_in{}'.format(i), label='Aux input {}'.format(i), get_cmd='AUXI? {}'.format(i), get_parser=float, unit='V') self.add_parameter('aux_out{}'.format(i), label='Aux output {}'.format(i), get_cmd='AUXO? {}'.format(i), get_parser=float, set_cmd='AUXV {0}, {{}}'.format(i), unit='V') # Setup self.add_parameter('output_interface', label='Output interface', get_cmd='OUTX?', set_cmd='OUTX {}', val_mapping={ 'RS232': '0\n', 'GPIB': '1\n', }) # Channel setup for ch in range(1, 2): # detailed validation and mapping performed in set/get functions self.add_parameter('ch{}_ratio'.format(ch), label='Channel {} ratio'.format(ch), get_cmd=partial(self._get_ch_ratio, ch), set_cmd=partial(self._set_ch_ratio, ch), vals=Strings()) self.add_parameter('ch{}_display'.format(ch), label='Channel {} display'.format(ch), get_cmd=partial(self._get_ch_display, ch), set_cmd=partial(self._set_ch_display, ch), vals=Strings()) self.add_parameter('ch{}_databuffer'.format(ch), channel=ch, parameter_class=ChannelBuffer) # Data transfer self.add_parameter('X', get_cmd='OUTP? 1', get_parser=float, unit='V') self.add_parameter('Y', get_cmd='OUTP? 2', get_parser=float, unit='V') self.add_parameter('R', get_cmd='OUTP? 3', get_parser=float, unit='V') self.add_parameter('P', get_cmd='OUTP? 4', get_parser=float, unit='deg') # Data buffer settings self.add_parameter('buffer_SR', label='Buffer sample rate', get_cmd='SRAT ?', set_cmd=self._set_buffer_SR, unit='Hz', val_mapping={ 62.5e-3: 0, 0.125: 1, 0.250: 2, 0.5: 3, 1: 4, 2: 5, 4: 6, 8: 7, 16: 8, 32: 9, 64: 10, 128: 11, 256: 12, 512: 13, 'Trigger': 14 }, get_parser=int) self.add_parameter('buffer_acq_mode', label='Buffer acquistion mode', get_cmd='SEND ?', set_cmd='SEND {}', val_mapping={ 'single shot': 0, 'loop': 1 }, get_parser=int) self.add_parameter('buffer_trig_mode', label='Buffer trigger start mode', get_cmd='TSTR ?', set_cmd='TSTR {}', val_mapping={ 'ON': 1, 'OFF': 0 }, get_parser=int) self.add_parameter('buffer_npts', label='Buffer number of stored points', get_cmd='SPTS ?', get_parser=int) # Auto functions self.add_function('auto_gain', call_cmd='AGAN') #not implemented #self.add_function('auto_reserve', call_cmd='ARSV') self.add_function('auto_phase', call_cmd='APHS') #FIXME auto offset works differently self.add_function('auto_offset', call_cmd='AOFF {0}', args=[Enum(1, 2, 3)]) # 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') self.add_function('send_trigger', call_cmd='TRIG', docstring=("Send a software trigger. " "This command has the same effect as a " "trigger at the rear panel trigger" " input.")) self.add_function('buffer_start', call_cmd='STRT', docstring=("The buffer_start command starts or " "resumes data storage. buffer_start" " is ignored if storage is already in" " progress.")) self.add_function('buffer_pause', call_cmd='PAUS', docstring=("The buffer_pause command pauses data " "storage. If storage is already paused " "or reset then this command is ignored.")) self.add_function('buffer_reset', call_cmd='REST', docstring=("The buffer_reset command resets the data" " buffers. The buffer_reset command can " "be sent at any time - any storage in " "progress, paused or not, will be reset." " This command will erase the data " "buffer.")) # Initialize the proper units of the outputs and sensitivities # not implemented in sr844 # self.input_config() # start keeping track of buffer setpoints self._buffer1_ready = False self._buffer2_ready = False self.connect_message()
def __init__(self, parent, name, channel): super().__init__(parent, name) self._channel = channel # Add the various channel parameters self.add_parameter('temperature', parameter_class=Parameter, initial_value=0, label=f"Temperature_{channel}", unit='K', vals=Numbers(0, 300), get_cmd=None, set_cmd=None) self.add_parameter(name='dummy_multi_parameter', parameter_class=MultiSetPointParam) self.add_parameter(name='dummy_scalar_multi_parameter', parameter_class=MultiScalarParam) self.add_parameter(name='dummy_2d_multi_parameter', parameter_class=Multi2DSetPointParam) self.add_parameter(name='dummy_2d_multi_parameter_2', parameter_class=Multi2DSetPointParam2Sizes) self.add_parameter(name='dummy_array_parameter', parameter_class=ArraySetPointParam) self.add_parameter(name='dummy_complex_array_parameter', parameter_class=ComplexArraySetPointParam) self.add_parameter('dummy_start', initial_value=0, unit='some unit', label='f start', vals=Numbers(0, 1e3), get_cmd=None, set_cmd=None) self.add_parameter( "dummy_stop", initial_value=100, unit="some unit", label="f stop", vals=Numbers(1, 1e3), get_cmd=None, set_cmd=None, ) self.add_parameter( "dummy_n_points", initial_value=101, unit="", vals=Numbers(1, 1e3), get_cmd=None, set_cmd=None, ) self.add_parameter('dummy_start_2', initial_value=0, unit='some unit', label='f start', vals=Numbers(0, 1e3), get_cmd=None, set_cmd=None) self.add_parameter( "dummy_stop_2", initial_value=100, unit="some unit", label="f stop", vals=Numbers(1, 1e3), get_cmd=None, set_cmd=None, ) self.add_parameter( "dummy_n_points_2", initial_value=101, unit="", vals=Numbers(1, 1e3), get_cmd=None, set_cmd=None, ) self.add_parameter('dummy_sp_axis', unit='some unit', label='Dummy sp axis', parameter_class=GeneratedSetPoints, startparam=self.dummy_start, stopparam=self.dummy_stop, numpointsparam=self.dummy_n_points, vals=Arrays(shape=(self.dummy_n_points, ))) self.add_parameter('dummy_sp_axis_2', unit='some unit', label='Dummy sp axis', parameter_class=GeneratedSetPoints, startparam=self.dummy_start_2, stopparam=self.dummy_stop_2, numpointsparam=self.dummy_n_points_2, vals=Arrays(shape=(self.dummy_n_points_2, ))) self.add_parameter(name='dummy_parameter_with_setpoints', label='Dummy Parameter with Setpoints', unit='some other unit', setpoints=(self.dummy_sp_axis, ), vals=Arrays(shape=(self.dummy_n_points, )), parameter_class=DummyParameterWithSetpoints1D) self.add_parameter(name='dummy_parameter_with_setpoints_2d', label='Dummy Parameter with Setpoints', unit='some other unit', setpoints=(self.dummy_sp_axis, self.dummy_sp_axis_2), vals=Arrays(shape=(self.dummy_n_points, self.dummy_n_points_2)), parameter_class=DummyParameterWithSetpoints2D) self.add_parameter(name='dummy_text', label='Dummy text', unit='text unit', initial_value='thisisastring', set_cmd=None, vals=Strings()) self.add_parameter(name='dummy_complex', label='Dummy complex', unit='complex unit', initial_value=1 + 1j, set_cmd=None, vals=ComplexNumbers()) self.add_parameter(name='dummy_parameter_with_setpoints_complex', label='Dummy Parameter with Setpoints complex', unit='some other unit', setpoints=(self.dummy_sp_axis, ), vals=Arrays(shape=(self.dummy_n_points, ), valid_types=(np.complexfloating, )), parameter_class=DummyParameterWithSetpointsComplex) self.add_function(name='log_my_name', call_cmd=partial(log.debug, f'{name}'))
def test_bad(self): for args in [[], [1], [Strings(), True]]: with self.assertRaises(TypeError): MultiType(*args)
def __init__(self, name: str, address: str, **kwargs: Any): super().__init__(name, address, terminator='\n', **kwargs) self.add_parameter('rangev', get_cmd='SENS:VOLT:RANG?', get_parser=float, set_cmd='SOUR:VOLT:RANG {:f}', label='Voltage range') self.add_parameter('rangei', get_cmd='SENS:CURR:RANG?', get_parser=float, set_cmd='SOUR:CURR:RANG {:f}', label='Current range') self.add_parameter('compliancev', get_cmd='SENS:VOLT:PROT?', get_parser=float, set_cmd='SENS:VOLT:PROT {:f}', label='Voltage Compliance') self.add_parameter('compliancei', get_cmd='SENS:CURR:PROT?', get_parser=float, set_cmd='SENS:CURR:PROT {:f}', label='Current Compliance') self.add_parameter('volt', get_cmd=self._get_read_output_protected, get_parser=self._volt_parser, set_cmd=':SOUR:VOLT:LEV {:.8f}', label='Voltage', unit='V', docstring="Sets voltage in 'VOLT' mode. " "Get returns measured voltage if " "sensing 'VOLT' otherwise it returns " "setpoint value. " "Note that it is an error to read voltage with " "output off") self.add_parameter('ramp_voltage', get_cmd=self._get_read_output_protected, get_parser=self._volt_parser, set_cmd=self.ramp_voltage_to, label='Voltage', unit='V') self.add_parameter( 'ramp_voltage_step', label='Step size for ramp_voltage', unit='V', initial_value=10e-3, get_cmd=None, set_cmd=None, ) self.add_parameter( 'ramp_voltage_delay', label='Delay for ramp_voltage', unit='s', initial_value=0, get_cmd=None, set_cmd=None, ) self.add_parameter('curr', get_cmd=self._get_read_output_protected, get_parser=self._curr_parser, set_cmd=':SOUR:CURR:LEV {:.8f}', label='Current', unit='A', docstring="Sets current in 'CURR' mode. " "Get returns measured current if " "sensing 'CURR' otherwise it returns " "setpoint value. " "Note that it is an error to read current with " "output off") self.add_parameter('mode', vals=Enum('VOLT', 'CURR'), get_cmd=':SOUR:FUNC?', set_cmd=self._set_mode_and_sense, label='Mode') self.add_parameter('sense', vals=Strings(), get_cmd=':SENS:FUNC?', set_cmd=':SENS:FUNC "{:s}"', label='Sense mode') self.add_parameter('output', set_cmd=':OUTP:STAT {}', get_cmd=':OUTP:STAT?', val_mapping=create_on_off_val_mapping(on_val="1", off_val="0")) self.add_parameter('nplcv', get_cmd='SENS:VOLT:NPLC?', get_parser=float, set_cmd='SENS:VOLT:NPLC {:f}', label='Voltage integration time') self.add_parameter('nplci', get_cmd='SENS:CURR:NPLC?', get_parser=float, set_cmd='SENS:CURR:NPLC {:f}', label='Current integration time') self.add_parameter( 'resistance', get_cmd=self._get_read_output_protected, get_parser=self._resistance_parser, label='Resistance', unit='Ohm', docstring="Measure resistance from current and voltage " "Note that it is an error to read current " "and voltage with output off") self.write(':TRIG:COUN 1;:FORM:ELEM VOLT,CURR') # This line sends 2 commands to the instrument: # ":TRIG:COUN 1" sets the trigger count to 1 so that each READ? returns # only 1 measurement result. # ":FORM:ELEM VOLT,CURR" sets the output string formatting of the the # Keithley 2400 to return "{voltage}, {current}". # Default value on instrument reset is "VOLT, CURR, RES, TIME, STATUS"; # however, resistance, status, and time are unused in this driver and # so are omitted. # These commands do not reset the instrument but do the minimal amount # to ensure that voltage and current parameters can be read from the # instrument, in the event that output formatting of the instrument was # previously changed to some other unknown state. self.connect_message()
def __init__(self, name: str, address: str, **kwargs) -> None: super().__init__(name, address, terminator='\n', **kwargs) idn = self.IDN.get() self.model = idn['model'] NPLC_list = { '34401A': [0.02, 0.2, 1, 10, 100], '34410A': [0.006, 0.02, 0.06, 0.2, 1, 2, 10, 100], '34411A': [0.001, 0.002, 0.006, 0.02, 0.06, 0.2, 1, 2, 10, 100] }[self.model] self._resolution_factor = { '34401A': [1e-4, 1e-5, 3e-6, 1e-6, 3e-7], '34410A': [6e-06, 3e-06, 1.5e-06, 7e-07, 3e-07, 2e-07, 1e-07], '34411A': [ 3e-05, 1.5e-05, 6e-06, 3e-06, 1.5e-06, 7e-07, 3e-07, 2e-07, 1e-07, 3e-08 ] }[self.model] self.add_parameter('resolution', get_cmd='VOLT:DC:RES?', get_parser=float, set_cmd=self._set_resolution, label='Resolution', unit='V') self.add_parameter('volt', get_cmd='READ?', label='Voltage', get_parser=float, unit='V') self.add_parameter('fetch', get_cmd='FETCH?', label='Voltage', get_parser=float, unit='V', snapshot_get=False, docstring=('Reads the data you asked for, i.e. ' 'after an `init_measurement()` you can ' 'read the data with fetch.\n' 'Do not call this when you did not ask ' 'for data in the first place!')) self.add_parameter('NPLC', get_cmd='VOLT:NPLC?', get_parser=float, set_cmd=self._set_nplc, vals=Enum(*NPLC_list), label='Integration time', unit='NPLC') self.add_parameter('terminals', get_cmd='ROUT:TERM?') self.add_parameter('range_auto', get_cmd='VOLT:RANG:AUTO?', set_cmd='VOLT:RANG:AUTO {:d}', val_mapping={ 'on': 1, 'off': 0 }) self.add_parameter('range', get_cmd='SENS:VOLT:DC:RANG?', get_parser=float, set_cmd='SENS:VOLT:DC:RANG {:f}', vals=Enum(0.1, 1.0, 10.0, 100.0, 1000.0)) if self.model in ['34401A']: self.add_parameter('display_text', get_cmd='DISP:TEXT?', set_cmd='DISP:TEXT "{}"', vals=Strings()) elif self.model in ['34410A', '34411A']: self.add_parameter('display_text', get_cmd='DISP:WIND1:TEXT?', set_cmd='DISP:WIND1:TEXT "{}"', vals=Strings()) self.add_parameter('display_text_2', get_cmd='DISP:WIND2:TEXT?', set_cmd='DISP:WIND2:TEXT "{}"', vals=Strings()) self.connect_message()
def test_valid_values(self): val = Strings() for vval in val.valid_values: val.validate(vval)
def __init__(self, name, address, **kwargs): super().__init__(name, address, terminator='\n', **kwargs) self.add_parameter('rangev', get_cmd='SENS:VOLT:RANG?', get_parser=float, set_cmd='SOUR:VOLT:RANG {:f}', label='Voltage range') self.add_parameter('rangei', get_cmd='SENS:CURR:RANG?', get_parser=float, set_cmd='SOUR:CURR:RANG {:f}', label='Current range') self.add_parameter('compliancev', get_cmd='SENS:VOLT:PROT?', get_parser=float, set_cmd='SENS:VOLT:PROT {:f}', label='Voltage Compliance') self.add_parameter('compliancei', get_cmd='SENS:CURR:PROT?', get_parser=float, set_cmd='SENS:CURR:PROT {:f}', label='Current Compliance') self.add_parameter('volt', get_cmd=':READ?', get_parser=self._volt_parser, set_cmd=':SOUR:VOLT:LEV {:.8f}', label='Voltage', unit='V') self.add_parameter('curr', get_cmd=':READ?', get_parser=self._curr_parser, set_cmd=':SOUR:CURR:LEV {:.8f}', label='Current', unit='A') self.add_parameter('mode', vals=Enum('VOLT', 'CURR'), get_cmd=':SOUR:FUNC?', set_cmd=self._set_mode_and_sense, label='Mode') self.add_parameter('sense', vals=Strings(), get_cmd=':SENS:FUNC?', set_cmd=':SENS:FUNC "{:s}"', label='Sense mode') self.add_parameter('output', get_parser=int, set_cmd=':OUTP:STAT {:d}', get_cmd=':OUTP:STAT?') self.add_parameter('nplcv', get_cmd='SENS:VOLT:NPLC?', get_parser=float, set_cmd='SENS:VOLT:NPLC {:f}', label='Voltage integration time') self.add_parameter('nplci', get_cmd='SENS:CURR:NPLC?', get_parser=float, set_cmd='SENS:CURR:NPLC {:f}', label='Current integration time') self.add_parameter('resistance', get_cmd=':READ?', get_parser=self._resistance_parser, label='Resistance', unit='Ohm')
def test_bad(): for args in [[], [1], [Strings(), True]]: with pytest.raises(TypeError): MultiTypeAnd(*args)
def test_set_sweep_errors(self): gates = self.gates # for reference, some add_parameter's that should work gates.add_parameter('t0', set_cmd='{}', vals=Numbers(), step=0.1, delay=0.01) gates.add_parameter('t2', set_cmd='{}', vals=Ints(), step=1, delay=0.01, max_val_age=0) with self.assertRaises(TypeError): # can't sweep non-numerics gates.add_parameter('t1', set_cmd='{}', vals=Strings(), step=1, delay=0.01) with self.assertRaises(TypeError): # need a numeric step too gates.add_parameter('t1', set_cmd='{}', vals=Numbers(), step='a skosh', delay=0.01) with self.assertRaises(TypeError): # Ints requires and int step gates.add_parameter('t1', set_cmd='{}', vals=Ints(), step=0.1, delay=0.01) with self.assertRaises(ValueError): # need a non-negative step gates.add_parameter('t1', set_cmd='{}', vals=Numbers(), step=-0.1, delay=0.01) with self.assertRaises(TypeError): # need a numeric delay gates.add_parameter('t1', set_cmd='{}', vals=Numbers(), step=0.1, delay='a tad') with self.assertRaises(ValueError): # need a non-negative delay gates.add_parameter('t1', set_cmd='{}', vals=Numbers(), step=0.1, delay=-0.01) with self.assertRaises(TypeError): # need a numeric max_val_age gates.add_parameter('t1', set_cmd='{}', vals=Numbers(), step=0.1, delay=0.01, max_val_age='an hour') with self.assertRaises(ValueError): # need a non-negative max_val_age gates.add_parameter('t1', set_cmd='{}', vals=Numbers(), step=0.1, delay=0.01, max_val_age=-1)
def __init__(self, name, address, min_freq=10e6, max_freq=8e9, min_power=-60, max_power=-10, trace_name='S11') -> None: super().__init__(name=name, address=address, terminator='\n') self.trace_name = trace_name self.min_freq = min_freq self.max_freq = max_freq #Set the device in continuous sweep mode self.visa_handle.write(":SENS:HOLD:FUNC CONT") # Drive power self.add_parameter('power', label='Power', get_cmd='SOUR:POW?', set_cmd='SOUR:POW {}', vals=Strings()) # IF bandwidth self.add_parameter('if_bandwidth', label='IF Bandwidth', get_cmd='SENS:BAND?', get_parser=float, set_cmd='SENS:BAND {:.2f}', unit='Hz') # Number of averages (also resets averages) self.add_parameter('averages_enabled', label='Averages Enabled', get_cmd="SENS:AVER?", set_cmd="SENS:AVER {}", val_mapping={ True: '1', False: '0' }) self.add_parameter('averages', label='Averages', get_cmd='SENS:AVER:COUN?', get_parser=int, set_cmd='SENS:AVER:COUN {:d}', unit='') # Setting frequency range self.add_parameter('start', label='Start Frequency', get_cmd='SENS:FREQ:STAR?', get_parser=float, set_cmd=self._set_start, unit='Hz', vals=Numbers(min_value=min_freq, max_value=max_freq)) self.add_parameter('stop', label='Stop Frequency', get_cmd='SENS:FREQ:STOP?', get_parser=float, set_cmd=self._set_stop, unit='Hz', vals=Numbers(min_value=min_freq, max_value=max_freq)) self.add_parameter('center', label='Center Frequency', get_cmd='SENS:FREQ:CENT?', get_parser=float, set_cmd=self._set_center, unit='Hz', vals=Numbers(min_value=min_freq, max_value=max_freq)) self.add_parameter('span', label='Frequency Span', get_cmd='SENS:FREQ:SPAN?', get_parser=float, set_cmd=self._set_span, unit='Hz', vals=Numbers(min_value=min_freq, max_value=max_freq)) # Number of points in a sweep self.add_parameter('points', label='Points', get_cmd='SENS:SWE:POIN?', get_parser=int, set_cmd=self._set_points, unit='', vals=Ints(min_value=1, max_value=10000)) self.add_parameter('trace', label='Trace', get_cmd=self._Sparam, set_cmd=self._set_Sparam, vals=Strings()) self.add_parameter(name='trace_re_im', start=self.start(), stop=self.stop(), npts=self.points(), trnm=self.trace(), parameter_class=FrequencySweepReIm) self.add_parameter(name='trace_mag', start=self.start(), stop=self.stop(), npts=self.points(), trnm=self.trace(), parameter_class=FrequencySweepMag) self.add_parameter('output_format', get_cmd='FORMAT:DATa?', get_parser=str, set_cmd='FORMAT:DATa {}', vals=Enum("REAL", "REAL32", "ASC")) self.connect_message() #Default parameters, mess with it on your own risk self.output_format("REAL")
def __init__(self, name: str, address: str, **kwargs: Any): super().__init__(name, address, **kwargs) # Reference and phase self.add_parameter('phase', label='Phase', get_cmd='PHAS?', get_parser=float, set_cmd='PHAS {:.2f}', unit='deg', vals=Numbers(min_value=-360, max_value=729.99)) self.add_parameter('reference_source', label='Reference source', get_cmd='FMOD?', set_cmd='FMOD {}', val_mapping={ 'external': 0, 'internal': 1, }, vals=Enum('external', 'internal')) self.add_parameter('frequency', label='Frequency', get_cmd='FREQ?', get_parser=float, set_cmd='FREQ {:.4f}', unit='Hz', vals=Numbers(min_value=1e-3, max_value=102e3)) self.add_parameter('ext_trigger', label='External trigger', get_cmd='RSLP?', set_cmd='RSLP {}', val_mapping={ 'sine': 0, 'TTL rising': 1, 'TTL falling': 2, }) self.add_parameter('harmonic', label='Harmonic', get_cmd='HARM?', get_parser=int, set_cmd='HARM {:d}', vals=Ints(min_value=1, max_value=19999)) self.add_parameter('amplitude', label='Amplitude', get_cmd='SLVL?', get_parser=float, set_cmd='SLVL {:.3f}', unit='V', vals=Numbers(min_value=0.004, max_value=5.000)) # Input and filter self.add_parameter('input_config', label='Input configuration', get_cmd='ISRC?', get_parser=self._get_input_config, set_cmd='ISRC {}', set_parser=self._set_input_config, vals=Enum(*self._INPUT_CONFIG_TO_N.keys())) self.add_parameter('input_shield', label='Input shield', get_cmd='IGND?', set_cmd='IGND {}', val_mapping={ 'float': 0, 'ground': 1, }) self.add_parameter('input_coupling', label='Input coupling', get_cmd='ICPL?', set_cmd='ICPL {}', val_mapping={ 'AC': 0, 'DC': 1, }) self.add_parameter('notch_filter', label='Notch filter', get_cmd='ILIN?', set_cmd='ILIN {}', val_mapping={ 'off': 0, 'line in': 1, '2x line in': 2, 'both': 3, }) # Gain and time constant self.add_parameter(name='sensitivity', label='Sensitivity', get_cmd='SENS?', set_cmd='SENS {:d}', get_parser=self._get_sensitivity, set_parser=self._set_sensitivity) self.add_parameter('reserve', label='Reserve', get_cmd='RMOD?', set_cmd='RMOD {}', val_mapping={ 'high': 0, 'normal': 1, 'low noise': 2, }) self.add_parameter('time_constant', label='Time constant', get_cmd='OFLT?', set_cmd='OFLT {}', unit='s', val_mapping={ 10e-6: 0, 30e-6: 1, 100e-6: 2, 300e-6: 3, 1e-3: 4, 3e-3: 5, 10e-3: 6, 30e-3: 7, 100e-3: 8, 300e-3: 9, 1: 10, 3: 11, 10: 12, 30: 13, 100: 14, 300: 15, 1e3: 16, 3e3: 17, 10e3: 18, 30e3: 19, }) self.add_parameter('filter_slope', label='Filter slope', get_cmd='OFSL?', set_cmd='OFSL {}', unit='dB/oct', val_mapping={ 6: 0, 12: 1, 18: 2, 24: 3, }) self.add_parameter('sync_filter', label='Sync filter', get_cmd='SYNC?', set_cmd='SYNC {}', val_mapping={ 'off': 0, 'on': 1, }) def parse_offset_get(s: str) -> Tuple[float, int]: parts = s.split(',') return float(parts[0]), int(parts[1]) # TODO: Parameters that can be set with multiple arguments # For the OEXP command for example two arguments are needed self.add_parameter('X_offset', get_cmd='OEXP? 1', get_parser=parse_offset_get) self.add_parameter('Y_offset', get_cmd='OEXP? 2', get_parser=parse_offset_get) self.add_parameter('R_offset', get_cmd='OEXP? 3', get_parser=parse_offset_get) # Aux input/output for i in [1, 2, 3, 4]: 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') # Setup self.add_parameter('output_interface', label='Output interface', get_cmd='OUTX?', set_cmd='OUTX {}', val_mapping={ 'RS232': '0\n', 'GPIB': '1\n', }) # Data transfer self.add_parameter('X', get_cmd='OUTP? 1', get_parser=float, unit='V') self.add_parameter('Y', get_cmd='OUTP? 2', get_parser=float, unit='V') self.add_parameter('R', get_cmd='OUTP? 3', get_parser=float, unit='V') self.add_parameter('P', get_cmd='OUTP? 4', get_parser=float, unit='deg') self.add_parameter( "complex_voltage", label="Voltage", get_cmd=self._get_complex_voltage, unit="V", docstring="Complex voltage parameter " "calculated from X, Y phase using " "Z = X +j*Y", vals=ComplexNumbers(), ) # Data buffer settings self.add_parameter('buffer_SR', label='Buffer sample rate', get_cmd='SRAT ?', set_cmd=self._set_buffer_SR, unit='Hz', val_mapping={ 62.5e-3: 0, 0.125: 1, 0.250: 2, 0.5: 3, 1: 4, 2: 5, 4: 6, 8: 7, 16: 8, 32: 9, 64: 10, 128: 11, 256: 12, 512: 13, 'Trigger': 14 }, get_parser=int) self.add_parameter('buffer_acq_mode', label='Buffer acquistion mode', get_cmd='SEND ?', set_cmd='SEND {}', val_mapping={ 'single shot': 0, 'loop': 1 }, get_parser=int) self.add_parameter('buffer_trig_mode', label='Buffer trigger start mode', get_cmd='TSTR ?', set_cmd='TSTR {}', val_mapping={ 'ON': 1, 'OFF': 0 }, get_parser=int) self.add_parameter('buffer_npts', label='Buffer number of stored points', get_cmd='SPTS ?', get_parser=int) self.add_parameter('sweep_setpoints', parameter_class=GeneratedSetPoints, vals=Arrays(shape=(self.buffer_npts.get, ))) # Channel setup for ch in range(1, 3): # detailed validation and mapping performed in set/get functions self.add_parameter(f'ch{ch}_ratio', label=f'Channel {ch} ratio', get_cmd=partial(self._get_ch_ratio, ch), set_cmd=partial(self._set_ch_ratio, ch), vals=Strings()) self.add_parameter(f'ch{ch}_display', label=f'Channel {ch} display', get_cmd=partial(self._get_ch_display, ch), set_cmd=partial(self._set_ch_display, ch), vals=Strings()) self.add_parameter(f'ch{ch}_databuffer', channel=ch, parameter_class=ChannelBuffer) self.add_parameter(f'ch{ch}_datatrace', channel=ch, vals=Arrays(shape=(self.buffer_npts.get, )), setpoints=(self.sweep_setpoints, ), parameter_class=ChannelTrace) # Auto functions self.add_function('auto_gain', call_cmd='AGAN') self.add_function('auto_reserve', call_cmd='ARSV') self.add_function('auto_phase', call_cmd='APHS') self.add_function('auto_offset', call_cmd='AOFF {0}', args=[Enum(1, 2, 3)]) # 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') self.add_function('send_trigger', call_cmd='TRIG', docstring=("Send a software trigger. " "This command has the same effect as a " "trigger at the rear panel trigger" " input.")) self.add_function('buffer_start', call_cmd='STRT', docstring=("The buffer_start command starts or " "resumes data storage. buffer_start" " is ignored if storage is already in" " progress.")) self.add_function('buffer_pause', call_cmd='PAUS', docstring=("The buffer_pause command pauses data " "storage. If storage is already paused " "or reset then this command is ignored.")) self.add_function('buffer_reset', call_cmd='REST', docstring=("The buffer_reset command resets the data" " buffers. The buffer_reset command can " "be sent at any time - any storage in " "progress, paused or not, will be reset." " This command will erase the data " "buffer.")) # Initialize the proper units of the outputs and sensitivities self.input_config() # start keeping track of buffer setpoints self._buffer1_ready = False self._buffer2_ready = False self.connect_message()
def __init__(self, name, address, **kwargs): super().__init__(name, address, terminator='\n', **kwargs) self.add_parameter('rangev', get_cmd='SENS:VOLT:RANG?', get_parser=float, set_cmd='SOUR:VOLT:RANG {:f}', label='Voltage range') self.add_parameter('rangei', get_cmd='SENS:CURR:RANG?', get_parser=float, set_cmd='SOUR:CURR:RANG {:f}', label='Current range') self.add_parameter('compliancev', get_cmd='SENS:VOLT:PROT?', get_parser=float, set_cmd='SENS:VOLT:PROT {:f}', label='Voltage Compliance') self.add_parameter('compliancei', get_cmd='SENS:CURR:PROT?', get_parser=float, set_cmd='SENS:CURR:PROT {:f}', label='Current Compliance') self.add_parameter('volt', get_cmd=self._get_read_output_protected, get_parser=self._volt_parser, set_cmd=':SOUR:VOLT:LEV {:.8f}', label='Voltage', unit='V', docstring="Sets voltage in 'VOLT' mode. " "Get returns measured voltage if " "sensing 'VOLT' otherwise it returns " "setpoint value. " "Note that it is an error to read voltage with " "output off") self.add_parameter('curr', get_cmd=self._get_read_output_protected, get_parser=self._curr_parser, set_cmd=':SOUR:CURR:LEV {:.8f}', label='Current', unit='A', docstring="Sets current in 'CURR' mode. " "Get returns measured current if " "sensing 'CURR' otherwise it returns " "setpoint value. " "Note that it is an error to read current with " "output off") self.add_parameter('mode', vals=Enum('VOLT', 'CURR'), get_cmd=':SOUR:FUNC?', set_cmd=self._set_mode_and_sense, label='Mode') self.add_parameter('sense', vals=Strings(), get_cmd=':SENS:FUNC?', set_cmd=':SENS:FUNC "{:s}"', label='Sense mode') self.add_parameter('output', get_parser=int, set_cmd=':OUTP:STAT {:d}', get_cmd=':OUTP:STAT?') self.add_parameter('nplcv', get_cmd='SENS:VOLT:NPLC?', get_parser=float, set_cmd='SENS:VOLT:NPLC {:f}', label='Voltage integration time') self.add_parameter('nplci', get_cmd='SENS:CURR:NPLC?', get_parser=float, set_cmd='SENS:CURR:NPLC {:f}', label='Current integration time') self.add_parameter( 'resistance', get_cmd=self._get_read_output_protected, get_parser=self._resistance_parser, label='Resistance', unit='Ohm', docstring="Measure resistance from current and voltage " "Note that it is an error to read current " "and voltage with output off")
def test_valid_values(self): m = MultiType(Strings(2, 4), Ints(10, 32)) for val in m.valid_values: m.validate(val)
def test_valid_values(self): val = Strings() val.validate(val.valid_values[0])
def __init__(self, parent, name, channel): super().__init__(parent, name) # Validate the channel value self._CHANNEL_VAL.validate(channel) self._channel = channel # Channel on the temperature controller. Can be A-D # Add the various channel parameters self.add_parameter('temperature', get_cmd='KRDG? {}'.format(self._channel), get_parser=float, label='Temerature', unit='K') self.add_parameter('sensor_raw', get_cmd='SRDG? {}'.format(self._channel), get_parser=float, label='Raw_Reading', unit='Ohms') # TODO: This will vary based on sensor type self.add_parameter('sensor_status', get_cmd='RDGST? {}'.format(self._channel), val_mapping={'OK': 0, 'Invalid Reading': 1, 'Temp Underrange': 16, 'Temp Overrange': 32, 'Sensor Units Zero': 64, 'Sensor Units Overrange': 128}, label='Sensor_Status') self.add_parameter('sensor_name', get_cmd='INNAME? {}'.format(self._channel), get_parser=str, set_cmd='INNAME {},\"{{}}\"'.format(self._channel), vals=Strings(15), label='Sensor_Name')
def __init__(self, name: str, address: str, terminator="\n", reset: bool = False, **kwargs): super().__init__(name, address, terminator=terminator, **kwargs) self.add_parameter('source_current_compliance', unit='A', get_parser=float, set_cmd='SENS:CURR:PROT {}', get_cmd='SENS:CURR:PROT?', vals=Numbers(1e-9, 105e-3)) self.add_parameter('source_voltage_compliance', unit='V', get_parser=float, set_cmd='SENS:VOLT:PROT {}', get_cmd='SENS:VOLT:PROT?', vals=Numbers(1e-12, 210)) self.add_parameter( 'source_current_compliance_tripped', get_cmd='SENS:CURR:PROT:TRIP?', val_mapping=on_off_vals, docstring='True if current has reached specified ' 'compliance.', ) self.add_parameter( 'source_voltage_compliance_tripped', get_cmd='SENS:VOLT:PROT:TRIP?', val_mapping=on_off_vals, docstring='True if voltage has reached specified ' 'compliance.', ) self.add_parameter( 'source_current', unit='A', get_parser=float, label='Source current', set_cmd='SOUR:CURR:LEV {}', get_cmd='SOUR:CURR:LEV?', vals=Numbers(-105e-3, 105e-3), docstring='When in current sourcing mode, tries to ' 'set current to this level.', ) self.add_parameter( 'sense_current', unit='A', get_parser=float, label='Measured current', get_cmd=partial(self._read_value, 'CURR:DC'), snapshot_get=False, docstring='Value of measured current, when in ' 'current sensing mode.', ) self.add_parameter( 'sense_voltage', unit='V', get_parser=float, label='Measured voltage', get_cmd=partial(self._read_value, 'VOLT:DC'), snapshot_get=False, docstring='Value of measured voltage, when in ' 'voltage sensing mode.', ) self.add_parameter( 'sense_resistance', unit='Ohm', get_parser=float, label='Measured resistance', get_cmd=partial(self._read_value, 'RES'), snapshot_get=False, docstring='Value of measured resistance, when in ' 'resistance sensing mode.', ) self.add_parameter('source_current_range', unit='A', get_parser=float, set_cmd='SOUR:CURR:RANG {}', get_cmd='SOUR:CURR:RANG?', vals=Numbers(1e-12, 105e-3)) self.add_parameter( 'source_voltage', unit='V', get_parser=float, label='Source voltage', set_cmd='SOUR:VOLT:LEV {}', get_cmd='SOUR:VOLT:LEV?', vals=Numbers(-210, 210), docstring='When in voltage sourcing mode, tries to ' 'set voltage to this level.', ) self.add_parameter('source_voltage_range', unit='V', get_parser=float, set_cmd='SOUR:VOLT:RANG {}', get_cmd='SOUR:VOLT:RANG?', vals=Numbers(200e-3, 200)) self.add_parameter( 'source_delay_auto', set_cmd=':SOUR:DEL:AUTO {}', get_cmd=':SOUR:DEL:AUTO?', val_mapping=on_off_vals, docstring="Automatically set a delay period that " "is appropriate for the present " "source/measure setup configuration.", ) self.add_parameter( 'source_delay', unit='s', get_parser=float, set_cmd=':SOUR:DEL {}', get_cmd=':SOUR:DEL?', vals=Numbers(0, 9999.998), docstring="Settling time after setting source " "value.", ) self.add_parameter( 'output_enabled', set_cmd='OUTP {}', get_cmd='OUTP?', val_mapping=on_off_vals, docstring='Turns the source on or off.', ) self.add_parameter( 'output_auto_off_enabled', set_cmd=':SOUR:CLE:AUTO {}', get_cmd='OUTP?', val_mapping=on_off_vals, ) self.add_parameter( 'source_mode', set_cmd='SOUR:FUNC {}', get_cmd=self._get_source_mode, vals=Enum('VOLT', 'CURR'), docstring="Either 'VOLT' to source voltage, " "or 'CURR' for current.", ) self.add_parameter( 'sense_mode', set_cmd=self._set_sense_mode, get_cmd=self._get_sense_mode, vals=Strings(), docstring="Sensing mode." "Set to 'VOLT:DC', " "'CURR:DC', or 'RES', or a combination " "thereof by using comma.", ) self.add_parameter( 'sense_autorange', set_cmd=self._set_sense_autorange, get_cmd=self._get_sense_autorange, vals=Bool(), docstring="If True, all ranges in all modes are" " chosen automatically", ) self.add_parameter( 'sense_current_range', unit='A', get_parser=float, set_cmd=':SENS:CURR:RANG {}', get_cmd=':SENS:CURR:RANG?', vals=Numbers(1e-12, 1e-1), ) self.add_parameter( 'sense_voltage_range', unit='V', get_parser=float, set_cmd=':SENS:VOLT:RANG {}', get_cmd=':SENS:VOLT:RANG?', vals=Enum(200, 20, 2, 0.2), ) self.add_parameter( 'sense_resistance_range', unit='Ohm', get_parser=float, set_cmd=':SENS:RES:RANG {}', get_cmd=':SENS:RES:RANG?', vals=Numbers(2, 2e13), ) self.add_parameter( 'sense_resistance_offset_comp_enabled', set_cmd=':SENS:RES:OCOM {}', get_cmd=':SENS:RES:OCOM?', val_mapping=on_off_vals, docstring="Set offset compensation on/off for " "resistance measurements.", ) self.add_parameter( 'trigger_source', set_cmd=':TRIG:SOUR {}', get_cmd=':TRIG:SOUR?', vals=Enum('IMM', 'TLIN'), docstring="Specify trigger control source." "IMMediate or TLINk.", ) self.add_parameter( 'arm_source', set_cmd=':ARM:SOUR {}', get_cmd=':ARM:SOUR?', vals=Enum('IMM', 'TLIN', "TIM", "MAN", "BUS", "NST", "PST", "BST"), docstring="Specify arm control source." "IMMediate, or TLINk, TIMer, MANual," " BUS, NSTest, PSTest, or BSTest.", ) self.add_parameter( 'trigger_count', set_cmd=':TRIG:COUN {}', get_cmd=':TRIG:COUN?', vals=Ints(), docstring="How many times to trigger.", ) self.add_parameter( 'arm_count', set_cmd=':ARM:COUN {}', get_cmd=':ARM:COUN?', vals=Ints(), docstring="How many times to arm.", ) self.add_parameter( 'nplc', get_parser=float, set_cmd=':NPLC {}', get_cmd=':NPLC?', vals=Numbers(0.01, 10), docstring="Set integration time to the specified" "value in Number of Powerline Cycles.", ) self.add_parameter( 'digits', get_parser=int, set_cmd='DISP:DIG {}', get_cmd='DISP:DIG?', vals=Ints(4, 7), docstring="Display resolution.", ) self.add_parameter( 'autozero', set_cmd='SYST:AZER:STAT {}', get_cmd='SYST:AZER:STAT?', val_mapping=on_off_vals, docstring="Enable autozero." "Enabling maximizes accuracy, " "disabling increases speed.", ) self.add_parameter( 'filter_auto', set_cmd='AVER:AUTO {}', get_cmd='AVER:AUTO?', val_mapping=on_off_vals, docstring="Automatically choose filtering.", ) self.add_parameter( 'filter_repeat_enabled', set_cmd=':AVER:REP:STAT {}', get_cmd='AVER:AUTO?', val_mapping=on_off_vals, docstring="Enable repeat filter.", ) self.add_parameter( 'filter_median_enabled', set_cmd=':MED:STAT {}', get_cmd=':MED:STAT?', val_mapping=on_off_vals, docstring="Enable median filter.", ) self.add_parameter( 'filter_moving_enabled', set_cmd=':AVER:STAT {}', get_cmd=':AVER:STAT?', val_mapping=on_off_vals, docstring="Enable moving average.", ) self.add_parameter( 'filter_repeat', get_parser=int, set_cmd=':AVER:REP:COUN {}', get_cmd=':AVER:REP:COUN?', vals=Ints(), docstring="Number of readings that are acquired" "and stored in the filter buffer.", ) self.add_parameter( 'filter_median', get_parser=int, set_cmd=':MED:RANK {}', get_cmd=':MED:RANK?', vals=Ints(), docstring="Number of reading samples" " for the median filter process.", ) self.add_parameter( 'filter_moving', get_parser=int, set_cmd=':AVER:COUN {}', get_cmd=':AVER:COUN?', vals=Ints(), docstring="Number of reading samples" " in the moving average filter.", ) self.connect_message() if reset: self.reset()