diff --git a/frappy_psi/SR830.py b/frappy_psi/SR830.py index 4933382..e6d3845 100644 --- a/frappy_psi/SR830.py +++ b/frappy_psi/SR830.py @@ -32,15 +32,47 @@ def string_to_value(value): class SR830_IO(StringIO): - end_of_line = b'\r' # should be or + end_of_line = b'\r' # should be or identification = [('*IDN?', r'Stanford_Research_Systems,.*')] -class XY(HasIO): - xy = Parameter('X, Y', datatype=TupleOf(FloatRange(unit='V'), FloatRange(unit='V'))) +class StanfRes(HasIO): + def set_par(self, cmd, *args): + head = ','.join([cmd] + [a if isinstance(a, str) else f'{a:g}' for a in args]) + tail = cmd.replace(' ', '? ') + new_tail = re.sub(r'[0-9.]+', '', tail) + + reply = self.communicate(f'{head};{new_tail}') + result = [] + for num in reply.split(','): + try: + result.append(float(num)) + except ValueError: + result.append(num) + if len(result) == 1: + return result[0] + return result + + def get_par(self, cmd): + reply = self.communicate(cmd) + result = [] + for num in reply.split(','): + try: + result.append(float(num)) + except ValueError: + result.append(num) + if len(result) == 1: + return result[0] + return result + + +class XY(StanfRes): + value = Parameter('X, Y', datatype=TupleOf(FloatRange(unit='V'), FloatRange(unit='V'))) amp = Parameter('oscill. amplit. control', FloatRange(4e-3, 5), unit='V', readonly=False) freq = Parameter('oscill. frequen. control', FloatRange(1e-3, 102000), unit='Hz', readonly=False) phase = Parameter('reference phase control', FloatRange(-360, 729), unit='deg', readonly=False) + autorange = Parameter('autorange_on', EnumType('autorange', off=0, soft=1, hard=2), + readonly=False, default=0) SEN_RANGE = ['2nV', '5nV', '10nV', '20nV', '50nV', '100nV', '200nV', '500nV', '1uV', '2uV', '5uV', '10uV', '20uV', '50uV', '100uV', '200uV', '500uV', @@ -101,51 +133,57 @@ class XY(HasIO): # conv_status = HasConvergence.read_status(self) return status_type, status_msg - def read_xy(self): - reply = self.communicate('SNAP? 1, 2') - xy = tuple(float(x) for x in reply.split(',')) - return xy + def read_value(self): + reply = self.get_par('SNAP? 1, 2') + value = tuple(float(x) for x in reply) + x, y = value + if self.autorange == 1: + if max(abs(x), abs(y)) >= 0.9 * self.range and self.irange < 26: + self.write_irange(self.irange + 1) + elif max(abs(x), abs(y)) <= 0.3 * self.range and self.irange > 0: + self.write_irange(self.irange - 1) + return value def read_irange(self): - return int(self.communicate('SENS?')) + return int(self.get_par('SENS?')) def read_range(self): idx = self.read_irange() name = self.SEN_RANGE[idx] - value = string_to_value(name) - return value + return string_to_value(name) def write_irange(self, irange): value = int(irange) - self.communicate(f'SENS {value}') + self.set_par(f'SENS {value}') return value def write_range(self, target): target = float(target) cl_idx = None - cl_value = float('-inf') + cl_value = float('inf') for idx, sen_value in enumerate(self.SEN_RANGE_values): - if target >= sen_value > cl_value: - cl_value = sen_value - cl_idx = idx + if sen_value >= target: + diff = sen_value - target - self.communicate(f'SENS {cl_idx}') + if diff < cl_value: + cl_value = sen_value + cl_idx = idx + + self.set_par(f'SENS {cl_idx}') return cl_value def read_itc(self): - return int(self.communicate(f'OFLT?')) + return int(self.get_par(f'OFLT?')) def write_itc(self, itc): value = int(itc) - self.communicate(f'OFLT {value}') - return value + return self.set_par(f'OFLT {value}') def read_tc(self): idx = self.read_itc() name = self.TIME_CONST[idx] - value = string_to_value(name) - return value + return string_to_value(name) def write_tc(self, target): target = float(target) @@ -160,31 +198,27 @@ class XY(HasIO): cl_value = time_value cl_idx = idx - self.communicate(f'OFLT {cl_idx}') + self.set_par(f'OFLT {cl_idx}') return cl_value def read_phase(self): - return float(self.communicate('PHAS?')) + return float(self.get_par('PHAS?')) def write_phase(self, value): - self.communicate(f'PHAS {value}') - return value + return self.set_par(f'PHAS {value}') def read_freq(self): - return float(self.communicate('FREQ?')) + return float(self.get_par('FREQ?')) def write_freq(self, value): - self.communicate(f'FREQ {value}') - return value + return self.set_par(f'FREQ {value}') def read_amp(self): - return float(self.communicate('SLVL?')) + return float(self.get_par('SLVL?')) def write_amp(self, value): - self.communicate(f'SLVL {value}') - return value + return self.set_par(f'SLVL {value}') def auto_phase(self): - return self.communicate('APHS') - + return self.set_par('APHS')