[WIP] frappy_psi:ccu4: add HeLevel, N2
Change-Id: Ib31ec440ecc51b01035d783065cb805b942b61b1
This commit is contained in:
parent
4da6aa95d7
commit
c6056ad1de
@ -20,9 +20,12 @@
|
|||||||
# *****************************************************************************
|
# *****************************************************************************
|
||||||
|
|
||||||
"""drivers for CCU4, the cryostat control unit at SINQ"""
|
"""drivers for CCU4, the cryostat control unit at SINQ"""
|
||||||
|
import time
|
||||||
# the most common Frappy classes can be imported from frappy.core
|
# the most common Frappy classes can be imported from frappy.core
|
||||||
from frappy.core import EnumType, FloatRange, \
|
from frappy.core import EnumType, FloatRange, TupleOf, \
|
||||||
HasIO, Parameter, Readable, StringIO, StatusType
|
HasIO, Parameter, Command, Readable, StringIO, StatusType, \
|
||||||
|
BUSY, IDLE, ERROR, DISABLED
|
||||||
|
from frappy.states import HasStates, status_code, Retry
|
||||||
|
|
||||||
|
|
||||||
class CCU4IO(StringIO):
|
class CCU4IO(StringIO):
|
||||||
@ -54,12 +57,12 @@ class HeLevel(HasIO, Readable):
|
|||||||
|
|
||||||
# conversion of the code from the CCU4 parameter 'hsf'
|
# conversion of the code from the CCU4 parameter 'hsf'
|
||||||
STATUS_MAP = {
|
STATUS_MAP = {
|
||||||
0: (StatusType.IDLE, 'sensor ok'),
|
0: (IDLE, 'sensor ok'),
|
||||||
1: (StatusType.ERROR, 'sensor warm'),
|
1: (ERROR, 'sensor warm'),
|
||||||
2: (StatusType.ERROR, 'no sensor'),
|
2: (ERROR, 'no sensor'),
|
||||||
3: (StatusType.ERROR, 'timeout'),
|
3: (ERROR, 'timeout'),
|
||||||
4: (StatusType.ERROR, 'not yet read'),
|
4: (ERROR, 'not yet read'),
|
||||||
5: (StatusType.DISABLED, 'disabled'),
|
5: (DISABLED, 'disabled'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def query(self, cmd):
|
def query(self, cmd):
|
||||||
@ -96,3 +99,116 @@ class HeLevel(HasIO, Readable):
|
|||||||
|
|
||||||
def write_sample_rate(self, value):
|
def write_sample_rate(self, value):
|
||||||
return self.query(f'hf={int(value)}')
|
return self.query(f'hf={int(value)}')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class HeLevelAuto(HasStates, HeLevel):
|
||||||
|
fill_level = Parameter('low threshold triggering start filling',
|
||||||
|
FloatRange(unit='%'), readonly=False)
|
||||||
|
full_level = Parameter('high threshold triggering stop filling',
|
||||||
|
FloatRange(unit='%'), readonly=False)
|
||||||
|
raw = Parameter('unsmoothed level', FloatRange(unit='%'))
|
||||||
|
fill_minutes_range = Parameter('range of possible fill rate',
|
||||||
|
TupleOf(FloatRange(unit='min'), FloatRange(unit='min')),
|
||||||
|
readonly=False)
|
||||||
|
hold_hours_range = Parameter('range of possible consumption rate',
|
||||||
|
TupleOf(FloatRange(unit='h'), FloatRange(unit='h')),
|
||||||
|
readonly=False)
|
||||||
|
fill_delay = Parameter('delay for cooling the transfer line',
|
||||||
|
FloatRange(unit='min'), readonly=False)
|
||||||
|
status = Parameter(datatype=StatusType(HeLevel, 'BUSY'))
|
||||||
|
|
||||||
|
_filling = False
|
||||||
|
_fillstart = 0
|
||||||
|
_last_read = 0
|
||||||
|
|
||||||
|
def doPoll(self):
|
||||||
|
super().doPoll()
|
||||||
|
if self._filling:
|
||||||
|
if self._filling == 1 and
|
||||||
|
if self.value
|
||||||
|
self.query('hcd=1')
|
||||||
|
|
||||||
|
def read_value(self):
|
||||||
|
self.raw = super().read_value()
|
||||||
|
if not self._state_machine.is_active:
|
||||||
|
return self.raw
|
||||||
|
return self.value
|
||||||
|
|
||||||
|
def read_status(self):
|
||||||
|
status = HeLevel.read_status(self)
|
||||||
|
if status[0] == IDLE:
|
||||||
|
return HasStates.read_status(self)
|
||||||
|
self.stop_machine(status)
|
||||||
|
return status
|
||||||
|
|
||||||
|
@status_code(BUSY)
|
||||||
|
def watching(self, state):
|
||||||
|
delta = state.delta(10)
|
||||||
|
if self.raw > self.value:
|
||||||
|
self.value -= delta / (3600 * self.fill_hours_range[1])
|
||||||
|
elif self.raw < self.value:
|
||||||
|
self.value -= delta / (3600 * self.fill_hours_range[0])
|
||||||
|
else:
|
||||||
|
self.value = self.raw
|
||||||
|
if self.value < self.fill_level:
|
||||||
|
self.query('hcd=1 hf=1')
|
||||||
|
state.fillstart = state.now
|
||||||
|
return self.precooling
|
||||||
|
self.query('hcd=1 hf=1')
|
||||||
|
return Retry
|
||||||
|
|
||||||
|
@status_code(BUSY)
|
||||||
|
def precooling(self, state):
|
||||||
|
delta = state.delta(1)
|
||||||
|
if self.raw > self.value:
|
||||||
|
self.value += delta / (60 * self.fill_minutes_range[0])
|
||||||
|
elif self.raw < self.value:
|
||||||
|
self.value -= delta / (60 * self.fill_minutes_range[0])
|
||||||
|
else:
|
||||||
|
self.value = self.raw
|
||||||
|
if self.value > self.full_level:
|
||||||
|
self.query('hcd=0 hf=0')
|
||||||
|
return self.watching
|
||||||
|
self.query('hcd=1 hf=1')
|
||||||
|
if state.now > state.fillstart + self.fill_delay * 60:
|
||||||
|
return self.filling
|
||||||
|
return Retry
|
||||||
|
|
||||||
|
@status_code(BUSY)
|
||||||
|
def filling(self, state):
|
||||||
|
delta = state.delta(1)
|
||||||
|
if self.raw > self.value:
|
||||||
|
self.value += delta / (60 * self.fill_minutes_range[0])
|
||||||
|
elif self.raw < self.value:
|
||||||
|
self.value += delta / (60 * self.fill_minutes_range[1])
|
||||||
|
else:
|
||||||
|
self.value = self.raw
|
||||||
|
if self.value > self.full_level:
|
||||||
|
self.query('hcd=0 hf=0')
|
||||||
|
return self.watching
|
||||||
|
self.query('hcd=1 hf=1')
|
||||||
|
return Retry
|
||||||
|
|
||||||
|
@Command()
|
||||||
|
def fill(self):
|
||||||
|
self.start_machine(self.precooling, fillstart=time.time())
|
||||||
|
self.query('hcd=1 hf=1')
|
||||||
|
|
||||||
|
@Command()
|
||||||
|
def stop(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class N2Sensor(HasIO, Readable):
|
||||||
|
# conversion of the code from the CCU4 parameter 'ns'
|
||||||
|
STATUS_MAP = {
|
||||||
|
0: (IDLE, 'sensor ok'),
|
||||||
|
1: (ERROR, 'no sensor'),
|
||||||
|
2: (ERROR, 'short circuit'),
|
||||||
|
3: (ERROR, 'upside down'),
|
||||||
|
4: (ERROR, 'sensor warm'),
|
||||||
|
5: (ERROR, 'empty'),
|
||||||
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user