diff --git a/secop_psi/ips_mercury.py b/secop_psi/ips_mercury.py index c3ee708..252f755 100644 --- a/secop_psi/ips_mercury.py +++ b/secop_psi/ips_mercury.py @@ -87,7 +87,6 @@ class Field(MercuryChannel, Magfield): return self.query('PSU:SIG:SWHT', off_on) def write_switch_heater(self, value): - super().write_switch_heater(value) return self.change('PSU:SIG:SWHT', value, off_on) def read_atob(self): diff --git a/secop_psi/magfield.py b/secop_psi/magfield.py index 65a33af..3efa025 100644 --- a/secop_psi/magfield.py +++ b/secop_psi/magfield.py @@ -80,17 +80,19 @@ class Magfield(HasLimits, Drivable): 'wait time to ensure current is stable', FloatRange(0, unit='s'), readonly=False, default=6) wait_stable_field = Parameter( 'wait time to ensure field is stable', FloatRange(0, unit='s'), readonly=False, default=31) + persistent_limit = Parameter( + 'above this limit, lead currents are not driven to 0', + FloatRange(0, unit='$'), readonly=False, default=99) _state = None __init = True - _super_sw_check = False _last_target = None - switch_time = None + switch_on_time = None + switch_off_time = None def doPoll(self): if self.__init: self.__init = False - self.switch_time = time.time() if self.read_switch_heater() and self.mode == Mode.PERSISTENT: self.read_value() # check for persistent field mismatch # switch off heater from previous live or manual intervention @@ -112,6 +114,7 @@ class Magfield(HasLimits, Drivable): def initModule(self): super().initModule() + self.registerCallbacks(self) # for update_switch_heater self._state = StateMachine(logger=self.log, threaded=False, cleanup=self.cleanup_state) def write_target(self, target): @@ -180,12 +183,16 @@ class Magfield(HasLimits, Drivable): return Retry() return self.start_switch_on - def write_switch_heater(self, value): - """implementations must super call this!""" - self._super_sw_check = True - if value != self.switch_heater: - self.switch_time = time.time() - return value + def update_switch_heater(self, value): + """is called whenever switch heater was changed""" + if value: + self.switch_off_time = None + if self.switch_on_time is None: + self.switch_on_time = time.time() + else: + self.switch_on_time = None + if self.switch_off_time is None: + self.switch_off_time = time.time() def start_switch_on(self, state): """switch heater on""" @@ -193,10 +200,7 @@ class Magfield(HasLimits, Drivable): self.status = Status.PREPARING, 'wait for heater on' else: self.status = Status.PREPARING, 'turn switch heater on' - self._super_sw_check = False self.write_switch_heater(True) - if not self._super_sw_check: - raise ProgrammingError('missing super call in write_switch_heater') return self.switch_on def switch_on(self, state): @@ -204,7 +208,11 @@ class Magfield(HasLimits, Drivable): if (self.target == self._last_target and abs(self.target - self.persistent_field) <= self.tolerance): # short cut return self.check_switch_off - if state.now - self.switch_time < self.wait_switch_on: + self.read_switch_heater() + if self.switch_on_time is None: + self.log.warning('switch turned off manually - try again') + return self.start_switch_on + if state.now - self.switch_on_time < self.wait_switch_on: return Retry() self._last_target = self.target return self.start_ramp_to_target @@ -255,7 +263,6 @@ class Magfield(HasLimits, Drivable): else: self.status = Status.FINALIZING, 'wait for heater off' self.write_switch_heater(False) - # no check for super call needed here (would have been detected in start_switch_on) return self.switch_off def switch_off(self, state): @@ -265,8 +272,15 @@ class Magfield(HasLimits, Drivable): self._last_target = None return self.start_switch_on self.persistent_field = self.value - if state.now - self.switch_time < self.wait_switch_off: + self.read_switch_heater() + if self.switch_off_time is None: + self.log.warning('switch turned on manually - try again') + return self.start_switch_off + if state.now - self.switch_off_time < self.wait_switch_off: return Retry() + if abs(self.value) > self.persistent_limit: + self.status = Status.IDLE, 'leads current at field, switch off' + return self.finish_state return self.start_ramp_to_zero def start_ramp_to_zero(self, state):