frappy_psi.dilution: improvements on DIL4

Change-Id: I204eaa8ef7a5d4a868c7ca8b17e2ebdae3cd9884
This commit is contained in:
2026-05-15 17:38:33 +02:00
parent 68d678b32a
commit ed22bb659a
+161 -123
View File
@@ -28,19 +28,17 @@ from frappy.lib.enum import Enum
from frappy.errors import ImpossibleError
from frappy.lib.mathparser import MathParser
T = Enum( # target states
off = 0,
sorbpump = 2,
condense = 5,
remove = 7,
remove_and_sorbpump = 9,
remove_and_condense = 10,
manual = 11,
test = 12,
T = Enum(off=0, # target states
sorbpump=1,
condense=5,
remove=7,
remove_and_sorbpump=9,
remove_and_condense=10,
# manual=11,
# test=12,
)
V = Enum(T, # value status inherits from target status
sorbpumping=1,
condensing=4,
circulating=6,
removing=8,
@@ -48,42 +46,14 @@ V = Enum(T, # value status inherits from target status
class Dilution(HasStates, Drivable):
condenseline_pressure = Attached() # G1
condense_valve = Attached() # V1
dump_valve = Attached() # V9
forepump = Attached() # rotary_pump_He3 (24)
condenseline_valve = Attached() # V1
circuitshort_valve = Attached() # V3
still_valve = Attached() # V6
pumpout_valve = Attached() # V14
still_pressure = Attached() # P1
dump_pressure = Attached() # G3
oneK_temp = Attached()
still_temp = Attached()
mix_temp = Attached()
value = Parameter('current state', EnumType(V), default=0)
target = Parameter('target state', EnumType(T), default=0)
sorbpumped = Parameter('sorb pump done', BoolType(), default=False, readonly=False)
sorb_cond = Parameter('sorb condition', StringType(), default='oneK>4', readonly=False)
sorb_pump_time = Parameter('sorb pump time', FloatRange(), default=2400, readonly=False)
dump_target = Parameter('low dump pressure limit indicating end of condensation phase',
FloatRange(unit='mbar * min'), readonly=False, default=50)
pulse_factor = Parameter('factor for calculating pump out pulse length',
FloatRange(unit='mbar'), readonly=False, default=20)
end_condense_pressure = Parameter('low condense pressure indicating end of condensation phase',
FloatRange(unit='mbar'), readonly=False, default=50)
end_remove_pressure = Parameter('pressure reached before end of remove (before fore pump)',
FloatRange(unit='mbar'), readonly=False, default=0.02)
condensing_p_low = Parameter('when to start pumping dump', datatype=FloatRange(unit='mbar'), default=500, readonly=False)
st = StringType()
valve_set = StructOf(close=st, open=st, check_open=st, check_closed=st)
condense_valves = Parameter('valve to act when condensing', valve_set)
valves_after_remove = Parameter('valve to act after remove', valve_set)
remove_valves = Parameter('valve to act when removing', valve_set)
valves_after_remove = Parameter('valves to act after remove', valve_set)
check_after_remove = Parameter('check for manual valves after remove', valve_set)
init = True
_start_time = 0
_warn_manual_work = None
def write_target(self, target):
@@ -105,84 +75,6 @@ class Dilution(HasStates, Drivable):
self.log.info('started %s', target.name)
return target
@status_code(BUSY, 'sorbpump state')
def sorbpump(self, state):
""" heat up to Tsorb and wait """
if state.init:
#self.ls372.write_target(40) # set Tsorb to 40K
self.start_time = state.now
self.handle_valves(**self.condense_valves)
return Retry
parser = MathParser(oneK=self.oneK_temp.value, still=self.still_temp.value, mix=self.mix_temp.value)
if parser.calculate(self.sorb_cond):
self.start_time = state.now
if state.now - self.start_time < self.sorb_pump_time:
return Retry
return self.condense
@status_code(BUSY)
def condense(self, state):
""" condense process """
if state.init:
# self.value = V.condensing
self.handle_valves(**self.condense_valves)
self.still_valve.write_target(100)
self._start_time = state.now
return Retry
pdump = self.dump_pressure.value
pcond = self.condenseline_pressure.read_value()
if pcond < self.condensing_p_low and state.now > self._start_time + 5:
pulse_time = 60 * self.pulse_factor / pdump
if pulse_time > 59:
pulse_time = 3600
self.pumpout_valve.delay = pulse_time
self.pumpout_valve.write_target(1)
if pdump > self.dump_target:
return Retry
return self.wait_for_condense_line_pressure
@status_code(BUSY)
def wait_for_condense_line_pressure(self, state):
if self.condenseline_pressure.read_value() > self.end_condense_pressure:
return Retry
self.condense_valve.write_target(0)
return self.circulate
@status_code(BUSY)
def circulate(self, state):
"""Zirkuliert die Mischung."""
if state.init:
self.handle_valves(**self.condense_valves)
if self.wait_valves():
return Retry
self.check_valve_result()
self.value = V.circulating
return Finish
@status_code(BUSY, 'remove (wait for turbo shut down)')
def remove(self, state):
"""Entfernt die Mischung."""
if state.init:
self.handle_valves(**self.remove_valves)
return Retry
self.circuitshort_valve.write_target(1)
return self.remove_endsequence
@status_code(BUSY)
def remove_endsequence(self, state):
if self.still_pressure.read_value() > self.end_remove_pressure:
return Retry
self.circuitshort_valve.write_target(0)
self.dump_valve.write_target(0)
return self.close_valves_after_remove
@status_code(BUSY)
def close_valves_after_remove(self, state):
if state.init:
self.handle_valves(**self.valves_after_remove)
self._warn_manual_work = True
return self.final_status(WARN, 'please check manual valves')
def read_status(self):
status = super().read_status()
if status[0] < ERROR and self._warn_manual_work:
@@ -234,20 +126,50 @@ class Dilution(HasStates, Drivable):
class DIL4(Dilution):
condenseline_pressure = Attached() # G1
circuitshort_valve = Attached() # V3
still_valve = Attached() # V6
pumpout_valve = Attached() # V14
still_pressure = Attached() # P1
dump_pressure = Attached() # G3
oneK_temp = Attached()
sorb_temp = Attached()
still_temp = Attached()
mix_temp = Attached()
vti_temp = Attached()
mix_power = Attached()
after_remove = Parameter('target state', EnumType(sorbpump=0, condense=1, remove_finish=2),
readonly=False, default='remove_finish')
sorbpumped = Parameter('sorb pump done', BoolType(), default=False, readonly=False)
sorb_cond = Parameter('sorb condition', StringType(), default='sorb>30', readonly=False)
sorb_pump_time = Parameter('sorb pump time', FloatRange(), default=2400, readonly=False)
dump_target = Parameter('low dump pressure limit indicating end of condensation phase',
FloatRange(unit='mbar * min'), readonly=False, default=50)
pulse_factor = Parameter('factor for calculating pump out pulse length',
FloatRange(unit='mbar'), readonly=False, default=20)
end_condense_pressure = Parameter('low condense pressure indicating end of condensation phase',
FloatRange(unit='mbar'), readonly=False, default=50)
end_remove_pressure = Parameter('pressure reached before end of remove (before fore pump)',
FloatRange(unit='mbar'), readonly=False, default=0.05)
condensing_p_low = Parameter('when to start pumping dump',
FloatRange(unit='mbar'), default=500, readonly=False)
_start_time = 0
condense_valves = {
'close': 'V2 V3 V4 V7 V8 V10 V11A V12A V13A',
'close': 'v2 v3 v4 v7 v8 v10 v11 v12 v13',
'check_closed': '',
'check_open': '',
'open': 'V1 V5 V9',
'open': 'v1 v5 v9',
}
remove_valves = {
'close': '',
'close': 'v4 v10 v13',
'check_closed': '',
'check_open': '',
'open': '',
'open': 'v1 v2 v3 v5 v8 v9 v11 v12',
}
valves_after_remove = {
'close': '',
'close': 'v1 v2 v3 v4 v5 v6 v7 v8 v9 v10 v11 v12',
'check_closed': '',
'open': '',
'check_open': '',
@@ -258,3 +180,119 @@ class DIL4(Dilution):
'open': '',
'check_open': '',
}
@status_code(BUSY)
def sorbpump(self, state):
""" heat up to Tsorb and wait """
if state.init:
self.start_time = state.now
self.vti_temp.write_target(5)
self.handle_valves(**self.condense_valves)
self.sorb_temp.write_target(40) # TODO: make variable
return Retry
parser = MathParser(
oneK=self.oneK_temp.value,
still=self.still_temp.value,
sorb=self.sorb_temp.value,
mix=self.mix_temp.value)
if parser.calculate(self.sorb_cond):
self.start_time = state.now
if state.now - self.start_time < self.sorb_pump_time:
return Retry
return self.sorbpump_phase2
@status_code(BUSY)
def sorbpump_phase2(self, state):
if state.init:
self.sorb_temp.write_target(1.25)
self.start_time = state.now
return Retry
if state.now - self.start_time < 900: # TODO: make variable
return Retry
return self.condense
@status_code(BUSY)
def condense(self, state):
""" condense process """
if state.init:
self.vti_temp.write_target(1.25)
# self.value = V.condensing
self.handle_valves(**self.condense_valves)
self.still_valve.write_target(100)
self._start_time = state.now
return Retry
pdump = self.dump_pressure.value
pcond = self.condenseline_pressure.read_value()
if pcond < self.condensing_p_low and state.now > self._start_time + 5:
pulse_time = 60 * self.pulse_factor / pdump
if pulse_time > 59:
pulse_time = 3600
self.pumpout_valve.delay = pulse_time
self.pumpout_valve.write_target(1)
if pdump > self.dump_target:
return Retry
return self.circulate
@status_code(BUSY)
def circulate(self, state):
"""Zirkuliert die Mischung."""
if state.init:
self.handle_valves(**self.condense_valves)
if self.wait_valves():
return Retry
self.check_valve_result()
self.value = V.circulating
return Finish
@status_code(BUSY)
def remove(self, state):
self.after_remove = 'remove_finish'
return self.remove_start(state)
@status_code(BUSY)
def remove_and_sorbpump(self, state):
self.after_remove = 'sorbpump'
return self.remove_start(state)
@status_code(BUSY)
def remove_and_condense(self, state):
self.after_remove = 'condense'
return self.remove_start(state)
@status_code(BUSY)
def remove_start(self, state):
"""Entfernt die Mischung."""
if state.init:
self.vti_temp.write_target(5)
self.mix_power.write_target(0.02)
self.handle_valves(**self.remove_valves)
return Retry
self.circuitshort_valve.write_target(1)
return self.removing
@status_code(BUSY)
def removing(self, state):
if (self.still_pressure.read_value() > 0.5 and
self.dump_pressure.read_value() > 350):
return Retry
return getattr(self, self.after_remove.name)
@status_code(BUSY)
def remove_finish(self, state):
if state.init:
self.vti_temp.write_target(10)
state.cnt_p1low = 0
else:
state.cnt_p1low += 1
pstill = self.still_pressure.read_value()
if pstill > self.end_remove_pressure or state.cnt_p1low < 3:
return Retry
self.handle_valves(**self.valves_after_remove)
return self.final_status(IDLE, '')
@status_code(BUSY)
def close_valves_after_remove(self, state):
if state.init:
self.handle_valves(**self.valves_after_remove)
self._warn_manual_work = True
return self.final_status(WARN, 'please check manual valves')