fixed dilsc, fist try before tests

Change-Id: Iaac5f07c27879c7c17be2e25defde19e9ddd1566
This commit is contained in:
zolliker 2024-04-29 12:18:12 +02:00
parent fcdee8e3ec
commit 17a44ef42a
2 changed files with 295 additions and 64 deletions

231
cfg/dilsc_cfg.py Normal file
View File

@ -0,0 +1,231 @@
Node('cfg/dilsc1.cfg',
'triton test',
interface='5000',
name='dilsc1',
)
Mod('triton',
'frappy_psi.mercury.IO',
'connection to triton software',
uri='tcp://192.168.2.33:33576',
)
Mod('T_mix',
'frappy_psi.triton.TemperatureSensor',
'mix. chamber temperature',
slot='T8',
io='triton',
)
Mod('T_pt2head',
'frappy_psi.triton.TemperatureSensor',
'PTR2 head temperature',
slot='T1',
io='triton',
)
Mod('T_pt2plate',
'frappy_psi.triton.TemperatureSensor',
'PTR2 plate temperature',
slot='T2',
io='triton',
)
Mod('T_still',
'frappy_psi.triton.TemperatureSensor',
'still temperature',
slot='T3',
io='triton',
)
Mod('htr_still',
'frappy_psi.triton.HeaterOutput',
'still heater',
slot='H2',
io='triton',
)
Mod('T_coldpl',
'frappy_psi.triton.TemperatureSensor',
'cold plate temperature',
slot='T4',
io='triton',
)
Mod('T_mixcx',
'frappy_psi.triton.TemperatureSensor',
'mix. chamber cernox',
slot='T5',
io='triton',
)
Mod('T_pt1head',
'frappy_psi.triton.TemperatureSensor',
'PTR1 head temperature',
slot='T6',
io='triton',
)
Mod('T_pt1plate',
'frappy_psi.triton.TemperatureSensor',
'PTR1 plate temperature',
slot='T7',
io='triton',
)
Mod('T_pucksensor',
'frappy_psi.triton.TemperatureLoop',
'puck sensor temperature',
output_module='htr_pucksensor',
slot='TA',
io='triton',
)
Mod('htr_pucksensor',
'frappy_psi.triton.HeaterOutputWithRange',
'mix. chamber heater',
slot='H1,TA',
io='triton',
)
Mod('T_magnet',
'frappy_psi.triton.TemperatureSensor',
'magnet temperature',
slot='T13',
io='triton',
)
Mod('action',
'frappy_psi.triton.Action',
'higher level scripts',
io='triton',
slot='DR',
)
Mod('p_dump',
'frappy_psi.mercury.PressureSensor',
'dump pressure',
slot='P1',
io='triton',
)
Mod('p_cond',
'frappy_psi.mercury.PressureSensor',
'condenser pressure',
slot='P2',
io='triton',
)
Mod('p_still',
'frappy_psi.mercury.PressureSensor',
'still pressure',
slot='P3',
io='triton',
)
Mod('p_fore',
'frappy_psi.mercury.PressureSensor',
'pressure on the pump side',
slot='P5',
io='triton',
)
Mod('p_back',
'frappy_psi.mercury.PressureSensor',
'pressure on the back side of the pump',
slot='P4',
io='triton',
)
Mod('p_ovc',
'frappy_psi.mercury.PressureSensor',
'outer vacuum pressure',
slot='P6',
io='triton',
)
Mod('V1',
'frappy_psi.triton.Valve',
'valve V1',
slot='V1',
io='triton',
)
Mod('V2',
'frappy_psi.triton.Valve',
'valve V2',
slot='V2',
io='triton',
)
Mod('V4',
'frappy_psi.triton.Valve',
'valve V4',
slot='V4',
io='triton',
)
Mod('V5',
'frappy_psi.triton.Valve',
'valve V5',
slot='V5',
io='triton',
)
Mod('V9',
'frappy_psi.triton.Valve',
'valve V9',
slot='V9',
io='triton',
)
Mod('ips',
'frappy_psi.mercury.IO',
'IPS for magnet',
uri='192.168.127.254:3001',
)
Mod('mf',
'frappy_psi.dilsc.VectorField',
'vector field',
x='mfx',
y='mfy',
z='mfz',
sphere_radius=0.6,
cylinders=((0.23, 5.2), (0.45, 0.8)),
)
Mod('mfx',
'frappy_psi.ips_mercury.SimpleField',
'magnetic field, x-axis',
slot='GRPX',
io='ips',
tolerance=0.0001,
wait_stable_field=0.0,
nunits=2,
target=Param(max=0.6),
ramp=0.225,
)
Mod('mfy',
'frappy_psi.ips_mercury.SimpleField',
'magnetic field, y axis',
slot='GRPY',
io='ips',
tolerance=0.0001,
wait_stable_field=0.0,
nunits=2,
target=Param(max=0.6),
ramp=0.225,
)
Mod('mfz',
'frappy_psi.ips_mercury.Field',
'magnetic field, z-axis',
slot='GRPZ',
io='ips',
tolerance=0.0001,
target=Param(max=5.2),
mode='DRIVEN',
ramp=0.52,
)

