magfield: add persistent_limit parameter

- use update_switch_heater instead of write_switch_heater
  for detecting switch time
- switch_time split into switch_on_time/switch_off_time

Change-Id: Id90a8b2c2520e24f3ee4a34aee25d41210e5d6d4
This commit is contained in:
zolliker 2022-08-16 10:02:57 +02:00
parent b81fc7b122
commit 2f6954c4f3
2 changed files with 29 additions and 16 deletions

View File

@ -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):

View File

@ -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):