diff --git a/secop_psi/triton.py b/secop_psi/triton.py index f7bf713..533f5ee 100644 --- a/secop_psi/triton.py +++ b/secop_psi/triton.py @@ -20,11 +20,13 @@ # ***************************************************************************** """oxford instruments triton (kelvinoxjt dil)""" -from math import sqrt -from secop.core import Writable, Parameter, Readable, Drivable, IDLE, WARN, BUSY, ERROR, Done -from secop.datatypes import EnumType, FloatRange +from math import sqrt, log10 +from secop.core import Writable, Parameter, Readable, Drivable, IDLE, WARN, BUSY, ERROR, \ + Done, Property +from secop.datatypes import EnumType, FloatRange, StringType from secop.lib.enum import Enum from secop_psi.mercury import MercuryChannel, Mapped, off_on, HasInput, SELF +from secop.lib import clamp import secop_psi.mercury as mercury actions = Enum(none=0, condense=1, circulate=2, collect=3) @@ -35,6 +37,7 @@ actions_map.mapping['NONE'] = actions.none # when writing, STOP is used instead class Action(MercuryChannel, Writable): channel_type = 'ACTN' + cooldown_channel = Property('cool down channel', StringType(), 'T5') value = Parameter('running action', EnumType(actions)) target = Parameter('action to do', EnumType(none=0, condense=1, collect=3), readonly=False) _target = 0 @@ -47,6 +50,7 @@ class Action(MercuryChannel, Writable): def write_target(self, value): self._target = value + self.change('SYS:DR:CHAN:COOL', self.cooldown_channel, str) return self.change('SYS:DR:ACTN', value, actions_map) # actions: @@ -245,10 +249,14 @@ class TemperatureLoop(ScannerChannel, mercury.TemperatureLoop): ENABLE = 'TEMP:LOOP:MODE' ENABLE_RAMP = 'TEMP:LOOP:RAMP:ENAB' RAMP_RATE = 'TEMP:LOOP:RAMP:RATE' + enable_pid_table = None # remove, does not work on triton + ctrlpars = Parameter('pid (gain, integral (inv. time), differential time') + system_channel = Property('system channel name', StringType(), 'MC') def write_control_active(self, value): - self.change('SYS:DR:CHAN:MC', 'T5', str) + if self.system_channel: + self.change('SYS:DR:CHAN:%s' % self.system_channel, self.slot.split(',')[0], str) if value: self.change('TEMP:LOOP:FILT:ENAB', 'ON', str) if self.output_module: @@ -260,7 +268,7 @@ class TemperatureLoop(ScannerChannel, mercury.TemperatureLoop): class HeaterOutput(HasInput, MercuryChannel, Writable): """heater output""" channel_type = 'HTR' - value = Parameter('heater output', FloatRange(unit='W')) + value = Parameter('heater output', FloatRange(unit='uW')) target = Parameter('heater output', FloatRange(0, unit='$'), readonly=False) resistivity = Parameter('heater resistivity', FloatRange(unit='Ohm')) @@ -268,7 +276,7 @@ class HeaterOutput(HasInput, MercuryChannel, Writable): return self.query('HTR:RES') def read_value(self): - return self.query('HTR:SIG:POWR') * 1e-6 + return round(self.query('HTR:SIG:POWR'), 3) def read_target(self): if self.controlled_by != 0: @@ -277,24 +285,33 @@ class HeaterOutput(HasInput, MercuryChannel, Writable): def write_target(self, value): self.write_controlled_by(SELF) - return self.change('HTR:SIG:POWR', value * 1e6) + if self.resistivity: + # round to the next voltage step + value = round(sqrt(value * self.resistivity)) ** 2 / self.resistivity + return round(self.change('HTR:SIG:POWR', value), 3) class HeaterOutputWithRange(HeaterOutput): """heater output with heater range""" channel_type = 'HTR,TEMP' - limit = Parameter('max. heater power', FloatRange(unit='W'), readonly=False) + limit = Parameter('max. heater power', FloatRange(unit='uW'), readonly=False) def read_limit(self): - maxcur = self.query('TEMP:LOOP:RANGE') * 0.001 # mA -> A - return self.read_resistivity() * maxcur ** 2 + maxcur = self.query('TEMP:LOOP:RANGE') # mA + return self.read_resistivity() * maxcur ** 2 # uW def write_limit(self, value): if value is None: - maxcur = 0.1 # max. allowed current 100mA + maxcur = 100 # max. allowed current 100mA else: maxcur = sqrt(value / self.read_resistivity()) - self.change('TEMP:LOOP:RANGE', maxcur * 1000) + for cur in 0.0316, 0.1, 0.316, 1, 3.16, 10, 31.6, 100: + if cur > maxcur * 0.999: + maxcur = cur + break + else: + maxcur = cur + self.change('TEMP:LOOP:RANGE', maxcur) return self.read_limit()