View File

@ -1,3 +1,4 @@
# -*- coding: utf-8 -*-
# ***************************************************************************** # *****************************************************************************
# This program is free software; you can redistribute it and/or modify it under # This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software # the terms of the GNU General Public License as published by the Free Software
@ -18,79 +19,78 @@
# ***************************************************************************** # *****************************************************************************
"""vector field""" """vector field"""
from frappy.core import Drivable, Done, BUSY, IDLE, WARN, ERROR import math
from frappy.errors import BadValueError from frappy.core import Drivable, Done, BUSY, IDLE, ERROR, Parameter, TupleOf, ArrayOf, FloatRange
from frappy.errors import RangeError
from frappy_psi.vector import Vector from frappy_psi.vector import Vector
from frappy.states import HasStates, Retry, status_code
DECREASE = 1 DECREASE = 1
INCREASE = 2 INCREASE = 2
class VectorField(Vector, Drivable): class VectorField(HasStates, Vector, Drivable):
_state = None sphere_radius = Parameter('max. sphere', datatype=FloatRange(0, 0.7, unit='T'), readonly=True, default=0.6)
cylinders = Parameter('allowed cylinders (list of radius and height)',
datatype=ArrayOf(TupleOf(FloatRange(0, 0.6, unit='T'), FloatRange(0, 5.2, unit='T')), 1, 9),
readonly=True, default=((0.23, 5.2), (0.45, 0.8)))
def doPoll(self): def initModule(self):
"""periodically called method""" super().initModule()
try: # override check_limits of the components with a check for restrictions on the vector
if self._starting: for idx, component in enumerate(self.components):
# first decrease components
driving = False def outer_check(target, vector=self, i=idx, inner_check=component.check_target):
for target, component in zip(self.target, self.components): inner_check(target)
if target * component.value < 0: value = [c.value - math.copysign(c.tolerance, c.value)
# change sign: drive to zero first for c in vector.components]
target = 0 value[i] = target
if abs(target) < abs(component.target): vector._check_limits(value)
if target != component.target:
component.write_target(target) component.check_target = outer_check
if component.isDriving():
driving = True
if driving:
return
# now we can go to the final targets
for target, component in zip(self.target, self.components):
component.write_target(target)
self._starting = False
else:
for component in self.components:
if component.isDriving():
return
self.setFastPoll(False)
finally:
super().doPoll()
def merge_status(self): def merge_status(self):
names = [c.name for c in self.components if c.status[0] >= ERROR] return self.status
if names:
return ERROR, 'error in %s' % ', '.join(names)
names = [c.name for c in self.components if c.isDriving()]
if self._state:
# self.log.info('merge %r', [c.status for c in self.components])
if names:
direction = 'down ' if self._state == DECREASE else ''
return BUSY, 'ramping %s%s' % (direction, ', '.join(names))
if self.status[0] == BUSY:
return self.status
return BUSY, 'driving'
if names:
return WARN, 'moving %s directly' % ', '.join(names)
names = [c.name for c in self.components if c.status[0] >= WARN]
if names:
return WARN, 'warnings in %s' % ', '.join(names)
return IDLE, ''
def write_target(self, value): def _check_limits(self, value):
"""check if value is within one of the safe shapes"""
if sum((v ** 2 for v in value)) <= self.sphere_radius ** 2:
return
for r, h in self.cylinders:
if sum(v ** 2 for v in value[0:2]) <= r ** 2 and abs(value[2]) <= h:
return
raise RangeError('vector %s does not fit in any limiting shape' % repr(value))
def write_target(self, target):
"""initiate target change""" """initiate target change"""
# first make sure target is valid # check limits first
for target, component in zip(self.target, self.components): for component_target, component in zip(target, self.components):
# check against limits if individual components # check against limits of individual components
component.check_limits(target) component.check_target(component_target, vector=None) # no outer check here!
if sum(v * v for v in value) > 1: self._check_limits(target)
raise BadValueError('norm of vector too high') for component_target, component in zip(target, self.components):
self.log.info('decrease') if component_target * component.value < 0:
self.setFastPoll(True) # change sign: drive to zero first
self.target = value component_target = 0
self._state = DECREASE if abs(component_target) > abs(component.value):
self.doPoll() continue # do not drive yet
self.log.info('done write_target %r', value) component.write_target(component_target)
return Done self.start_machine(self.ramp_down, target=target)
return target
@status_code(BUSY)
def ramp_down(self, state):
for target, component in zip(state.target, self.components):
if component.isDriving():
return Retry()
for target, component in zip(state.target, self.components):
component.write_target(target)
return self.final_ramp
@status_code(BUSY)
def final_ramp(self, state):
for component in self.components:
if component.isDriving():
return Retry()
return self.final_status()