From ef5f4cd2f3ea4d5bbcca3fa04e57fc2cd95e846a Mon Sep 17 00:00:00 2001 From: l_samenv Date: Thu, 29 Jun 2023 15:05:18 +0200 Subject: [PATCH] frappy_psi.cryoltd: fixes after frappy upgrade --- cfg/main/flamemag_cfg.py | 53 ++++++++++++++++++++------------ frappy_psi/cryoltd.py | 66 ++++++++++++++++++++++++++-------------- 2 files changed, 77 insertions(+), 42 deletions(-) diff --git a/cfg/main/flamemag_cfg.py b/cfg/main/flamemag_cfg.py index 657e725..2b8b5e1 100644 --- a/cfg/main/flamemag_cfg.py +++ b/cfg/main/flamemag_cfg.py @@ -1,3 +1,8 @@ +Node('flamemag.psi.ch', + 'flame magnet', + interface='tcp://5000' +) + Mod('cio', 'frappy_psi.cryoltd.IO', 'IO to cryo ltd software', @@ -14,6 +19,7 @@ Mod('B', 'frappy_psi.cryoltd.MainField', 'magnetic field', channel='Main', + main='main', constraint=80000.0, target=Param( max=35000.0, @@ -27,6 +33,8 @@ Mod('B', overshoot={'o': 1.0, 't': 180.0}, degauss={'s': 500.0, 'd': 30.0, 'f': 5.0, 't': 120.0}, tolerance=5.0, + wait_switch_on = 30, + wait_switch_off = 30, wait_stable_field=180.0, ) @@ -34,6 +42,7 @@ Mod('Bx', 'frappy_psi.cryoltd.ComponentField', 'magnetic field x component', channel='VMX', + main='main', check_against='B', target=Param( max=200.0, @@ -50,6 +59,7 @@ Mod('By', 'frappy_psi.cryoltd.ComponentField', 'magnetic field y component', channel='VMY', + main='main', check_against='B', target=Param( max=100.0, @@ -66,6 +76,7 @@ Mod('Bz', 'frappy_psi.cryoltd.ComponentField', 'magnetic field z component', channel='VMZ', + main='main', check_against='B', target=Param( max=100.0, @@ -82,130 +93,132 @@ Mod('compressorA', 'frappy_psi.cryoltd.Compressor', 'compressor A', channel='A', + main='main', ) Mod('compressorB', 'frappy_psi.cryoltd.Compressor', 'compressor B', channel='B', + main='main', ) Mod('T_stage1_A', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='1st Stage A', main='main', ) Mod('T_stage2_A', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='2nd Stage A', main='main', ) Mod('T_stage1_B', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='1st Stage B', main='main', ) Mod('T_stage2_B', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='2nd Stage B', main='main', ) Mod('T_top_A', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Inner Magnet A (Top)', main='main', ) Mod('T_bottom_A', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Inner Magnet A (Bottom)', main='main', ) Mod('T_top_B', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Inner Magnet B (Top)', main='main', ) Mod('T_bottom_B', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Inner Magnet B (Bottom)', main='main', ) Mod('T_Z_shim', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Z Shim Former', main='main', ) Mod('T_XY_shim', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='XY Shim Former', main='main', ) Mod('T_XY_vector', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='XY Vector Former', main='main', ) Mod('T_radiation_shield', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Radiation Shield', main='main', ) Mod('T_persistent_joints', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Persistent Joints', main='main', ) Mod('T_outer_A', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Outer Magnet A', main='main', ) Mod('T_outer_B', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Outer Magnet B', main='main', ) Mod('T_shim_B', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Z Shim Former B', main='main', ) Mod('T_bore_shield', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Bore Radiation Shield', main='main', ) Mod('T_XYZ_shim', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='XYZ Shim Plate', main='main', ) Mod('T_Z_shim_switch', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Z Shim Switch', main='main', ) Mod('T_main_switch', - 'frappy_psi.cryoltd.Temperature', + 'frappy_psi.cryoltd.Temperature', '', channel='Main Coil Switch', main='main', ) diff --git a/frappy_psi/cryoltd.py b/frappy_psi/cryoltd.py index 605cdff..135dba5 100644 --- a/frappy_psi/cryoltd.py +++ b/frappy_psi/cryoltd.py @@ -28,12 +28,12 @@ changed from the client is fixed for at least 10 seconds. """ import re import time +from math import copysign from frappy.core import HasIO, StringIO, Readable, Drivable, Parameter, Command, \ - Module, Property, Attached, Enum, IDLE, BUSY, ERROR, Done + Module, Property, Attached, Enum, IDLE, BUSY, ERROR from frappy.errors import ConfigError, BadValueError, HardwareError from frappy.datatypes import FloatRange, StringType, EnumType, StructOf from frappy.states import HasStates, status_code, Retry -from frappy.features import HasTargetLimits import frappy_psi.magfield as magfield # floating point value followed with unit @@ -128,7 +128,7 @@ class Main(HasIO, Module): class Channel: - main = Attached(Main, default='main') + main = Attached(Main) channel = Property('channel name', StringType()) pollinterval = Parameter(export=False) block_until = None @@ -199,7 +199,7 @@ PersistencyMode = Enum( ) -class BaseMagfield(HasStates, HasTargetLimits, Channel): +class BaseMagfield(HasStates, Channel): _status_text = '' _ready_text = '' _error_text = '' @@ -214,13 +214,13 @@ class BaseMagfield(HasStates, HasTargetLimits, Channel): dt = self.parameters['target'].datatype if dt.min < 1e-99: # make limits symmetric dt.min = - dt.max - min_, max_ = self.target_limits - self.target_limits = [max(min_, dt.min), min(max_, dt.max)] + # min_, max_ = self.target_limits + # self.target_limits = [max(min_, dt.min), min(max_, dt.max)] dt = self.parameters['ramp'].datatype if self.ramp == 0: # unconfigured: take max. self.ramp = dt.max if not isinstance(self, magfield.Magfield): - # add unneeded attributes, as the appear in GetAll + # add unneeded attributes, as they appear in GetAll self.switch_heater = None self.current = None @@ -263,7 +263,7 @@ class BaseMagfield(HasStates, HasTargetLimits, Channel): setpoint=('_Setpoint', self.to_gauss), switch_heater=('_Heater', self.cvt_switch_heater), cs_mode=('_Persistent Mode', self.cvt_cs_mode), - approach_mode=('_Approach', self.cvt_approach_mode), + # no readback: approach_mode=('_Approach', self.cvt_approach_mode), ) def cvt_error(self, text): @@ -297,13 +297,14 @@ class BaseMagfield(HasStates, HasTargetLimits, Channel): def write_target(self, target): self.reset_error() super().write_target(target) - return Done + return target def start_sweep(self, target): if self.approach_mode == self.approach_mode.OVERSHOOT: - o = self.overshoot['o'] - if (target - self.value) * o < 0: - self.write_overshoot(dict(self.overshoot, o=-o)) + sign = copysign(1, target - self.value) * copysign(1, target) + oval = copysign(self.overshoot['o'], sign) + tval = self.overshoot['t'] + self.sendcmd('Set::SetOvershoot %g,%g' % (oval, tval)) self.write_ramp(self.ramp) if self.hw_units == 'A': self.sendcmd('Set::Sweep %gA' % (target / self.A_to_G)) @@ -331,6 +332,8 @@ class BaseMagfield(HasStates, HasTargetLimits, Channel): # wait for overshoot/degauss/cycle sm.stabilize_start = sm.now return Retry + if sm.stabilize_start is None: + sm.stabilize_start = sm.now if sm.now - sm.stabilize_start < self.wait_stable_field: return Retry return self.end_stablilize @@ -368,18 +371,19 @@ class BaseMagfield(HasStates, HasTargetLimits, Channel): self.block('approach_mode') return value - @classmethod - def cvt_approach_mode(cls, text): - return cls.ApproachMode(text.upper()) + # no readback: + # @classmethod + # def cvt_approach_mode(cls, text): + # return cls.ApproachMode(text.upper()) overshoot = Parameter('overshoot [%] and hold time [s]', - StructOf(o=FloatRange(-100, 100, unit='%'), t=FloatRange(0, unit='s')), + StructOf(o=FloatRange(0, 100, unit='%'), t=FloatRange(0, unit='s')), readonly=False, default=dict(o=0, t=0), group='approach_settings') - def write_overshoot(self, value): - self.sendcmd('Set::SetOvershoot %g,%g' % (value['o'], value['t'])) - return value + #def write_overshoot(self, value): + # self.sendcmd('Set::SetOvershoot %g,%g' % (value['o'], value['t'])) + # return value cycle = Parameter('start value, damping factor, final value, hold time', StructOf(s=FloatRange(-100, 100, unit='%'), @@ -458,26 +462,36 @@ class MainField(BaseMagfield, magfield.Magfield): def write_mode(self, mode): self.reset_error() super().write_mode(mode) # updates mode - return Done + return mode @status_code('PREPARING') def start_ramp_to_field(self, sm): + self.sendcmd('Set::SetApproach 0') # direct mode self.start_sweep(self.value) return self.ramp_to_field # -> stabilize_current -> start_switch_on @status_code('PREPARING') def start_switch_on(self, sm): self.write_cs_mode(CsMode.DRIVEN) + self.sendcmd('Set::SetApproach 0') # direct mode # self.block('switch_heater', 1, 60) self.start_sweep(self.value) self.block('_ready_text', 'FALSE') + # self.switch_on_time = sm.now # not needed? don ein update_switch_heater return self.wait_for_switch_on # -> start_ramp_to_target -> ramp_to_target -> stabilize_field + wait_switch_on = Parameter('minimum time to wait for opening switch') + @status_code('PREPARING') def wait_for_switch_on(self, sm): + if self.switch_on_time is None: + self.switch_on_time = sm.now + if sm.now - self.switch_on_time < self.wait_switch_on: + return Retry if self._ready_text == 'FALSE': return Retry - self.last_target(sm.target) + self._last_target = sm.target + self.sendcmd('Set::SetApproach %d' % self.approach_mode) return self.start_ramp_to_target def end_stablilize(self, sm): @@ -491,16 +505,24 @@ class MainField(BaseMagfield, magfield.Magfield): self.write_cs_mode(CsMode.SEMIPERSISTENT) else: # PERSISTENT or DISABLED self.write_cs_mode(CsMode.PERSISTENT) + self.sendcmd('Set::SetApproach 0') # direct mode self.start_sweep(sm.target) self.block('_ready_text', 'FALSE') self.block('switch_heater', 1) + self.switch_off_time = sm.now return self.wait_for_switch_off # -> start_ramp_to_zero + wait_switch_off = Parameter('minimum time to wait for closing switch') + @status_code('PREPARING') def wait_for_switch_off(self, sm): + if self.switch_off_time is None: + self.switch_off_time = sm.now + if sm.now - self.switch_off_time < self.wait_switch_off: + return Retry if self.switch_heater: return Retry - self.last_target(sm.target) + self._last_target = sm.target if self.mode == PersistencyMode.SEMIPERSISTENT: return self.final_status(IDLE, 'semipersistent') return self.ramp_to_zero