diff --git a/secop_psi/k2601b.py b/secop_psi/k2601b.py index 6a984e5..d1ad8bc 100644 --- a/secop_psi/k2601b.py +++ b/secop_psi/k2601b.py @@ -23,7 +23,7 @@ not tested yet""" from secop.core import Attached, BoolType, EnumType, FloatRange, \ - HasIodev, Module, Parameter, StringIO, Writable + HasIodev, Module, Parameter, StringIO, Writable, Done class K2601bIO(StringIO): @@ -31,13 +31,16 @@ class K2601bIO(StringIO): SOURCECMDS = { + 0: 'reset()' + ' smua.source.func = smua.OUTPUT_DCAMPS' + ' display.smua.measure.func = display.MEASURE_VOLTS' + ' smua.source.autorangei = 1' + ' smua.source.output = %d print("ok"")', 1: 'reset()' - 'smua.source.func = smua.OUTPUT_DCVOLTS ' - 'display.smua.measure.func = display.MEASURE_DCAMP ' - 'smua.source.autorangev = 1', - 2: 'reset()' - 'smua.source.func = smua.OUTPUT_DCAMPS ' - 'smua.source.autorangei = 1', + ' smua.source.func = smua.OUTPUT_DCVOLTS' + ' display.smua.measure.func = display.MEASURE_DCAMPS' + ' smua.source.autorangev = 1' + ' smua.source.output = %d print("ok"")', } @@ -45,9 +48,8 @@ class SourceMeter(HasIodev, Module): resistivity = Parameter('readback resistivity', FloatRange(unit='Ohm'), poll=True) power = Parameter('readback power', FloatRange(unit='W'), poll=True) - mode = Parameter('measurement mode', EnumType(off=0, current=1, voltage=2), - readonly=False, default=0) - active = Parameter('output enable', BoolType(), readonly=False, poll=True) + mode = Parameter('measurement mode', EnumType(current_off=0, voltage_off=1, current_on=2, voltage_on=3), + readonly=False, poll=True) iodevClass = K2601bIO @@ -57,20 +59,12 @@ class SourceMeter(HasIodev, Module): def read_power(self): return self.sendRecv('print(smua.measure.p())') - def read_active(self): - return self.sendRecv('print(smua.source.output)') - - def write_active(self, value): - return self.sendRecv('smua.source.output = %d print(smua.source.output)' % value) - - # for now, mode will not be read from hardware + def read_mode(self): + return float(self.sendRecv('print(smua.source.func+2*smua.source.output)')) def write_mode(self, value): - if value == 0: - self.write_active(0) - else: - self.sendRecv(SOURCECMDS[value] + ' print(0)') - return value + assert 'ok' == self.sendRecv(SOURCECMDS[value % 2] % (value >= 2)) + return self.read_mode() class Current(HasIodev, Writable): @@ -78,9 +72,12 @@ class Current(HasIodev, Writable): value = Parameter('measured current', FloatRange(unit='A'), poll=True) target = Parameter('set current', FloatRange(unit='A'), poll=True) - active = Parameter('current is controlled', BoolType(), default=False) # polled from Current/Voltage + active = Parameter('current is controlled', BoolType(), default=False) # polled by SourceMeter limit = Parameter('current limit', FloatRange(0, 2.0, unit='A'), default=2, poll=True) + def initModule(self): + self._sourcemeter.registerCallbacks(self) + def read_value(self): return self.sendRecv('print(smua.measure.i())') @@ -104,16 +101,16 @@ class Current(HasIodev, Writable): return value return self.sendRecv('smua.source.limiti = %g print(smua.source.limiti)' % value) - def read_active(self): - return self._sourcemeter.mode == 1 and self._sourcemeter.read_active() - def write_active(self, value): - if self._sourcemeter.mode != 1: - if value: - self._sourcemeter.write_mode(1) # switch to current - else: - return 0 - return self._sourcemeter.write_active(value) + if value: + self._sourcemeter.write_mode('current_on') + elif self._sourcemeter.mode == 'current_on': + self._sourcemeter.write_mode('current_off') + return self.active + + def update_mode(self, mode): + # will be called whenever the attached sourcemeters mode changes + self.active = mode == 'current_on' class Voltage(HasIodev, Writable): @@ -121,9 +118,12 @@ class Voltage(HasIodev, Writable): value = Parameter('measured voltage', FloatRange(unit='V'), poll=True) target = Parameter('set voltage', FloatRange(unit='V'), poll=True) - active = Parameter('voltage is controlled', BoolType(), poll=True) + active = Parameter('voltage is controlled', BoolType(), default=False) # polled by SourceMeter limit = Parameter('current limit', FloatRange(0, 2.0, unit='V'), default=2, poll=True) + def initModule(self): + self._sourcemeter.registerCallbacks(self) + def read_value(self): return self.sendRecv('print(smua.measure.v())') @@ -147,13 +147,13 @@ class Voltage(HasIodev, Writable): return value return self.sendRecv('smua.source.limitv = %g print(smua.source.limitv)' % value) - def read_active(self): - return self._sourcemeter.mode == 2 and self._sourcemeter.read_active() - def write_active(self, value): - if self._sourcemeter.mode != 2: - if value: - self._sourcemeter.write_mode(2) # switch to voltage - else: - return 0 - return self._sourcemeter.write_active(value) + if value: + self._sourcemeter.write_mode('voltage_on') + elif self._sourcemeter.mode == 'voltage_on': + self._sourcemeter.write_mode('voltage_off') + return self.active + + def update_mode(self, mode): + # will be called whenever the attached sourcemeters mode changes + self.active = mode == 'voltage_on' diff --git a/secop_psi/ls370res.py b/secop_psi/ls370res.py index 279cc04..0b73e9f 100644 --- a/secop_psi/ls370res.py +++ b/secop_psi/ls370res.py @@ -228,7 +228,7 @@ class ResChannel(HasIodev, Readable): if autorange: result['autorange'] = 'hard' # else: do not change autorange - self.log.info('%s range %r %r %r' % (self.name, rng, autorange, self.autorange)) + # self.log.info('%s range %r %r %r' % (self.name, rng, autorange, self.autorange)) if excoff: result.update(iexc=0, vexc=0) elif iscur: diff --git a/secop_psi/softcal.py b/secop_psi/softcal.py index bfa06a1..927da18 100644 --- a/secop_psi/softcal.py +++ b/secop_psi/softcal.py @@ -181,13 +181,16 @@ class Sensor(Readable): pollerClass = None _value_error = None - def __init__(self, name, logger, cfgdict, srv): - cfgdict.setdefault('description', 'calibrated value of module %r' % cfgdict['rawsensor']) - super().__init__(name, logger, cfgdict, srv) + def checkProperties(self): + if 'description' not in self.propertyValues: + self.description = '_' # avoid complaining about missing description + super().checkProperties() def initModule(self): self._rawsensor.registerCallbacks(self, ['status']) # auto update status self._calib = CalCurve(self.calib) + if self.description == '_': + self.description = '%r calibrated with curve %r' % (self.rawsensor, self.calib) def write_calib(self, value): self._calib = CalCurve(value)