diff --git a/secop_psi/ips_mercury.py b/secop_psi/ips_mercury.py index f74972a..4c14ccf 100644 --- a/secop_psi/ips_mercury.py +++ b/secop_psi/ips_mercury.py @@ -26,6 +26,7 @@ from secop.lib.enum import Enum from secop.errors import BadValueError, HardwareError from secop_psi.magfield import Magfield from secop_psi.mercury import MercuryChannel, off_on, Mapped +from secop.lib.statemachine import Retry Action = Enum(hold=0, run_to_set=1, run_to_zero=2, clamped=3) hold_rtoz_rtos_clmp = Mapped(HOLD=Action.hold, RTOS=Action.run_to_set, @@ -52,7 +53,6 @@ class Field(MercuryChannel, Magfield): nslaves = 3 slave_currents = None __init = True - __reset_switch_time = False def doPoll(self): super().doPoll() @@ -98,15 +98,10 @@ class Field(MercuryChannel, Magfield): def read_switch_heater(self): value = self.query('PSU:SIG:SWHT', off_on) now = time.time() - switch_time = self.switch_time[self.switch_heater] if value != self.switch_heater: - self.__reset_switch_time = True - if now < (switch_time or 0) + 10: + if now < (self.switch_time[self.switch_heater] or 0) + 10: # probably switch heater was changed, but IPS reply is not yet updated return self.switch_heater - elif self.__reset_switch_time: - self.__reset_switch_time = False - self.switch_time = [None, None] return value def write_switch_heater(self, value): @@ -155,16 +150,22 @@ class Field(MercuryChannel, Magfield): try: self.set_and_go(self.persistent_field) except (HardwareError, AssertionError): - state.switch_undef = self.switch_on_time or state.now + state.switch_undef = self.switch_time[self.switch_heater.on] or state.now return self.wait_for_switch return self.ramp_to_field + def ramp_to_field(self, state): + if self.action != 'run_to_set': + self.status = Status.PREPARING, 'restart ramp to field' + return self.start_ramp_to_field + return super().ramp_to_field(state) + def wait_for_switch(self, state): - if self.now - self.switch_undef < self.wait_switch_on: + if state.now - state.switch_undef < self.wait_switch_on: return Retry() self.set_and_go(self.persistent_field) return self.ramp_to_field - + def start_ramp_to_target(self, state): self.set_and_go(self.target) return self.ramp_to_target diff --git a/secop_psi/magfield.py b/secop_psi/magfield.py index ef90bc2..b7d42f6 100644 --- a/secop_psi/magfield.py +++ b/secop_psi/magfield.py @@ -76,33 +76,23 @@ class Magfield(HasLimits, Drivable): # ArrayOf(TupleOf(FloatRange(unit='$'), FloatRange(unit='$/min'))), readonly=False) # TODO: the following parameters should be changed into properties after tests wait_switch_on = Parameter( - 'wait time to ensure switch is on', FloatRange(0, unit='s'), readonly=False, default=61) + 'wait time to ensure switch is on', FloatRange(0, unit='s'), readonly=False, default=60) wait_switch_off = Parameter( - 'wait time to ensure switch is off', FloatRange(0, unit='s'), readonly=False, default=61) + 'wait time to ensure switch is off', FloatRange(0, unit='s'), readonly=False, default=60) wait_stable_leads = Parameter( '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) + 'wait time to ensure field is stable', FloatRange(0, unit='s'), readonly=False, default=30) persistent_limit = Parameter( 'above this limit, lead currents are not driven to 0', FloatRange(0, unit='$'), readonly=False, default=99) _state = None - __init = True _last_target = None switch_time = None, None def doPoll(self): - if self.__init: - self.__init = False - 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 - self.write_target(self.persistent_field) - else: - self._last_target = self.persistent_field - else: - self.read_value() + self.read_value() self._state.cycle() def checkProperties(self): @@ -119,6 +109,19 @@ class Magfield(HasLimits, Drivable): self.registerCallbacks(self) # for update_switch_heater self._state = StateMachine(logger=self.log, threaded=False, cleanup=self.cleanup_state) + def startModule(self, start_events): + start_events.queue(self.startupCheck) + super().startModule(start_events) + + def startupCheck(self): + 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 + self.write_mode(self.mode) + self.write_target(self.persistent_field) + else: + self._last_target = self.persistent_field + def write_target(self, target): self.check_limits(target) self.target = target