finished thermofisher

but: convergence does not work yet properly
Change-Id: I834f8368730c347ba9f08a03eceae1a60fc66f90
This commit is contained in:
Oksana Shliakhtun 2023-04-26 10:23:14 +02:00
parent 329c8d999a
commit 2d628e151c
5 changed files with 96 additions and 48 deletions

View File

@ -1,5 +1,5 @@
Node('TFA10.psi.ch', Node('TFA10.psi.ch',
'TFA10', 'TFA10 test',
'tcp://5000', 'tcp://5000',
) )
@ -10,13 +10,14 @@ Mod('io',
) )
Mod('T', Mod('T',
'frappy_psi.qnw.TemperatureLoopA10', 'frappy_psi.thermofisher.TemperatureLoopA10',
'holder temperature', 'holder temperature',
io='io', io='io',
target=Param(max=100),
) )
Mod('Th', Mod('Th',
'frappy_psi.qnw.SensorA10', 'frappy_psi.thermofisher.SensorA10',
'heat exch. temperature', 'heat exch. temperature',
io='io', io='io',
) )

View File

@ -65,7 +65,7 @@ class HasOutputModule(Writable):
""" """
# mandatory=False: it should be possible to configure a module with fixed control # mandatory=False: it should be possible to configure a module with fixed control
output_module = Attached(HasControlledBy, mandatory=False) output_module = Attached(HasControlledBy, mandatory=False)
control_active = Parameter('control mode', BoolType()) control_active = Parameter('control mode', BoolType(), default=False)
def initModule(self): def initModule(self):
super().initModule() super().initModule()

View File

@ -21,10 +21,11 @@
# ***************************************************************************** # *****************************************************************************
from frappy.core import Parameter, FloatRange, BUSY, IDLE, WARN from frappy.core import Parameter, FloatRange, BUSY, IDLE, WARN
from frappy.states import HasStates
from frappy.lib.statemachine import StateMachine, Retry, Stop from frappy.lib.statemachine import StateMachine, Retry, Stop
class HasConvergence: class HasConvergence(HasStates):
"""mixin for convergence checks """mixin for convergence checks
Implementation based on tolerance, settling time and timeout. Implementation based on tolerance, settling time and timeout.

View File

@ -121,6 +121,7 @@ class TemperatureLoopTC1(SensorTC1, Drivable):
return True return True
self.set_param('TC', '-') self.set_param('TC', '-')
return False return False
###########
def read_ramp(self): def read_ramp(self):
return float(self.get_param('RR')) return float(self.get_param('RR'))
@ -145,13 +146,3 @@ class TemperatureLoopTC1(SensorTC1, Drivable):
def stop(self): def stop(self):
if self.control and self.ramp_used: if self.control and self.ramp_used:
self.write_target(self.value) self.write_target(self.value)

View File

