diff --git a/frappy_psi/dilution_new.py b/frappy_psi/dilution_new.py index 7a1d6ab8..c8105eb2 100644 --- a/frappy_psi/dilution_new.py +++ b/frappy_psi/dilution_new.py @@ -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')