@ -20,90 +20,145 @@
# ***************************************************************************** # *****************************************************************************
from frappy.core import StringIO, Parameter, Readable, HasIO, \ from frappy.core import StringIO, Parameter, Readable, HasIO, \
Drivable, FloatRange Drivable, FloatRange, IDLE, ERROR, WARN, BoolType
from frappy_psi.convergence import HasConvergence
class ThermFishIO(StringIO): class ThermFishIO(StringIO):
end_of_line = '\r' end_of_line = '\r'
identification = [('RVER', r'.[.*')] # Firmware Version identification = [('RVER', r'.*')] # Firmware Version
class SensorA10(HasIO, Readable): class SensorA10(HasIO, Readable):
ClassIO = ThermFishIO ioClass = ThermFishIO
value = Parameter('internal temperature', unit='degC') value = Parameter('internal temperature', unit='degC')
def get_par(self, cmd):
new_cmd = 'R' + cmd
reply = self.communicate(new_cmd)
if any(unit.isalpha() for unit in reply):
reply = ''.join(unit for unit in reply if not unit.isalpha())
return float(reply)
# def set_par(self, cmd, arg):
# new_cmd = 'S' + cmd.format(arg=arg)
# return self.communicate(new_cmd)
# # return self.get_par(cmd)
def read_value(self): def read_value(self):
return self.communicate('RT') # return the value and the units without space return self.get_par('T')
def set_par(self, cmd): def read_status(self):
result_str = self.communicate('RUFS')
values_str = result_str.strip().split()
values_int = [int(val) for val in values_str]
v1, v2, v3, v4, v5 = values_int[:5]
status_messages = [
(ERROR, 'high tempr. cutout fault', v2, 0),
(ERROR, 'high RA tempr. fault', v2, 1),
(ERROR, 'high temperature fixed fault', v3, 7),
(ERROR, 'low temperature fixed fault', v3, 6),
(ERROR, 'high temperature fault', v3, 5),
(ERROR, 'low temperature fault', v3, 4),
(ERROR, 'low level fault', v3, 3),
(ERROR, 'circulator fault', v4, 5),
(ERROR, 'high press. cutout', v5, 2),
(ERROR, 'motor overloaded', v5, 1),
(ERROR, 'pump speed fault', v5, 0),
(WARN, 'open internal sensor', v1, 7),
(WARN, 'shorted internal sensor', v1, 6),
(WARN, 'high temperature warn', v3, 2),
(WARN, 'low temperature warn', v3, 1),
(WARN, 'low level warn', v3, 0),
(IDLE, 'max. heating', v5, 5),
(IDLE, 'heating', v5, 6),
(IDLE, 'cooling', v5, 4),
(IDLE, 'max cooling', v5, 3),
(IDLE, '', v4, 3),
]
for status_type, status_msg, vi,bit in status_messages:
if vi & (1 << bit):
return status_type, status_msg
return WARN, 'circulation off'
class TemperatureLoopA10(HasConvergence, SensorA10, Drivable):
class TemperatureLoopA10(SensorSC, Drivable):
value = Parameter('temperature', unit='degC') value = Parameter('temperature', unit='degC')
target = Parameter('setpoint', FloatRange, readonly=False) target = Parameter('setpoint/target', datatype=FloatRange, unit='degC', default=0)
p_heat = Parameter('proportional heat parameter', FloatRange(), unit='degC', readonly=False) circ_on = Parameter('is circulation running', BoolType(), readonly=False, default=False)
# pids
p_heat = Parameter('proportional heat parameter', FloatRange(), readonly=False)
i_heat = Parameter('integral heat parameter', FloatRange(), readonly=False) i_heat = Parameter('integral heat parameter', FloatRange(), readonly=False)
d_heat = Parameter('derivative heat parameter', FloatRange(), readonly=False) d_heat = Parameter('derivative heat parameter', FloatRange(), readonly=False)
p_cool = Parameter('proportional cool parameter', FloatRange(), readonly=False) p_cool = Parameter('proportional cool parameter', FloatRange(), readonly=False)
i_cool = Parameter('integral cool parameter', FloatRange(), readonly=False) i_cool = Parameter('integral cool parameter', FloatRange(), readonly=False)
d_cool = Parameter('derivative cool parameter', FloatRange(), readonly=False) d_cool = Parameter('derivative cool parameter', FloatRange(), readonly=False)
setpoint_num = ['', 1, 2, 3, 4, 5] def read_circ_on(self):
return self.communicate('RO')
def write_circ_on(self, circ_on):
circ_on_str = '1' if circ_on else '0'
self.communicate(f'SO {circ_on_str}')
return self.read_circ_on()
def read_target(self): def read_target(self):
return self.communicate(f'RS{self.setpoint_num}') return self.get_par('S')
def write_target(self): def write_target(self, target):
target = self.communicate(f'SS{self.setpoint_num} {self.target}') self.write_circ_on('1')
self.communicate(f'SS {target}')
self.start_state()
return target return target
## heat PID ## heat PID
def read_p_heat(self): def read_p_heat(self):
p_heat = self.communicate(f'RPH') p_heat = self.get_par('PH')
return p_heat return float(p_heat)
def write_p_heat(self, p_heat): def write_p_heat(self, p_heat):
self.communicate(f'SPH {p_heat}') self.communicate(f'SPH {p_heat}')
return self.read_p_heat() return p_heat
def read_i_heat(self): def read_i_heat(self):
i_heat = self.communicate(f'RIH') i_heat = self.get_par('IH')
return i_heat return float(i_heat)
def write_i_heat(self, i_heat): def write_i_heat(self, i_heat):
self.communicate(f'SIH {i_heat}') self.communicate(f'SIH {i_heat}')
return self.read_i_heat() return i_heat
def read_d_heat(self): def read_d_heat(self):
d_heat = self.communicate(f'RDH') d_heat = self.get_par('DH')
return d_heat return float(d_heat)
def write_d_heat(self, d_heat): def write_d_heat(self, d_heat):
self.communicate(f'SDH {d_heat}') self.communicate(f'SDH {d_heat}')
return self.read_d_heat() return d_heat
## cool PID ## cool PID
def read_p_cool(self): def read_p_cool(self):
p_cool = self.communicate(f'RPC') p_cool = self.get_par('PC')
return p_cool return float(p_cool)
def write_p_cool(self, p_cool): def write_p_cool(self, p_cool):
self.communicate(f'SPC {p_cool}') self.communicate(f'SPC {p_cool}')
return self.read_p_cool() return p_cool
def read_i_cool(self): def read_i_cool(self):
i_cool = self.communicate(f'RIC') i_cool = self.get_par('IC')
return i_cool return float(i_cool)
def write_i_cool(self, i_cool): def write_i_cool(self, i_cool):
self.communicate(f'SIC {i_cool}') self.communicate(f'SIC {i_cool}')
return self.read_i_cool() return i_cool
def read_d_cool(self): def read_d_cool(self):
d_cool = self.communicate(f'RDC') d_cool = self.get_par('DC')
return d_cool return float(d_cool)
def write_d_cool(self, d_cool): def write_d_cool(self, d_cool):
self.communicate(f'SDC {d_cool}') self.communicate(f'SDC {d_cool}')
return self.read_d_cool() return d_cool